Avoid doing extra game state updates if the game state updates are somehow slower than graphical updates.

master
Cyp 2011-12-18 16:53:58 +01:00
parent a5ad6ef0e9
commit ceb339939e
3 changed files with 32 additions and 5 deletions

View File

@ -149,7 +149,7 @@ UDWORD getModularScaledRealTime(UDWORD timePeriod, UDWORD requiredRange)
}
/* Call this each loop to update the game timer */
void gameTimeUpdate()
void gameTimeUpdate(unsigned renderAverage, unsigned stateAverage)
{
deltaGameTime = 0;
deltaGraphicsTime = 0;
@ -171,8 +171,13 @@ void gameTimeUpdate()
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.
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
int newDeltaGraphicsTime = quantiseFraction(modifier.n, modifier.d, currTime, prevRealTime);

View File

@ -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.
* @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.)
void gameTimeUpdateEnd(void);

View File

@ -93,6 +93,9 @@
#include "objmem.h"
#endif
#include <numeric>
static void fireWaitingCallbacks(void);
/*
@ -663,6 +666,10 @@ static void gameStateUpdate()
GAMECODE gameLoop(void)
{
static uint32_t lastFlushTime = 0;
static unsigned stateTimes[8];
static unsigned renderTimes[8];
static int stateTimeIndex = 0;
static int renderTimeIndex = 0;
bool didTick = false;
while (true)
@ -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.
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.
gameTimeUpdate();
gameTimeUpdate(renderAverage, stateAverage);
if (deltaGameTime == 0)
{
@ -682,9 +692,14 @@ GAMECODE gameLoop(void)
ASSERT(!paused && !gameUpdatePaused() && !editPaused(), "Nonsensical pause values.");
unsigned before = wzGetTicks();
syncDebug("Begin game state update, gameTime = %d", gameTime);
gameStateUpdate();
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.");
}
@ -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.
}
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 */