Allow multiple logical updates per rendered frame.

Allows maintaining game speed when the GPU can't keep up.
master
Cyp 2011-12-11 15:52:39 +01:00
parent 74261ad652
commit e50368114d
3 changed files with 39 additions and 18 deletions

View File

@ -32,6 +32,10 @@
#include <time.h>
// Maximum seconds per frame.
// If not reaching the goal, force graphics updates, even if we aren't doing enough game state updates to maintain game speed.
#define MAXIMUM_SPF 1/4
/* See header file for documentation */
UDWORD gameTime = 0, deltaGameTime = 0, graphicsTime = 0, deltaGraphicsTime = 0, realTime = 0, deltaRealTime = 0;
float graphicsTimeFraction = 0.0, realTimeFraction = 0.0;
@ -188,10 +192,10 @@ void gameTimeUpdate()
{
unsigned player;
// Pause time, since we are waiting GAME_GAME_TIME from other players.
scaledCurrTime = graphicsTime;
// Pause time at current game time, since we are waiting GAME_GAME_TIME from other players.
scaledCurrTime = gameTime;
baseTime = currTime;
timeOffset = graphicsTime;
timeOffset = gameTime;
debug(LOG_SYNC, "Waiting for other players. gameTime = %u, player times are {%s}", gameTime, listToString("%u", ", ", gameQueueTime, gameQueueTime + game.maxPlayers).c_str());
mayUpdate = false;
@ -212,10 +216,10 @@ void gameTimeUpdate()
// Adjust deltas.
if (scaledCurrTime >= gameTime && mayUpdate)
{
if (scaledCurrTime > gameTime + GAME_TICKS_PER_UPDATE)
if (scaledCurrTime > gameTime + GAME_TICKS_PER_SEC*MAXIMUM_SPF)
{
// Game isn't updating fast enough...
uint32_t slideBack = deltaGraphicsTime - GAME_TICKS_PER_UPDATE;
uint32_t slideBack = deltaGraphicsTime - GAME_TICKS_PER_SEC*MAXIMUM_SPF;
baseTime += slideBack / modifier; // adjust the addition to base time
deltaGraphicsTime -= slideBack;
}
@ -235,6 +239,11 @@ void gameTimeUpdate()
deltaGameTime = 0;
}
if (deltaGameTime != 0)
{
deltaGraphicsTime = 0; // Don't update graphics until game state is updated.
}
// Store the game and graphics times
gameTime += deltaGameTime;
graphicsTime += deltaGraphicsTime;

View File

@ -2575,9 +2575,12 @@ float available_speed[] = {
5.f / 2.f, // n
3.f / 1.f, // n
10.f / 1.f, // n
20.f / 1.f // n
20.f / 1.f, // n
30.f / 1.f, // n
60.f / 1.f, // n
100.f / 1.f, // n
};
unsigned int nb_available_speeds = 12;
unsigned int nb_available_speeds = ARRAY_SIZE(available_speed);
void kf_SpeedUp( void )
{

View File

@ -671,25 +671,34 @@ static void gameStateUpdate()
/* The main game loop */
GAMECODE gameLoop(void)
{
bool gameTicked; // true iff we are doing a logical update.
static uint32_t lastFlushTime = 0;
// Receive NET_BLAH messages.
// 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();
// Update gameTime and graphicsTime, and corresponding deltas. Note that gameTime and graphicsTime pause, if we aren't getting our GAME_GAME_TIME messages.
gameTimeUpdate();
gameTicked = deltaGameTime != 0;
if (gameTicked)
bool didTick = false;
while (true)
{
// Receive NET_BLAH messages.
// 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();
// Update gameTime and graphicsTime, and corresponding deltas. Note that gameTime and graphicsTime pause, if we aren't getting our GAME_GAME_TIME messages.
gameTimeUpdate();
if (deltaGameTime == 0)
{
break; // Not doing a game state update.
}
didTick = true;
ASSERT(!paused && !gameUpdatePaused() && !editPaused(), "Nonsensical pause values.");
syncDebug("Begin game state update, gameTime = %d", gameTime);
gameStateUpdate();
syncDebug("End game state update, gameTime = %d", gameTime);
ASSERT(deltaGraphicsTime == 0, "Shouldn't update graphics and game state at once.");
}
if (gameTicked || realTime - lastFlushTime < 400u)
if (didTick || realTime - lastFlushTime < 400u)
{
lastFlushTime = realTime;
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.