Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

EcaFaYn!

Frischling

  • »EcaFaYn!« ist der Autor dieses Themas

Beiträge: 62

Wohnort: NRW

Beruf: Azubi + Student

  • Private Nachricht senden

1

12.04.2009, 17:02

GELÖST: Verzögerung bei Tastendruck

Moin allerseits,
ich hab mich heute erst hier angemeldet und schon mal überall umgeschaut,
aber sowas wie ein Ort wo man sich vorstellt o.ä. habe ich nicht gefunden ...
Hätte ich ganz nett gefunden aber vielleicht braucht man sowas in einem Programmierforum nicht :D
Dann lege ich mal einfach los mit einem Problem, dass mich derzeit plagt.
Und nicht böse sein, falls ein offensichtlicher Fehler dahinter steckt, die Schule hat mich zu einer langen Pause vom Programmieren gezwungen und deswegen bin ich ziemlich aus der Übung ;)

Los geht's: Um wieder ein bisschen reinzukommen (in C++ und OpenGL), habe ich mich mal an einer Abwandlung des Spieles Snake versucht.
Zunächst habe ich mich nicht um den Rahmen oder die Struktur mit Klassen für die Spieler usw. gekümmert, sondern erstmal ganz elementar überlegt, wie eine gesteuerte Schlange überhaupt realisierbar ist.

Letztendlich bin ich bei diesem Code angekommen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
#define WIN32_LEAN_AND_MEAN     //trim the excess fat from Windows


//Includes

#include <windows.h>            //standard Windows app include

#include <gl/gl.h>              //standard OpenGL include

#include <gl/glu.h>             //OpenGL utilities

#include <gl/glaux.h>           //OpenGL auxiliary functions


#include <ctype.h>            // for special functions like toupper()

#include <math.h>             //math operations like sinus


//------------------------------------------------------------------------


//Global variables


HDC g_HDC;                      //global device context

bool fullScreen = true;         //start off in full-screen mode


bool Cleared = false;

const int DELAY_TIME = 25;

  double x;                      //x position

  double y;                      //y position

  double angle;                //angle of the snakes "head"

  
  //delay timers               

  int act_timer;
  int std_timer;
  
  int score;

//------------------------------------------------------------------------


//function to set the pixel format for the device context

void SetupPixelFormat(HDC hDC)
{
     int nPixelFormat;          //your pixel format index

     
     static PIXELFORMATDESCRIPTOR pfd = {
            sizeof(PIXELFORMATDESCRIPTOR),          //size of structure

            1,                                      //version, always set to 1

            PFD_DRAW_TO_WINDOW |                    //support window

            PFD_SUPPORT_OPENGL |                    //support OpenGL

            PFD_DOUBLEBUFFER,                       //support double buffering

            PFD_TYPE_RGBA,                          //RGBA color mode

            32,                                     //go for 32 bit color mode

            0, 0, 0, 0, 0, 0,                     //ignore color bits, not used

            0,                                      //no alpha buffer

            0,                                      //ignore shift bit

            0,                                      //no accumilation buffer

            0, 0, 0, 0,                             //ignore accumilation bits

            16,                                     //16-bit z-buffer size

            0,                                      //no stencil buffer

            0,                                      //no auxiliary buffer

            PFD_MAIN_PLANE,                         //main draw plane

            0,                                      //reserved

            0, 0, 0 };                              //layer masks ignored


     //choose best matching pixel format, return index

     nPixelFormat = ChoosePixelFormat(hDC, &pfd);

     //set pixel format to device context

     SetPixelFormat(hDC, nPixelFormat, &pfd);
}

//the Windows Procedure event handler

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        static HGLRC hRC;                   //rendering context

        static HDC hDC;                     //device context

        int width, height;                  //window width and height

        
        switch (message)
        {
               case WM_CREATE:              //window is being created

               hDC = GetDC(hwnd);         //get current window's device context

               g_HDC = hDC;                 
               SetupPixelFormat(hDC);   //call your pixel format setup function

               
               //create rendering context and make it current 

               hRC = wglCreateContext(hDC); 
               wglMakeCurrent(hDC, hRC);    
               return 0;                    
               break;                       
                                            
               case WM_CLOSE:               //window is closing

               //deselect rendering context and delete it

               wglMakeCurrent(hDC, NULL);
               wglDeleteContext(hRC);
               
               //send WM_QUIT to message queue

               PostQuitMessage(0);

               return 0;
               break;
               
               case WM_SIZE:
               height = HIWORD(lParam);       //retrieve width and height

               width = LOWORD(lParam);  
               
               if (height == 0)               //don't want a divide by zero

               {
               height = 1;
               }
               
               //reset the viewport to new dimensions

               glViewport(0, 0, width, height);
               glMatrixMode(GL_PROJECTION);     //set projection matrix

               glLoadIdentity();               //reset projection matrix

               
               //calculate aspect ratio of window

        gluPerspective(45.0f, (GLfloat)width/(GLfloat)height, 1.0f, 1000.0f);
               
               glMatrixMode(GL_MODELVIEW);     //set modelview matrix

               glLoadIdentity();               //reset modelview matrix

               
               return 0;
               break;
               
               case WM_CHAR:
               {
                 switch (toupper(wParam))
                 {

                   case '1':                               //to the left

                   {  
                   if (act_timer == 0)
                   {
                     act_timer = DELAY_TIME;
                     angle += 0.05;
                   }
                   }break; 
                   
                   case 'Q':                               //to the right

                   {
                   if (act_timer == 0)
                   {
                     act_timer = DELAY_TIME;
                     angle -= 0.05;
                   }
                   }break;
                   
                   default:
                   break;
                 }
               }
               default:
               break;
        }    
        
        return (DefWindowProc(hwnd, message, wParam, lParam));
}

//the main Windows entry point

int WINAPI WinMain (HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpCmdLine,
                    int nShowCmd)
{
    WNDCLASSEX windowClass; 
    HWND hwnd;                      //window handle  

    MSG msg;                        //message

    bool done;                      //flag saying when your app is complete                   

    
    //fill out the window class structure

    windowClass.cbSize          = sizeof(WNDCLASSEX);
    windowClass.style           = CS_HREDRAW | CS_VREDRAW;
    windowClass.lpfnWndProc     = WndProc;
    windowClass.cbClsExtra      = 0;
    windowClass.cbWndExtra      = 0;
    windowClass.hInstance       = hInstance;
    windowClass.hIcon           = LoadIcon(NULL, IDI_APPLICATION);//default icon

    windowClass.hCursor         = LoadCursor(NULL, IDC_ARROW);  //default arrow

    windowClass.hbrBackground   = NULL;
    windowClass.lpszMenuName    = NULL;
    windowClass.lpszClassName   = "MyClass";
    windowClass.hIconSm         = LoadIcon(NULL, IDI_WINLOGO);  //small icon

    
    //register the window class

    if (!RegisterClassEx(&windowClass))
    return 0;
    
    //class registered, so now create your window

    hwnd = CreateWindowEx(NULL,                              //extended style

                          "MyClass",                         //class name

                          "The OpenGL Window Application",   //app name

                          WS_OVERLAPPEDWINDOW | WS_VISIBLE | //style

                          WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
                          100, 100,                          //x, y coordinate

                          500, 500,                          //width, height

                          NULL,                              //handle to parent

                          NULL,                              //handle to menu

                          hInstance,                     //application instance

                          NULL);                             //no extra params

    
    //check if window creation failed (hwnd would equal NULL)

    if (!hwnd)
    return 0;
    
    ShowWindow(hwnd, SW_SHOW);         //display the window

    UpdateWindow(hwnd);                //update the window

    
    done = false;                      //initialize the loop condition variable

    
    //main message loop

    while (!done)
    {
          PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE);
          
          if (msg.message == WM_QUIT)   //do you receive a WM_QUIT message?

          {
          done = true;                  //if so, time to quit the application

          }
          else
          {                             //do rendering here

          //clear screen and depth buffer

          if (Cleared == false) //temporary prevention of clearing the screen

          glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
          Cleared = true;
          
          glLoadIdentity();           //reset modelview matrix

          //-------------------------------------------------------------------

          
          glPointSize(5);
          glLineWidth(5);
          
          glTranslatef(0.0f, 0.0f, -10.0f);
          
          glColor3f(1.0f, 0.0f, 0.0f);        //set color to red

          
          glBegin(GL_POINTS);              //draw point

              glVertex3f(x, y, 0);
          glEnd();
          
          if (angle >= 360.0f || angle <= -360.0f)        //reset angle counter

          angle = 0.0f;
          
          if (std_timer == DELAY_TIME)
          {
          std_timer = 0;
          x += (cos(angle)) * 0.05; //get new x value using angle functions

          y += (sin(angle)) * 0.05; //get new y value using angle functions

          }
          
          if (act_timer > 0)
          act_timer--;
          
          std_timer++;
          Sleep(1);
          
          //-------------------------------------------------------------------

          
          SwapBuffers(g_HDC);                 //bring back buffer to foreground

          
          TranslateMessage(&msg);           //translate/dispatch to event queue

          DispatchMessage(&msg);      
          }
    }
    
    return msg.wParam;
}


