Rework main loop
This commit is contained in:
parent
c3dcd1ff0f
commit
c7711b6cf4
1 changed files with 171 additions and 109 deletions
280
game.h
280
game.h
|
@ -23,6 +23,23 @@
|
||||||
independent of rendering and physics libraries, but out of convenient adopts
|
independent of rendering and physics libraries, but out of convenient adopts
|
||||||
their coordinate system (X right, Y up, Z forward) and rotations (Euler
|
their coordinate system (X right, Y up, Z forward) and rotations (Euler
|
||||||
angles, by Z, then by X, then Y).
|
angles, by Z, then by X, then Y).
|
||||||
|
|
||||||
|
RESOURCE FILE: The game uses so called resource file to store various
|
||||||
|
resources, mainly maps and replays. There is considered to be one abstract
|
||||||
|
global file which is just a long text string. Internally the global file is
|
||||||
|
composed of a hardcoded internal resource file string (stored in assets) with
|
||||||
|
very basic maps, and an optional user file (appended to the internal file)
|
||||||
|
that the frontend may provide, allowing adding more resources without
|
||||||
|
recompiling the game. The user file may be disabled on platforms that e.g.
|
||||||
|
don't have file systems, but the internal file will be always present. The
|
||||||
|
format of the resource file is following: it consists of resource strings
|
||||||
|
separated by '#' character (resource strings cannot contain this character).
|
||||||
|
Each resource string starts with a magic number: a single character
|
||||||
|
identifying the type of the resource (map, replay, ...), then the name of the
|
||||||
|
resource follows, then character ';' and then the resource string itself (up
|
||||||
|
until next '#' or end of file). The format of the string depends on the type
|
||||||
|
of resource, i.e. the format of map string has a special format (described in
|
||||||
|
the map module) etc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LCR_GAME_H
|
#ifndef _LCR_GAME_H
|
||||||
|
@ -157,6 +174,10 @@ uint8_t LCR_gameGetNextAudioSample(void);
|
||||||
#define LCR_GAME_STATE_RUN 0x02
|
#define LCR_GAME_STATE_RUN 0x02
|
||||||
#define LCR_GAME_STATE_RUN_FINISHED 0x03
|
#define LCR_GAME_STATE_RUN_FINISHED 0x03
|
||||||
|
|
||||||
|
|
||||||
|
#define LCR_RESOURCE_ITEM_CHUNK 8
|
||||||
|
#define LCR_MENU_STRING_SIZE 16
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint8_t state;
|
uint8_t state;
|
||||||
|
@ -168,7 +189,16 @@ struct
|
||||||
uint8_t controlMode;
|
uint8_t controlMode;
|
||||||
uint8_t debugDraw;
|
uint8_t debugDraw;
|
||||||
uint8_t musicVolume;
|
uint8_t musicVolume;
|
||||||
int resourceFileState; ///< -1 if reading external res. f., else pos.
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int state; ///< -1 if reading external res. f., else pos.
|
||||||
|
|
||||||
|
unsigned char loadedItemCount;
|
||||||
|
char loadedItemNames[LCR_RESOURCE_ITEM_CHUNK * LCR_MENU_STRING_SIZE];
|
||||||
|
unsigned int loadedItemsIndices[LCR_RESOURCE_ITEM_CHUNK]; // absolute
|
||||||
|
unsigned int itemsTotal; // total of items of this type
|
||||||
|
} resourceFile;
|
||||||
} LCR_game;
|
} LCR_game;
|
||||||
|
|
||||||
uint8_t LCR_gameGetMusicVolume(void)
|
uint8_t LCR_gameGetMusicVolume(void)
|
||||||
|
@ -249,7 +279,7 @@ void LCR_gameResetRun(void)
|
||||||
void LCR_gameRewindResourceFile(void)
|
void LCR_gameRewindResourceFile(void)
|
||||||
{
|
{
|
||||||
LCR_appendResourceStr("");
|
LCR_appendResourceStr("");
|
||||||
LCR_game.resourceFileState = 0;
|
LCR_game.resourceFile.state = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -263,34 +293,34 @@ char LCR_gameGetNextResourceFileChar(void)
|
||||||
#if LCR_SETTING_ENABLE_RESOURCE_FILE
|
#if LCR_SETTING_ENABLE_RESOURCE_FILE
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
if (LCR_game.resourceFileState < 0) // external file?
|
if (LCR_game.resourceFile.state < 0) // external file?
|
||||||
{
|
{
|
||||||
c = LCR_getNextResourceFileChar();
|
c = LCR_getNextResourceFileChar();
|
||||||
|
|
||||||
if (c == 0)
|
if (c == 0)
|
||||||
LCR_game.resourceFileState = 0; // move to internal file next
|
LCR_game.resourceFile.state = 0; // move to internal file next
|
||||||
}
|
}
|
||||||
else // internal file
|
else // internal file
|
||||||
{
|
{
|
||||||
c = LCR_internalResourceFile[LCR_game.resourceFileState];
|
c = LCR_internalResourceFile[LCR_game.resourceFile.state];
|
||||||
LCR_game.resourceFileState++;
|
LCR_game.resourceFile.state++;
|
||||||
|
|
||||||
if (c == 0)
|
if (c == 0)
|
||||||
{
|
{
|
||||||
c = LCR_getNextResourceFileChar();
|
c = LCR_getNextResourceFileChar();
|
||||||
LCR_game.resourceFileState = c ? -1 : 0; // trust this
|
LCR_game.resourceFile.state = c ? -1 : 0; // trust this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
#else
|
#else
|
||||||
if (LCR_internalResourceFile[LCR_game.resourceFileState] == 0)
|
if (LCR_internalResourceFile[LCR_game.resourceFile.state] == 0)
|
||||||
{
|
{
|
||||||
LCR_game.resourceFileState = 0;
|
LCR_game.resourceFile.state = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return LCR_internalResourceFile[LCR_game.resourceFileState++];
|
return LCR_internalResourceFile[LCR_game.resourceFile.state++];
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,7 +357,7 @@ void LCR_seekResourceByIndex(unsigned int index)
|
||||||
index--;
|
index--;
|
||||||
}
|
}
|
||||||
|
|
||||||
do // skip the name
|
do // skip magic number and name
|
||||||
c = LCR_gameGetNextResourceFileChar();
|
c = LCR_gameGetNextResourceFileChar();
|
||||||
while (c != LCR_RESOURCE_FILE_SEPARATOR2 &&
|
while (c != LCR_RESOURCE_FILE_SEPARATOR2 &&
|
||||||
c != LCR_RESOURCE_FILE_SEPARATOR && c != 0);
|
c != LCR_RESOURCE_FILE_SEPARATOR && c != 0);
|
||||||
|
@ -354,7 +384,19 @@ void LCR_gameInit(void)
|
||||||
LCR_racingInit();
|
LCR_racingInit();
|
||||||
LCR_audioInit();
|
LCR_audioInit();
|
||||||
|
|
||||||
LCR_game.resourceFileState = 0;
|
LCR_game.resourceFile.state = 0;
|
||||||
|
|
||||||
|
LCR_game.resourceFile.loadedItemCount = 0;
|
||||||
|
LCR_game.resourceFile.itemsTotal = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < LCR_RESOURCE_ITEM_CHUNK; ++i)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < LCR_MENU_STRING_SIZE; ++j)
|
||||||
|
LCR_game.resourceFile.loadedItemNames[i * LCR_MENU_STRING_SIZE + j] = 0;
|
||||||
|
|
||||||
|
LCR_game.resourceFile.loadedItemsIndices[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
LCR_game.frame = 0;
|
LCR_game.frame = 0;
|
||||||
LCR_game.musicVolume = 255;
|
LCR_game.musicVolume = 255;
|
||||||
|
@ -362,6 +404,19 @@ void LCR_gameInit(void)
|
||||||
LCR_game.nextRacingTickTime = 0;
|
LCR_game.nextRacingTickTime = 0;
|
||||||
LCR_game.controlMode = LCR_CONTROL_MODE_FREECAM;
|
LCR_game.controlMode = LCR_CONTROL_MODE_FREECAM;
|
||||||
LCR_gameStartRun();
|
LCR_gameStartRun();
|
||||||
|
|
||||||
|
LCR_game.state = LCR_GAME_STATE_RUN;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Loads up to LCR_RESOURCE_ITEM_CHUNK items of given type (0 = map, 1 = replay)
|
||||||
|
into RAM, starting at given index (among items of the same type).
|
||||||
|
*/
|
||||||
|
void LCR_gameLoadResourceFileChunk(uint8_t type, unsigned int startIndex)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
void LCR_gameEnd(void)
|
void LCR_gameEnd(void)
|
||||||
|
@ -369,10 +424,73 @@ void LCR_gameEnd(void)
|
||||||
LCR_LOG0("ending");
|
LCR_LOG0("ending");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t LCR_gameStep(uint32_t time)
|
void LCR_gameDraw3DView(void)
|
||||||
{
|
{
|
||||||
LCR_GameUnit carTransform[6];
|
LCR_GameUnit carTransform[6];
|
||||||
|
|
||||||
|
LCR_GameUnit physicsInterpolationParam = LCR_GAME_UNIT -
|
||||||
|
((LCR_game.nextRacingTickTime - LCR_game.time) * LCR_GAME_UNIT)
|
||||||
|
/ LCR_RACING_TICK_MS;
|
||||||
|
|
||||||
|
LCR_racingGetCarTransform(carTransform,carTransform + 3,
|
||||||
|
physicsInterpolationParam);
|
||||||
|
|
||||||
|
LCR_rendererSetCarTransform(carTransform,carTransform + 3);
|
||||||
|
|
||||||
|
if (LCR_game.controlMode != LCR_CONTROL_MODE_FREECAM)
|
||||||
|
LCR_rendererCameraFollow();
|
||||||
|
|
||||||
|
#if LCR_ANIMATE_CAR
|
||||||
|
LCR_rendererSetWheelState(LCR_racingGetWheelRotation(),
|
||||||
|
LCR_racingGetWheelSteer() * 2);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LCR_rendererDraw();
|
||||||
|
|
||||||
|
int val = LCR_carSpeedKMH();
|
||||||
|
|
||||||
|
if (val < 5) // don't show tiny oscillations when still
|
||||||
|
val = 0;
|
||||||
|
|
||||||
|
char str[6];
|
||||||
|
|
||||||
|
str[0] = val >= 100 ? '0' + (val / 100) % 10 : ' ';
|
||||||
|
str[1] = val >= 10 ? '0' + (val / 10) % 10 : ' ';
|
||||||
|
str[2] = '0' + val % 10;
|
||||||
|
str[3] = 0;
|
||||||
|
|
||||||
|
LCR_rendererDrawText(str,
|
||||||
|
LCR_EFFECTIVE_RESOLUTION_X -
|
||||||
|
LCR_rendererComputeTextWidth(str,2) - 20,
|
||||||
|
LCR_EFFECTIVE_RESOLUTION_Y -
|
||||||
|
LCR_rendererComputeTextHeight(2) - 20,0,2);
|
||||||
|
|
||||||
|
val = LCR_racingGetRunTimeMS() / 1000; // seconds
|
||||||
|
|
||||||
|
str[3] = '0' + (val % 60) / 10;
|
||||||
|
str[4] = '0' + val % 10;
|
||||||
|
|
||||||
|
val = (val / 60) % 100; // minutes
|
||||||
|
|
||||||
|
str[0] = '0' + val / 10;
|
||||||
|
str[1] = '0' + val % 10;
|
||||||
|
str[2] = '\'';
|
||||||
|
str[5] = 0;
|
||||||
|
|
||||||
|
LCR_rendererDrawText(str,20,LCR_EFFECTIVE_RESOLUTION_Y -
|
||||||
|
LCR_rendererComputeTextHeight(2) - 20,0,2);
|
||||||
|
|
||||||
|
#if LCR_SETTING_DEBUG_PHYSICS_DRAW
|
||||||
|
LCR_GameUnit camTr[7];
|
||||||
|
LCR_rendererGetCameraTransform(camTr,camTr + 3,camTr + 6);
|
||||||
|
LCR_physicsDebugDraw(camTr,camTr + 3,camTr[6]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t LCR_gameStep(uint32_t time)
|
||||||
|
{
|
||||||
|
uint32_t sleep = 0;
|
||||||
|
|
||||||
LCR_LOG2("game step start");
|
LCR_LOG2("game step start");
|
||||||
|
|
||||||
LCR_game.time = time;
|
LCR_game.time = time;
|
||||||
|
@ -381,14 +499,47 @@ uint8_t LCR_gameStep(uint32_t time)
|
||||||
LCR_keyStates[i] = LCR_keyPressed(i) ?
|
LCR_keyStates[i] = LCR_keyPressed(i) ?
|
||||||
(LCR_keyStates[i] < 255 ? LCR_keyStates[i] + 1 : 255) : 0;
|
(LCR_keyStates[i] < 255 ? LCR_keyStates[i] + 1 : 255) : 0;
|
||||||
|
|
||||||
uint32_t sleep = 0;
|
|
||||||
|
|
||||||
if (LCR_keyStates[LCR_KEY_B] == 1)
|
if (LCR_keyStates[LCR_KEY_B] == 1)
|
||||||
LCR_game.controlMode = LCR_game.controlMode == LCR_CONTROL_MODE_FREECAM ?
|
LCR_game.controlMode = LCR_game.controlMode == LCR_CONTROL_MODE_FREECAM ?
|
||||||
LCR_CONTROL_MODE_DRIVE : LCR_CONTROL_MODE_FREECAM;
|
LCR_CONTROL_MODE_DRIVE : LCR_CONTROL_MODE_FREECAM;
|
||||||
else if (LCR_keyStates[LCR_KEY_B] == 30)
|
else if (LCR_keyStates[LCR_KEY_B] == 30)
|
||||||
LCR_gameResetRun();
|
LCR_gameResetRun();
|
||||||
|
|
||||||
|
LCR_GameUnit offsets[5];
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; ++i)
|
||||||
|
offsets[i] = 0;
|
||||||
|
|
||||||
|
if (LCR_game.controlMode == LCR_CONTROL_MODE_FREECAM)
|
||||||
|
{
|
||||||
|
if (LCR_keyStates[LCR_KEY_A])
|
||||||
|
{
|
||||||
|
if (LCR_keyStates[LCR_KEY_UP])
|
||||||
|
offsets[4] = LCR_FREE_CAMERA_TURN_STEP;
|
||||||
|
else if (LCR_keyStates[LCR_KEY_DOWN])
|
||||||
|
offsets[4] -= LCR_FREE_CAMERA_TURN_STEP;
|
||||||
|
|
||||||
|
if (LCR_keyStates[LCR_KEY_RIGHT])
|
||||||
|
offsets[3] -= LCR_FREE_CAMERA_TURN_STEP;
|
||||||
|
else if (LCR_keyStates[LCR_KEY_LEFT])
|
||||||
|
offsets[3] = LCR_FREE_CAMERA_TURN_STEP;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (LCR_keyStates[LCR_KEY_UP])
|
||||||
|
offsets[0] = LCR_FREE_CAMERA_STEP;
|
||||||
|
else if (LCR_keyStates[LCR_KEY_DOWN])
|
||||||
|
offsets[0] -= LCR_FREE_CAMERA_STEP;
|
||||||
|
|
||||||
|
if (LCR_keyStates[LCR_KEY_RIGHT])
|
||||||
|
offsets[1] = LCR_FREE_CAMERA_STEP;
|
||||||
|
else if (LCR_keyStates[LCR_KEY_LEFT])
|
||||||
|
offsets[1] -= LCR_FREE_CAMERA_STEP;
|
||||||
|
}
|
||||||
|
|
||||||
|
LCR_rendererMoveCamera(offsets,offsets + 3);
|
||||||
|
}
|
||||||
|
|
||||||
while (time >= LCR_game.nextRacingTickTime)
|
while (time >= LCR_game.nextRacingTickTime)
|
||||||
{
|
{
|
||||||
LCR_LOG2("gonna step racing engine");
|
LCR_LOG2("gonna step racing engine");
|
||||||
|
@ -427,6 +578,9 @@ uint8_t LCR_gameStep(uint32_t time)
|
||||||
LCR_LOG1("crash (big)");
|
LCR_LOG1("crash (big)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int engineIntensity = LCR_carSpeedKMH() * 2;
|
||||||
|
LCR_audioSetEngineIntensity(engineIntensity < 256 ? engineIntensity : 255);
|
||||||
|
|
||||||
LCR_game.nextRacingTickTime += LCR_RACING_TICK_MS;
|
LCR_game.nextRacingTickTime += LCR_RACING_TICK_MS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,102 +590,10 @@ uint8_t LCR_gameStep(uint32_t time)
|
||||||
{
|
{
|
||||||
LCR_LOG2("gonna render next frame");
|
LCR_LOG2("gonna render next frame");
|
||||||
|
|
||||||
LCR_GameUnit physicsInterpolationParam = LCR_GAME_UNIT -
|
|
||||||
((LCR_game.nextRacingTickTime - time) * LCR_GAME_UNIT)
|
|
||||||
/ LCR_RACING_TICK_MS;
|
|
||||||
|
|
||||||
LCR_racingGetCarTransform(carTransform,carTransform + 3,
|
|
||||||
physicsInterpolationParam);
|
|
||||||
|
|
||||||
LCR_rendererSetCarTransform(carTransform,carTransform + 3);
|
|
||||||
|
|
||||||
while (time >= LCR_game.nextRenderFrameTime)
|
while (time >= LCR_game.nextRenderFrameTime)
|
||||||
LCR_game.nextRenderFrameTime += 1000 / LCR_SETTING_FPS;
|
LCR_game.nextRenderFrameTime += 1000 / LCR_SETTING_FPS;
|
||||||
|
|
||||||
LCR_GameUnit offsets[5];
|
LCR_gameDraw3DView();
|
||||||
|
|
||||||
for (int i = 0; i < 5; ++i)
|
|
||||||
offsets[i] = 0;
|
|
||||||
|
|
||||||
if (LCR_game.controlMode == LCR_CONTROL_MODE_FREECAM)
|
|
||||||
{
|
|
||||||
if (LCR_keyStates[LCR_KEY_A])
|
|
||||||
{
|
|
||||||
if (LCR_keyStates[LCR_KEY_UP])
|
|
||||||
offsets[4] = LCR_FREE_CAMERA_TURN_STEP;
|
|
||||||
else if (LCR_keyStates[LCR_KEY_DOWN])
|
|
||||||
offsets[4] -= LCR_FREE_CAMERA_TURN_STEP;
|
|
||||||
|
|
||||||
if (LCR_keyStates[LCR_KEY_RIGHT])
|
|
||||||
offsets[3] -= LCR_FREE_CAMERA_TURN_STEP;
|
|
||||||
else if (LCR_keyStates[LCR_KEY_LEFT])
|
|
||||||
offsets[3] = LCR_FREE_CAMERA_TURN_STEP;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (LCR_keyStates[LCR_KEY_UP])
|
|
||||||
offsets[0] = LCR_FREE_CAMERA_STEP;
|
|
||||||
else if (LCR_keyStates[LCR_KEY_DOWN])
|
|
||||||
offsets[0] -= LCR_FREE_CAMERA_STEP;
|
|
||||||
|
|
||||||
if (LCR_keyStates[LCR_KEY_RIGHT])
|
|
||||||
offsets[1] = LCR_FREE_CAMERA_STEP;
|
|
||||||
else if (LCR_keyStates[LCR_KEY_LEFT])
|
|
||||||
offsets[1] -= LCR_FREE_CAMERA_STEP;
|
|
||||||
}
|
|
||||||
|
|
||||||
LCR_rendererMoveCamera(offsets,offsets + 3);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LCR_rendererCameraFollow();
|
|
||||||
|
|
||||||
#if LCR_ANIMATE_CAR
|
|
||||||
LCR_rendererSetWheelState(LCR_racingGetWheelRotation(),
|
|
||||||
LCR_racingGetWheelSteer() * 2);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
LCR_rendererDraw();
|
|
||||||
|
|
||||||
int val = LCR_carSpeedKMH();
|
|
||||||
|
|
||||||
LCR_audioSetEngineIntensity((2 * val) < 256 ? (2 * val) : 255);
|
|
||||||
|
|
||||||
if (val < 5) // don't show tiny oscillations when still
|
|
||||||
val = 0;
|
|
||||||
|
|
||||||
char str[6];
|
|
||||||
|
|
||||||
str[0] = val >= 100 ? '0' + (val / 100) % 10 : ' ';
|
|
||||||
str[1] = val >= 10 ? '0' + (val / 10) % 10 : ' ';
|
|
||||||
str[2] = '0' + val % 10;
|
|
||||||
str[3] = 0;
|
|
||||||
|
|
||||||
LCR_rendererDrawText(str,
|
|
||||||
LCR_EFFECTIVE_RESOLUTION_X -
|
|
||||||
LCR_rendererComputeTextWidth(str,2) - 20,
|
|
||||||
LCR_EFFECTIVE_RESOLUTION_Y -
|
|
||||||
LCR_rendererComputeTextHeight(2) - 20,0,2);
|
|
||||||
|
|
||||||
val = LCR_racingGetRunTimeMS() / 1000; // seconds
|
|
||||||
|
|
||||||
str[3] = '0' + (val % 60) / 10;
|
|
||||||
str[4] = '0' + val % 10;
|
|
||||||
|
|
||||||
val = (val / 60) % 100; // minutes
|
|
||||||
|
|
||||||
str[0] = '0' + val / 10;
|
|
||||||
str[1] = '0' + val % 10;
|
|
||||||
str[2] = '\'';
|
|
||||||
str[5] = 0;
|
|
||||||
|
|
||||||
LCR_rendererDrawText(str,20,LCR_EFFECTIVE_RESOLUTION_Y -
|
|
||||||
LCR_rendererComputeTextHeight(2) - 20,0,2);
|
|
||||||
|
|
||||||
#if LCR_SETTING_DEBUG_PHYSICS_DRAW
|
|
||||||
LCR_GameUnit camTr[7];
|
|
||||||
LCR_rendererGetCameraTransform(camTr,camTr + 3,camTr + 6);
|
|
||||||
LCR_physicsDebugDraw(camTr,camTr + 3,camTr[6]);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue