"Skidding"
I am experiencing something a little perculiar. I am using the key capture method in many of Nehes examples (i.e. not DX, which I cant use for reasons I wont bore you with). When one presses the up key, they move forward. All well and good. But when they release it, they keep moving for a little before stopping. The longer they hold the key down, the longer the "skidding" goes on for. Its drastically reduced (but not totally eliminated) on faster machines, so it would appear to be linked with framerate, but why am I having this problem at all? Other projects with similar or greater graphical output dont have this prob. Outputing stuff to the screen shows the program thinks the button is just being held down longer than it is.
Any suggestions as to what I could do to solve this, or even track down exactly why it happens, would be greatly appreciated...
Thanks
zoidy
September 15, 2003 03:53 PM
If you are using a message handler, you are only calling it every frame. So therefore, if you are in the middle of a frame and you press a key, it will take until the next frame for the computer to notice.
Thank you, but if I understand you correctly I dont think thats it. As I say, the problem gets worse the longer you hold the button down. The mouse input still seems to work real-time (movement, rather than buttons) so I have actually been able to release the up button and still been able to steer around corners for a few seconds before the release key was acknowledged and the player came to a stop.
Could it be anything else?
Thanks
zoidy
Could it be anything else?
Thanks
zoidy
1. IF it's only a tiny tiny delay it could be a psycological effect.
Your reaction time is about 0.2 seconds, where you command your finger to release the button and 0.2 seconds later you see it happen.
2. the keyboard could have a small delay.
This is not realy a problem, if you add a small acceleration factor to your movements you will have much smoother movement's and this delay that's bugging you will allso not be as apparent as before.
Allso add filers to your mouse movements and your fps counter, the latter one gave me mutch nicer fps numbers(from 15 to 300).
or there may be way to mutch cola in your keyboard.
[edited by - lc_overlord on September 16, 2003 4:42:13 PM]
Your reaction time is about 0.2 seconds, where you command your finger to release the button and 0.2 seconds later you see it happen.
2. the keyboard could have a small delay.
This is not realy a problem, if you add a small acceleration factor to your movements you will have much smoother movement's and this delay that's bugging you will allso not be as apparent as before.
Allso add filers to your mouse movements and your fps counter, the latter one gave me mutch nicer fps numbers(from 15 to 300).
or there may be way to mutch cola in your keyboard.
[edited by - lc_overlord on September 16, 2003 4:42:13 PM]
www.flashbang.se | www.thegeekstate.com | nehe.gamedev.net | glAux fix for lesson 6 | [twitter]thegeekstate[/twitter]
How are you converting key stroke into motion? Do you use any sort of physics engine? I am developing with a physics engine where the skidding is intentional because of momentum, friction, etc.
variant: basically, when a key is pressed:
xpos += (float)sin(heading*piover180) * MoveDistance;
where MoveDistance is 0.75 and xpos is the position in the level. Obviously that is altered depending on the key in question. So no, there is no kind of physics engine. If the time didnt change so much I might try to claim it was a physics thing though!
lc_overlord: well, the delay has been up to about 12 seconds on my slower computer, and at the time the framerate was about 10-15. Pretty noticable.
And... sorry if I am being dense, but I am not sure what you mean by "add filers to your mouse movements and your fps counter". Could you explain please?
Thanks
zoidy
xpos += (float)sin(heading*piover180) * MoveDistance;
where MoveDistance is 0.75 and xpos is the position in the level. Obviously that is altered depending on the key in question. So no, there is no kind of physics engine. If the time didnt change so much I might try to claim it was a physics thing though!