Das Problem ist nun (abgesehen von der spärlichen Kommentierung, die ich noch nachhole :D) dass, wenn man "1" und "Q" schnell hintereinander drückt, die "Schlange" sehr lange braucht, bis sie reagiert und in die entsprechende Richtung - die Taste, die zuletzt gedrückt wurde - abbiegt. Ich vermute mal, dass dies irgendwie mit dem Message Handler zu tun haben muss, oder nicht? Vielleicht fragt dieser nicht schnell genug ab, um alle Anschläge zu registrieren oder dergleichen. Ich habe momentan nur keine Ahnung, wie man dieses Problem lösen kann - ihr vielleicht?

Pfew, langer Post, nicht wahr? Aber es gibt so viel zu erzählen ;) Also, falls Fragen offen sind, nicht zögern - ich kann, auch förmlich, ja nicht beim ersten Mal alles richtig machen :p

Gruß, EcaFaYn!
On the grind - Supersci

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

2

12.04.2009, 17:20

Ja genau, das liegt an deiner Eingabe Verarbeitung. Nimm dafür nicht den Messagehandler sondern Poll die Tasten (z.B. per GetAsyncKeyState) oder nimm DirectInput.

3

12.04.2009, 17:35

Hi EcaFaYn!

Frohe Ostern und Willkommen im Forum! :)

Einen Vorstellungsthread findet du unter Offtopic (dritter von oben).

Bitte demnächst für C++ - Code entsprechende Tags verwenden. ;)
Hab das mal für dich erledigt.
fka tm

EcaFaYn!

Frischling

  • »EcaFaYn!« ist der Autor dieses Themas

Beiträge: 62

Wohnort: NRW

Beruf: Azubi + Student

  • Private Nachricht senden

4

12.04.2009, 18:21

@ TrikkieMikkie:
Unfassbar! Ich muss mit Blindheit geschlagen gewesen sein :D Ist immer schlauer, sich die ganze Button-Leiste anzusehen - und in der Offtopic-Abteilung hab ich einen Vorstellthread irgendwie nicht vermutet, nun ja, jetzt bin ich schlauer :p Dann werde ich mich doch gleich als nächstes Mal ums Vorstellen kümmern.
Oh, und natürlich auch dir Frohe Ostern! xD

@David_pb:
Besten Dank! Ich habe das jetzt mal mit GetAsyncKeyState umgesetzt und es funktioniert nun ohne Verzögerung, danke für den Tipp. Um DirectInput werde ich mich später noch ausgiebig kümmern, wenn ich in meinem OpenGL-Buch ("OpenGL Game Programming" von Hawkins und Astle, kennt ihr vielleicht) an dem entsprechenden Kapitel angekommen bin ;) .
Nur der Neugier halber, ist die Stelle, an der ich die Funktion eingesetzt habe, sinnvoll (abgesehen davon, dass man es bei fortgeschrittener Programmentwicklung evtl. in Funktionen verpackt)? Also in diese Endlosschleife?

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
#define WIN32_LEAN_AND_MEAN     //trim the excess fat from Windows


//Includes

#include <windows.h>            //standard Windows app include

#include <gl/gl.h>              //standard OpenGL include

#include <gl/glu.h>             //OpenGL utilities

#include <gl/glaux.h>           //OpenGL auxiliary functions


#include <ctype.h>            // for special functions like toupper()

#include <math.h>             //math operations like sinus


//Global variables

HDC g_HDC;                      //global device context

bool fullScreen = true;         //start off in full-screen mode


bool Cleared = false;

const int DELAY_TIME = 25;

  double x;
  double y;
  double angle;
  
  //delay timers

  int act_timer;
  int std_timer;
  
  int score;

//Classes          

//------------------------------------------------------------------------

class Player
{
  private:
  //player's position in map array

  double x;
  double y;
  double angle;
  
  //delay timers

  int act_timer;
  int std_timer;
  
  int score;
  
  public:
  
         
};
//------------------------------------------------------------------------

class Map
{
  protected:        
  public:
  void Rotate();
};
//------------------------------------------------------------------------


//function to set the pixel format for the device context

void SetupPixelFormat(HDC hDC)
{
     int nPixelFormat;          //your pixel format index

     
     static PIXELFORMATDESCRIPTOR pfd = {
            sizeof(PIXELFORMATDESCRIPTOR),          //size of structure

            1,                                      //version, always set to 1

            PFD_DRAW_TO_WINDOW |                    //support window

            PFD_SUPPORT_OPENGL |                    //support OpenGL

            PFD_DOUBLEBUFFER,                       //support double buffering

            PFD_TYPE_RGBA,                          //RGBA color mode

            32,                                     //go for 32 bit color mode

            0, 0, 0, 0, 0, 0,                     //ignore color bits, not used

            0,                                      //no alpha buffer

            0,                                      //ignore shift bit

            0,                                      //no accumilation buffer

            0, 0, 0, 0,                             //ignore accumilation bits

            16,                                     //16-bit z-buffer size

            0,                                      //no stencil buffer

            0,                                      //no auxiliary buffer

            PFD_MAIN_PLANE,                         //main draw plane

            0,                                      //reserved

            0, 0, 0 };                              //layer masks ignored


     //choose best matching pixel format, return index

     nPixelFormat = ChoosePixelFormat(hDC, &pfd);

     //set pixel format to device context

     SetPixelFormat(hDC, nPixelFormat, &pfd);
}

//the Windows Procedure event handler

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        static HGLRC hRC;                   //rendering context

        static HDC hDC;                     //device context

        int width, height;                  //window width and height

        
        switch (message)
        {
               case WM_CREATE:              //window is being created

               hDC = GetDC(hwnd);         //get current window's device context

               g_HDC = hDC;                 
               SetupPixelFormat(hDC);   //call your pixel format setup function

               
               //create rendering context and make it current 

               hRC = wglCreateContext(hDC); 
               wglMakeCurrent(hDC, hRC);    
               return 0;                    
               break;                       
                                            
               case WM_CLOSE:               //window is closing

               //deselect rendering context and delete it

               wglMakeCurrent(hDC, NULL);
               wglDeleteContext(hRC);
               
               //send WM_QUIT to message queue

               PostQuitMessage(0);

               return 0;
               break;
               
               case WM_SIZE:
               height = HIWORD(lParam);       //retrieve width and height

               width = LOWORD(lParam);  
               
               if (height == 0)               //don't want a divide by zero

               {
               height = 1;
               }
               
               //reset the viewport to new dimensions

               glViewport(0, 0, width, height);
               glMatrixMode(GL_PROJECTION);     //set projection matrix

               glLoadIdentity();               //reset projection matrix

               
               //calculate aspect ratio of window

        gluPerspective(45.0f, (GLfloat)width/(GLfloat)height, 1.0f, 1000.0f);
               
               glMatrixMode(GL_MODELVIEW);     //set modelview matrix

               glLoadIdentity();               //reset modelview matrix

               
               return 0;
               break;
               
               default:
               break;
        }    
        
        return (DefWindowProc(hwnd, message, wParam, lParam));
}

//the main Windows entry point

int WINAPI WinMain (HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpCmdLine,
                    int nShowCmd)
{
    WNDCLASSEX windowClass; 
    HWND hwnd;                      //window handle  

    MSG msg;                        //message

    bool done;                      //flag saying when your app is complete                   

    
    //fill out the window class structure

    windowClass.cbSize          = sizeof(WNDCLASSEX);
    windowClass.style           = CS_HREDRAW | CS_VREDRAW;
    windowClass.lpfnWndProc     = WndProc;
    windowClass.cbClsExtra      = 0;
    windowClass.cbWndExtra      = 0;
    windowClass.hInstance       = hInstance;
    windowClass.hIcon           = LoadIcon(NULL, IDI_APPLICATION);//default icon

    windowClass.hCursor         = LoadCursor(NULL, IDC_ARROW);  //default arrow

    windowClass.hbrBackground   = NULL;
    windowClass.lpszMenuName    = NULL;
    windowClass.lpszClassName   = "MyClass";
    windowClass.hIconSm         = LoadIcon(NULL, IDI_WINLOGO);  //small icon

    
    //register the window class

    if (!RegisterClassEx(&windowClass))
    return 0;
    
    //class registered, so now create your window

    hwnd = CreateWindowEx(NULL,                              //extended style

                          "MyClass",                         //class name

                          "The OpenGL Window Application",   //app name

                          WS_OVERLAPPEDWINDOW | WS_VISIBLE | //style

                          WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
                          100, 100,                          //x, y coordinate

                          500, 500,                          //width, height

                          NULL,                              //handle to parent

                          NULL,                              //handle to menu

                          hInstance,                     //application instance

                          NULL);                             //no extra params

    
    //check if window creation failed (hwnd would equal NULL)

    if (!hwnd)
    return 0;
    
    ShowWindow(hwnd, SW_SHOW);         //display the window

    UpdateWindow(hwnd);                //update the window

    
    done = false;                      //initialize the loop condition variable

    
    //main message loop

    while (!done)
    {
          PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE);
          
          if (msg.message == WM_QUIT)   //do you receive a WM_QUIT message?

          {
          done = true;                  //if so, time to quit the application

          }
          else
          {                             //do rendering here

          //clear screen and depth buffer

          if (Cleared == false) //temporary prevention of clearing the screen

          glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
          Cleared = true;
          
          glLoadIdentity();           //reset modelview matrix

          //-------------------------------------------------------------------

          
          glPointSize(5);
          glLineWidth(5);
          
          glTranslatef(0.0f, 0.0f, -10.0f);
          
          glColor3f(1.0f, 0.0f, 0.0f);        //set color to red

          
          glBegin(GL_POINTS);              //draw point

              glVertex3f(x, y, 0);
          glEnd();
          //Input:-------------------------------------------------------------

          
          if (GetAsyncKeyState(0x31))        // "1" pressed?

          {
             if (act_timer == 0)
             {
             act_timer = DELAY_TIME;
             angle += 0.05;
             }
          }
          
          if (GetAsyncKeyState(0x51))        // "Q" pressed?

          {
             if (act_timer == 0)
             {
             act_timer = DELAY_TIME;
             angle -= 0.05;
             }
          }
          
          //------------------------------------------------------------------- 

          
          if (angle >= 360.0f || angle <= -360.0f)        //reset angle counter

          angle = 0.0f;
          
          if (std_timer == DELAY_TIME)
          {
          std_timer = 0;
          x += (cos(angle)) * 0.05; //get new x value using angle functions

          y += (sin(angle)) * 0.05; //get new y value using angle functions

          }
          
          if (act_timer > 0)
          act_timer--;
          
          std_timer++;
          Sleep(1);
          
          //-------------------------------------------------------------------

          
          SwapBuffers(g_HDC);                 //bring back buffer to foreground

          
          TranslateMessage(&msg);           //translate/dispatch to event queue

          DispatchMessage(&msg);      
          }
    }
    
    return msg.wParam;
}


Gruß, EcaFaYn!
On the grind - Supersci

Werbeanzeige