Skip to content

Commit

Permalink
Avoid doing extra game state updates if the game state updates are so…
Browse files Browse the repository at this point in the history
…mehow slower than graphical updates.
  • Loading branch information
Cyp committed Dec 18, 2011
1 parent a5ad6ef commit ceb3399
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 5 deletions.
9 changes: 7 additions & 2 deletions lib/gamelib/gtime.cpp
Expand Up @@ -149,7 +149,7 @@ UDWORD getModularScaledRealTime(UDWORD timePeriod, UDWORD requiredRange)
} }


/* Call this each loop to update the game timer */ /* Call this each loop to update the game timer */
void gameTimeUpdate() void gameTimeUpdate(unsigned renderAverage, unsigned stateAverage)
{ {
deltaGameTime = 0; deltaGameTime = 0;
deltaGraphicsTime = 0; deltaGraphicsTime = 0;
Expand All @@ -171,8 +171,13 @@ void gameTimeUpdate()
return; return;
} }


(void)stateAverage; // Don't need to know the average state update time.
// A bit arbitrary formula, but if the average time to render a frame is high compared to the time to update the
// state, then update multiple times per frame. Otherwise, update at least once per frame.
unsigned maximumTicksPerFrame = renderAverage*2 + GAME_TICKS_PER_UPDATE*modifier.d/std::max<int>(modifier.n, 1) + 1;

// Make sure graphics updates fast enough. // Make sure graphics updates fast enough.
prevRealTime = std::max(prevRealTime + MAXIMUM_TICKS_PER_FRAME, currTime) - MAXIMUM_TICKS_PER_FRAME; // Written this way to avoid unsigned underflow. prevRealTime = std::max(prevRealTime + maximumTicksPerFrame, currTime) - maximumTicksPerFrame; // Written this way to avoid unsigned underflow.


// Calculate the new game time // Calculate the new game time
int newDeltaGraphicsTime = quantiseFraction(modifier.n, modifier.d, currTime, prevRealTime); int newDeltaGraphicsTime = quantiseFraction(modifier.n, modifier.d, currTime, prevRealTime);
Expand Down
2 changes: 1 addition & 1 deletion lib/gamelib/gtime.h
Expand Up @@ -71,7 +71,7 @@ extern void setGameTime(uint32_t newGameTime);
* The game time increases in GAME_UNITS_PER_TICK increments, and deltaGameTime is either 0 or GAME_UNITS_PER_TICK. * The game time increases in GAME_UNITS_PER_TICK increments, and deltaGameTime is either 0 or GAME_UNITS_PER_TICK.
* @returns true iff the game time ticked. * @returns true iff the game time ticked.
*/ */
extern void gameTimeUpdate(void); void gameTimeUpdate(unsigned renderAverage, unsigned stateAverage);
/// Call after updating the state, and before processing any net messages that use deltaGameTime. (Sets deltaGameTime = 0.) /// Call after updating the state, and before processing any net messages that use deltaGameTime. (Sets deltaGameTime = 0.)
void gameTimeUpdateEnd(void); void gameTimeUpdateEnd(void);


Expand Down
26 changes: 24 additions & 2 deletions src/loop.cpp
Expand Up @@ -93,6 +93,9 @@
#include "objmem.h" #include "objmem.h"
#endif #endif


#include <numeric>


static void fireWaitingCallbacks(void); static void fireWaitingCallbacks(void);


/* /*
Expand Down Expand Up @@ -663,6 +666,10 @@ static void gameStateUpdate()
GAMECODE gameLoop(void) GAMECODE gameLoop(void)
{ {
static uint32_t lastFlushTime = 0; static uint32_t lastFlushTime = 0;
static unsigned stateTimes[8];
static unsigned renderTimes[8];
static int stateTimeIndex = 0;
static int renderTimeIndex = 0;


bool didTick = false; bool didTick = false;
while (true) while (true)
Expand All @@ -671,8 +678,11 @@ GAMECODE gameLoop(void)
// Receive GAME_BLAH messages, and if it's time, process exactly as many GAME_BLAH messages as required to be able to tick the gameTime. // Receive GAME_BLAH messages, and if it's time, process exactly as many GAME_BLAH messages as required to be able to tick the gameTime.
recvMessage(); recvMessage();


unsigned renderAverage = std::accumulate(renderTimes, renderTimes + ARRAY_SIZE(renderTimes), 0) / ARRAY_SIZE(renderTimes);
unsigned stateAverage = std::accumulate(stateTimes, stateTimes + ARRAY_SIZE(stateTimes), 0) / ARRAY_SIZE(stateTimes);

// Update gameTime and graphicsTime, and corresponding deltas. Note that gameTime and graphicsTime pause, if we aren't getting our GAME_GAME_TIME messages. // Update gameTime and graphicsTime, and corresponding deltas. Note that gameTime and graphicsTime pause, if we aren't getting our GAME_GAME_TIME messages.
gameTimeUpdate(); gameTimeUpdate(renderAverage, stateAverage);


if (deltaGameTime == 0) if (deltaGameTime == 0)
{ {
Expand All @@ -682,9 +692,14 @@ GAMECODE gameLoop(void)


ASSERT(!paused && !gameUpdatePaused() && !editPaused(), "Nonsensical pause values."); ASSERT(!paused && !gameUpdatePaused() && !editPaused(), "Nonsensical pause values.");


unsigned before = wzGetTicks();
syncDebug("Begin game state update, gameTime = %d", gameTime); syncDebug("Begin game state update, gameTime = %d", gameTime);
gameStateUpdate(); gameStateUpdate();
syncDebug("End game state update, gameTime = %d", gameTime); syncDebug("End game state update, gameTime = %d", gameTime);
unsigned after = wzGetTicks();

stateTimes[stateTimeIndex] = after - before;
stateTimeIndex = (stateTimeIndex + 1)%ARRAY_SIZE(stateTimes);


ASSERT(deltaGraphicsTime == 0, "Shouldn't update graphics and game state at once."); ASSERT(deltaGraphicsTime == 0, "Shouldn't update graphics and game state at once.");
} }
Expand All @@ -695,7 +710,14 @@ GAMECODE gameLoop(void)
NETflush(); // Make sure the game time tick message is really sent over the network, and that we aren't waiting too long to send data. NETflush(); // Make sure the game time tick message is really sent over the network, and that we aren't waiting too long to send data.
} }


return renderLoop(); unsigned before = wzGetTicks();
GAMECODE renderReturn = renderLoop();
unsigned after = wzGetTicks();

renderTimes[renderTimeIndex] = after - before;
renderTimeIndex = (renderTimeIndex + 1)%ARRAY_SIZE(renderTimes);

return renderReturn;
} }


/* The video playback loop */ /* The video playback loop */
Expand Down

0 comments on commit ceb3399

Please sign in to comment.