lc_overlord: well, the delay has been up to about 12 seconds on my slower computer, and at the time the framerate was about 10-15. Pretty noticable.
And... sorry if I am being dense, but I am not sure what you mean by "add filers to your mouse movements and your fps counter". Could you explain please?
Thanks
zoidy
MY bad that should be filters not filers, basicly you take the last 5-10 values, add them together and then divide by 5-10(you should know how this works).
From what you have said it seams to me that it waits for a certain number of frames before reacting.
THis is odd, so could you please send some code concerning the keychacking ,movement and related.
sidenote: You don''t seem to have some kind of "frame time" value in that movement algo.
movedistance should realy be (30/frametime) instead of just 0.75.
Idon''t think that is the problem though, but youll get a constant speed while moving no matter what your fps
From what you have said it seams to me that it waits for a certain number of frames before reacting.
THis is odd, so could you please send some code concerning the keychacking ,movement and related.
sidenote: You don''t seem to have some kind of "frame time" value in that movement algo.
movedistance should realy be (30/frametime) instead of just 0.75.
Idon''t think that is the problem though, but youll get a constant speed while moving no matter what your fps
www.flashbang.se | www.thegeekstate.com | nehe.gamedev.net | glAux fix for lesson 6 | [twitter]thegeekstate[/twitter]
Ok. I have played about, and randomly changed stuff, but to be honest, I am not sure why it is acting like this. As I understand things, I should be getting what the illustrious Anonymous Poster said, i.e. it should only take until the next frame until input is processed. I dont see why it takes multiple frames. Below is (slightly abbreviated, but hopefully still fully understandable, and only unimoprtant things are taken out) code. If anyone can suggest anything, please let me know...
For those of you who waded through that thank you. I hope inspiration strikes.
For those of you who didnt, another puzzler. In fullscreen, textures work fine. However, in a window they are all distorted and jagged, as if at regular intervals it is being pulled in opposite directions. Any ideas?
Thanks...
zoidy
typedef struct { // Contains information vital to a window HWND hWnd; // Window handle HDC hDC; // Device context HGLRC hRC; // Rendering context HINSTANCE hInstance; // Application instance const char* className; // Application class name char* title; // Window title int width; // Width int height; // Height int bits; // Bits per pixel bool FullScreen; // Are we running in fullscreen?} BC_WindowData; // GL_Window//// Global VarsBC_WindowData Win;bool KeyPressed [256];bool PreviousKeys [256];GLuint base;bool CreateWindow = TRUE;float MoveDistance = 1.750;float heading=90;const float piover180 = 0.0174532925f;float lookupdown = 0.0f;float Timer;//FRAME COUNTER CODE: for debugging / optimisingstatic FLOAT fps = 0.0f;static FLOAT last_time = 0.0f;static DWORD frames = 0L;float times;// END// Initialises stuff for the programvoid Initialise (void){ // **** Load and create font **** glDepthFunc (GL_LEQUAL); // Less or equal depth testing glEnable (GL_DEPTH_TEST); // Enable depth testing SetCursorPos(320,240); // Set the mouse position as the centre of the window}void TerminateWindow (HWND hwnd){ // **** Delete font **** // **** Release device context etc ****}// Functions to set the pixel format for the device contextvoid SetupPixelFormat (HDC hDC){ int nPixelFormat; // Pixel Format Index static PIXELFORMATDESCRIPTOR pfd = { sizeof (PIXELFORMATDESCRIPTOR), // size of structure 1, // version, always ''1'' PFD_DRAW_TO_WINDOW | // support window PFD_SUPPORT_OPENGL | // support opengl PFD_DOUBLEBUFFER, // support double buffering PFD_TYPE_RGBA, 32, // 32 bit colour mode 0, 0, 0, 0, 0, 0, // ignore colour bits 0, // no alpha buffer 0, // ignore shift bit 0, // no accumulation buffer 0, 0, 0, 0, // ignore accumulation bits 16, // 16 bit z-buffer size 0, // no stencil buffer 0, // no auxiliary buffer PFD_MAIN_PLANE, // main drawing 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 handlerLRESULT 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_SYSCOMMAND: // Intercept system commands { switch (wParam) // Check system calls { case SC_SCREENSAVE: // Screensaver trying to start? case SC_MONITORPOWER: // Monitor trying to enter powersave? return 0; // Prevent from happening } break; // Exit } return 0; // Return case WM_CREATE: // window is being created hDC = GetDC (hwnd); // get current windows device context Win.hDC = hDC; SetupPixelFormat (hDC); // create rendering context and make it current hRC = wglCreateContext (hDC); wglMakeCurrent (hDC, hRC); return 0; break; case WM_CLOSE: // window is closing // send WM_QUIT to message queue PostQuitMessage (0); return 0; break; case WM_SIZE: height = HIWORD (lParam); width = LOWORD (lParam); if (height == 0) // avoid 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, 0.25f, 1000.0f); glMatrixMode (GL_MODELVIEW); // set modelview matrix glLoadIdentity (); return 0; break; case WM_KEYDOWN: KeyPressed[wParam] = true; return 0; break; case WM_KEYUP: KeyPressed[wParam] = false; return 0; break; default: break; } return (DefWindowProc (hwnd, message, wParam, lParam));}bool windowsetup (RECT &windowRect, DWORD &dwExStyle, DWORD &dwStyle){ WNDCLASSEX windowClass; // fill out the window class structure windowClass.cbSize = sizeof (WNDCLASSEX); windowClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; windowClass.lpfnWndProc = WndProc; windowClass.cbClsExtra = 0; windowClass.cbWndExtra = 0; windowClass.hInstance = Win.hInstance; windowClass.hIcon = LoadIcon (NULL, IDI_APPLICATION); // default icon windowClass.hCursor = LoadCursor (NULL, IDC_ARROW); // default arrow windowClass.hbrBackground = NULL; // dont need background windowClass.lpszMenuName = NULL; // no menu windowClass.lpszClassName = Win.className; windowClass.hIconSm = LoadIcon (NULL, IDI_WINLOGO); // small logo // register the window class if (!RegisterClassEx (&windowClass)) return 0; if (Win.FullScreen) { DEVMODE dmScreenSettings; // device mode memset (&dmScreenSettings, 0, sizeof(dmScreenSettings)); dmScreenSettings.dmSize = sizeof(dmScreenSettings); dmScreenSettings.dmPelsWidth = Win.width; dmScreenSettings.dmPelsHeight = Win.height; dmScreenSettings.dmBitsPerPel = Win.bits; dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; if (ChangeDisplaySettings (&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { // setting display mode failed, switch to windowed MessageBox (NULL, "Display mode failed", NULL, MB_OK); Win.FullScreen = false; } } if (Win.FullScreen) // if we are still fullscreen { dwExStyle = WS_EX_APPWINDOW | WS_EX_TOPMOST; dwStyle = WS_POPUP; ShowCursor (FALSE); } else // windowed mode { dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; dwStyle = WS_OVERLAPPEDWINDOW; } AdjustWindowRectEx (&windowRect, dwStyle, FALSE, dwExStyle); // class registered, so now create window Win.hWnd = CreateWindowEx (dwExStyle, // extended style Win.className, // class name Win.title, // app name dwStyle | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, // style 0, 0, // x, y coordinate Win.width, Win.height, // width, height HWND_DESKTOP, // handle to parent NULL, // handle to menu Win.hInstance, // application instance NULL); // no extra params // check if window creation failed (hwnd would equal null) if (!Win.hWnd) return true; // Failed, so we are done, quit ShowWindow (Win.hWnd, SW_SHOW); // display the window UpdateWindow (Win.hWnd); // update the window return false; // Success, were not done}bool ValidKey (char Key){ // If the key has been pressed, and it wasnt pressed in the previous cycle if ((KeyPressed [Key] == true)&&(PreviousKeys [Key] == false)) return true; // Return true (ie successful) else return false; // Otherwise return false}void Update (bool &done, POINT &mpos, Poly Quad[Wallno], Box Rack [Rackno]){ mpos = GetMousePosition (); if (mpos.y != 240) lookupdown += (mpos.y - 240)/MouseSensitivity; if (mpos.x != 320) heading -= (mpos.x - 320)/MouseSensitivity; if (heading > 360) heading -= 360; else if (heading < 0) heading += 360; SetCursorPos(320,240); // Set the mouse position as the centre of the window if (ValidKey(VK_F12)) { if (Win.FullScreen) // Is window in fullscreen mode { ChangeDisplaySettings (NULL,0); // Switch back to desktop resolution ShowCursor (TRUE); // Show cursor } Win.FullScreen = (Win.FullScreen == true) ? false : true; done = true; } if (ValidKey(VK_F7)) lighting = (lighting == true) ? false : true; float newx = xmov; float newz = zmov; MoveDistance = 1.75f/(times*0.005f); if ((KeyPressed [VK_UP])&&(!KeyPressed [VK_DOWN])) { newx -= (float)sin(heading*piover180) * MoveDistance; newz -= (float)cos(heading*piover180) * MoveDistance; } else if ((KeyPressed [VK_DOWN])&&(!KeyPressed [VK_UP])) { newx += (float)sin(heading*piover180) * MoveDistance; newz += (float)cos(heading*piover180) * MoveDistance; } if ((KeyPressed [VK_LEFT])&&(!KeyPressed [VK_RIGHT])) { newx += (float)sin((heading - 90)*piover180) * MoveDistance; newz += (float)cos((heading - 90)*piover180) * MoveDistance; } else if ((KeyPressed [VK_RIGHT])&&(!KeyPressed [VK_LEFT])) { newx += (float)sin((heading + 90)*piover180) * MoveDistance; newz += (float)cos((heading + 90)*piover180) * MoveDistance; } // **** COLLISION DETECTION **** xpos = newx; zpos = newz; for (int i = 0; i < 256; i++) PreviousKeys [i] = KeyPressed[i];}void Draw (POINT mpos, Poly Quad[Wallno], Box Rack[Rackno]){ // do rendering here // clear screen and depth buffer glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity (); // reset modelview matrix glPushMatrix(); glRotatef(lookupdown,1.0f,0,0); glRotatef(360.0f-heading,0,1.0f,0); glTranslatef (-xmov, 0.0f, -zmov); glBegin (GL_QUADS); for (int i = 0; i < Wallno-2; i++) { glNormal3f (Quad[i].Normal[0], Quad[i].Normal[1], Quad[i].Normal[2]); glVertex3f (Quad[i].One[0], Quad[i].One[1], Quad[i].One[2]); glVertex3f (Quad[i].Two[0], Quad[i].Two[1], Quad[i].Two[2]); glVertex3f (Quad[i].Three[0], Quad[i].Three[1], Quad[i].Three[2]); glVertex3f (Quad[i].Four[0], Quad[i].Four[1], Quad[i].Four[2]); } glEnd(); glColor3f (0.0f, 0.0f, 1.0f); glPopMatrix(); glMatrixMode(GL_PROJECTION); // Select The Projection Matrix glPushMatrix(); // Store The Projection Matrix glLoadIdentity(); // Reset The Projection Matrix glOrtho(0,640,480,0,-1,1); // Set Up An Ortho Screen glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix glTranslated(0.0f, 0.0f, 1.0f); // Move To The Current Mouse Position glPrint (5.0f, 10.0f, "Press Esc to quit"); glMatrixMode(GL_PROJECTION); // Select The Projection Matrix glPopMatrix(); // Restore The Old Projection Matrix glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix glFlush();}// the main Windows entry pointint WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd){ MSG msg; // message bool done; // "app complete" flag DWORD dwExStyle; // Windows extended style DWORD dwStyle; // Window style RECT windowRect; // Window Properties: Win.hInstance = hInstance; Win.className = "BaseCode"; Win.title = "OpenGL Basecode"; Win.width = 640; Win.height = 480; Win.bits = 16; Win.FullScreen = false; windowRect.left = (long)0; windowRect.right = (long)Win.width; windowRect.top = (long)0; windowRect.bottom = (long)Win.height; POINT mpos; Poly Quad[Wallno]; done = false; // initialise the loop condition variable while (ProgramLooping) { done = windowsetup (windowRect, dwExStyle, dwStyle); Initialise (); // main message loop while (!done) { PeekMessage (&msg, Win.hWnd, NULL, NULL, PM_REMOVE); if ((msg.message == WM_QUIT)|| // received a WM_QUIT message? (KeyPressed[VK_ESCAPE])) // Pressed Escape { ProgramLooping = false; done = true; // if so, time to quit the app } else { // Main logic loop // FRAMES COUNT processing times = timeGetTime()*0.001f;//get current time in seconds ++frames; // update the frame rate 1ce per second if (times-last_time>1.0f) { fps = frames/(times-last_time); last_time = times; frames = 0L; } // END Update (done, mpos, Quad, Rack); Draw (mpos, Quad, Rack); SwapBuffers (Win.hDC); TranslateMessage (&msg); DispatchMessage (&msg); } } // while (done) TerminateWindow (Win.hWnd); UnregisterClass (Win.className, Win.hInstance); // UnRegister window class } return msg.wParam;}
For those of you who waded through that thank you. I hope inspiration strikes.
For those of you who didnt, another puzzler. In fullscreen, textures work fine. However, in a window they are all distorted and jagged, as if at regular intervals it is being pulled in opposite directions. Any ideas?
Thanks...
zoidy
Well this is coming from a physics enthusiast, but you may want a fancier way of calculating skid which results from static friction from the surface the thing is moving on pulling in the opposite direction of the thing at some force. But it sounds to me just like you need to decelerate the thing time-based instead of frame-based which would involve calculating a desirable deceleration at fps = 1 then dividing this number by the FPS each frame so that all the frames combined movement in one second would equal the desired movement in one second. Hope that helps
My fellow Americans I have just signed legislation that outlaws Russia forever. Bombing will commence in five minutes.
Just an idea might be that, while holding the directional button, you are queueing (sp?) up events. Kind of like holding down a key when you are typing. Then, maybe your engine can only execute N of those keypresses every frame. That would explain why the longer you hold it, the longer you "skid". Hopefully this helps,
[ XtaC ]
[ XtaC ]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement