Added linear interpolation between states
This commit is contained in:
parent
5e7bff96d0
commit
d2ce7bc506
|
@ -20,7 +20,7 @@
|
|||
#define ENABLE_CLIENT_SIDE_PREDICTION
|
||||
#define ENABLE_SERVER_RECONCILLIATION
|
||||
|
||||
uint8_t colours[16][3] =
|
||||
const uint8_t colours[16][3] =
|
||||
{
|
||||
{255, 255, 255},
|
||||
{100, 176, 254},
|
||||
|
@ -117,41 +117,11 @@ void * networkHandler(void * parameters)
|
|||
recvfrom(udpSocket, updatedState, sizeof(struct gameState), 0, NULL, NULL);
|
||||
|
||||
// Only update the state if the given state is more recent than the current state:
|
||||
if(updatedState->timestamp.tv_sec > arguments->state->timestamp.tv_sec)
|
||||
if(updatedState->timestamp.tv_sec > arguments->state->timestamp.tv_sec ||
|
||||
(updatedState->timestamp.tv_sec == arguments->state->timestamp.tv_sec &&
|
||||
updatedState->timestamp.tv_usec > arguments->state->timestamp.tv_usec))
|
||||
{
|
||||
memcpy(arguments->state, updatedState, sizeof(struct gameState));
|
||||
#ifdef ENABLE_SERVER_RECONCILLIATION
|
||||
// Throw away any already acknowledged inputs:
|
||||
while (arguments->inputBuffer->start != -1 &&
|
||||
arguments->inputBuffer->inputs[arguments->inputBuffer->start].tickNumber < arguments->state->tickNumber)
|
||||
{
|
||||
arguments->inputBuffer->start = (arguments->inputBuffer->start + 1) % 256;
|
||||
if(arguments->inputBuffer->start == arguments->inputBuffer->end)
|
||||
{
|
||||
arguments->inputBuffer->start = -1;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t currentMessage = arguments->inputBuffer->start;
|
||||
uint64_t lastTickNumber = arguments->inputBuffer->inputs[arguments->inputBuffer->start].tickNumber;
|
||||
|
||||
// Re-apply the currently unused messages:
|
||||
while (currentMessage != 1 &&
|
||||
currentMessage != arguments->inputBuffer->end)
|
||||
{
|
||||
updateInput(arguments->state, &arguments->inputBuffer->inputs[currentMessage]);
|
||||
currentMessage = (currentMessage + 1) % 256;
|
||||
if (arguments->inputBuffer->inputs[currentMessage].tickNumber != lastTickNumber)
|
||||
{
|
||||
doGameTick(arguments->state);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if(updatedState->timestamp.tv_sec == arguments->state->timestamp.tv_sec &&
|
||||
updatedState->timestamp.tv_usec > arguments->state->timestamp.tv_usec)
|
||||
{
|
||||
memcpy(arguments->state, updatedState, sizeof(struct gameState));
|
||||
// memcpy(arguments->state, updatedState, sizeof(struct gameState));
|
||||
#ifdef ENABLE_SERVER_RECONCILLIATION
|
||||
// Throw away any already acknowledged inputs:
|
||||
while (arguments->inputBuffer->start != -1 &&
|
||||
|
@ -180,6 +150,7 @@ void * networkHandler(void * parameters)
|
|||
}
|
||||
#endif
|
||||
}
|
||||
lerpStates(arguments->state, updatedState);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -188,6 +159,7 @@ void * gameThreadHandler(void * parameters)
|
|||
struct threadParameters * arguments = parameters;
|
||||
|
||||
#ifdef ENABLE_CLIENT_SIDE_PREDICTION
|
||||
struct gameState * nextStep = calloc(1, sizeof(struct gameState));
|
||||
while (true)
|
||||
{
|
||||
updateInput(arguments->state, arguments->message);
|
||||
|
@ -204,7 +176,9 @@ void * gameThreadHandler(void * parameters)
|
|||
arguments->inputBuffer->end = (arguments->inputBuffer->end + 1) % 256;
|
||||
}
|
||||
#endif
|
||||
doGameTick(arguments->state);
|
||||
memcpy(nextStep, arguments->state, sizeof(struct gameState));
|
||||
doGameTick(nextStep);
|
||||
lerpStates(arguments->state, nextStep);
|
||||
usleep(15625);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
#include "cspt-state.h"
|
||||
|
||||
void updateInput(struct gameState * state, struct clientInput * message)
|
||||
|
@ -11,7 +16,28 @@ void updateInput(struct gameState * state, struct clientInput * message)
|
|||
state->clients[message->clientNumber].upAcceleration = message->up;
|
||||
state->clients[message->clientNumber].downAcceleration = message->down;
|
||||
}
|
||||
}
|
||||
|
||||
void lerpStates (struct gameState * state, struct gameState * endState)
|
||||
{
|
||||
// Create a copy of the initial state for interpolating to the final state:
|
||||
struct gameState * startState = calloc(1, sizeof(struct gameState));
|
||||
memcpy(startState, state, sizeof(struct gameState));
|
||||
|
||||
for (double progress = 0.0; progress < 1.0; progress += 0.01)
|
||||
{
|
||||
for (uint8_t index = 0; index < 16; index++)
|
||||
{
|
||||
// Movement:
|
||||
state->clients[index].xPosition = startState->clients[index].xPosition +
|
||||
(progress * (endState->clients[index].xPosition - startState->clients[index].xPosition));
|
||||
state->clients[index].yPosition = startState->clients[index].yPosition +
|
||||
(progress * (endState->clients[index].yPosition - startState->clients[index].yPosition));
|
||||
}
|
||||
usleep(100);
|
||||
}
|
||||
free(startState);
|
||||
memcpy(state, endState, sizeof(struct gameState));
|
||||
}
|
||||
|
||||
void doGameTick(struct gameState * state)
|
||||
|
|
|
@ -39,6 +39,8 @@ struct inputHistory
|
|||
|
||||
void updateInput(struct gameState * state, struct clientInput * message);
|
||||
|
||||
void lerpStates (struct gameState * state, struct gameState * endState);
|
||||
|
||||
void doGameTick(struct gameState * state);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue