/** ** Wait for interactive input event for one frame. ** ** Handles system events, joystick, keyboard, mouse. ** Handles the network messages. ** Handles the sound queue. ** ** All events available are fetched. Sound and network only if available. ** Returns if the time for one frame is over. */ void WaitEventsOneFrame() { ++FrameCounter; Uint32 ticks = SDL_GetTicks(); if (ticks > NextFrameTicks) { // We are too slow :( ++SlowFrameCounter; } InputMouseTimeout(*GetCallbacks(), ticks); InputKeyTimeout(*GetCallbacks(), ticks); CursorAnimate(ticks); int interrupts = 0; for (;;) { // Time of frame over? This makes the CPU happy. :( ticks = SDL_GetTicks(); if (!interrupts && ticks < NextFrameTicks) { SDL_Delay(NextFrameTicks - ticks); ticks = SDL_GetTicks(); } while (ticks >= NextFrameTicks) { ++interrupts; FrameFraction += FrameRemainder; if (FrameFraction > 10) { FrameFraction -= 10; ++NextFrameTicks; } NextFrameTicks += FrameTicks; } SDL_Event event[1]; const int i = SDL_PollEvent(event); if (i) { // Handle SDL event SdlDoEvent(*GetCallbacks(), *event); } // Network int s = 0; if (IsNetworkGame()) { s = NetworkFildes.HasDataToRead(0); if (s > 0) { GetCallbacks()->NetworkEvent(); } } // No more input and time for frame over: return if (!i && s <= 0 && interrupts) { break; } } handleInput(NULL); if (!SkipGameCycle--) { SkipGameCycle = SkipFrames; } }
/** ** Wait for interactive input event for one frame. ** ** Handles system events, joystick, keyboard, mouse. ** Handles the network messages. ** Handles the sound queue. ** ** All events available are fetched. Sound and network only if available. ** Returns if the time for one frame is over. */ void WaitEventsOneFrame() { struct timeval tv; fd_set rfds; fd_set wfds; Socket maxfd; int i; int s = 0; SDL_Event event[1]; Uint32 ticks; int interrupts; ++FrameCounter; ticks = SDL_GetTicks(); if (ticks > NextFrameTicks) { // We are too slow :( ++SlowFrameCounter; } InputMouseTimeout(GetCallbacks(), ticks); InputKeyTimeout(GetCallbacks(), ticks); CursorAnimate(ticks); interrupts = 0; for (;;) { // // Time of frame over? This makes the CPU happy. :( // ticks = SDL_GetTicks(); if (!interrupts && ticks < NextFrameTicks) { SDL_Delay(NextFrameTicks - ticks); ticks = SDL_GetTicks(); } while (ticks >= NextFrameTicks) { ++interrupts; FrameFraction += FrameRemainder; if (FrameFraction > 10) { FrameFraction -= 10; ++NextFrameTicks; } NextFrameTicks += FrameTicks; } // // Prepare select // maxfd = 0; tv.tv_sec = tv.tv_usec = 0; FD_ZERO(&rfds); FD_ZERO(&wfds); // // Network // if (IsNetworkGame()) { if (NetworkFildes > maxfd) { maxfd = NetworkFildes; } FD_SET(NetworkFildes, &rfds); } #if 0 s = select(maxfd + 1, &rfds, &wfds, NULL, (i = SDL_PollEvent(event)) ? &tv : NULL); #else // QUICK HACK to fix the event/timer problem // The timer code didn't interrupt the select call. // Perhaps I could send a signal to the process // Not very nice, but this is the problem if you use other libraries // The event handling of SDL is wrong designed = polling only. // There is hope on SDL 1.3 which will have this fixed. //s = select(maxfd + 1, &rfds, &wfds, NULL, &tv); //printf("PollEvent\n"); i = SDL_PollEvent(event); #endif if (i) { // Handle SDL event SdlDoEvent(GetCallbacks(), event); } if (s > 0) { // // Network // if (IsNetworkGame() && FD_ISSET(NetworkFildes, &rfds) ) { GetCallbacks()->NetworkEvent(); } } // // No more input and time for frame over: return // if (!i && s <= 0 && interrupts) { break; } } handleInput(NULL); if (!SkipGameCycle--) { SkipGameCycle = SkipFrames; } if (!UseOpenGL && (GameRunning || Editor.Running || PatchEditorRunning)) { Video.ClearScreen(); } }