Continue replay saving
This commit is contained in:
parent
e43ed793a3
commit
27da348b24
6 changed files with 218 additions and 185 deletions
|
@ -42,6 +42,7 @@ Some of the **gameplay features** include:
|
||||||
- **No codes of censorship, flags, furry mascots or similar political bullshit**. This is just a game.
|
- **No codes of censorship, flags, furry mascots or similar political bullshit**. This is just a game.
|
||||||
- **No "modern" bullshit such as OOP, meme design patterns, scripting and similar nonsense**.
|
- **No "modern" bullshit such as OOP, meme design patterns, scripting and similar nonsense**.
|
||||||
- It is **absolutely and completely public domain free software with ZERO conditions on use** under CC0, it is legally more free that most "FOSS" software, there is no copyleft or credit requirement, you can do ABSOLUTELY anything you want with the project. This is a **selfless project aiming for no benefit of the creator** (include any non-finacial benefit as well), this is made purely to bring more good to the world without gaining any advantage for self.
|
- It is **absolutely and completely public domain free software with ZERO conditions on use** under CC0, it is legally more free that most "FOSS" software, there is no copyleft or credit requirement, you can do ABSOLUTELY anything you want with the project. This is a **selfless project aiming for no benefit of the creator** (include any non-finacial benefit as well), this is made purely to bring more good to the world without gaining any advantage for self.
|
||||||
|
- This game has **PURE SOUL**. No Unity or Unreal, no "retro" imitation shaders, no assets from a store. This isn't an immitation of a 90s game, this IS a 90s game.
|
||||||
|
|
||||||
## Manifesto
|
## Manifesto
|
||||||
|
|
||||||
|
|
5
TODO.txt
5
TODO.txt
|
@ -1,5 +1,10 @@
|
||||||
=========== GENERAL ==============
|
=========== GENERAL ==============
|
||||||
|
|
||||||
|
- make the U-ramp map taller due to new physics
|
||||||
|
- replay format should probably record game version
|
||||||
|
- also there should probably be some version system that says version of
|
||||||
|
physics vs version of everything else; replay could only record physics
|
||||||
|
version (maybe just two or three chars?)
|
||||||
- on 1st map the camera is obscured by the wall at the start, fix it somehow
|
- on 1st map the camera is obscured by the wall at the start, fix it somehow
|
||||||
(not the best first impression)
|
(not the best first impression)
|
||||||
- culling is very slow now, it showed that distance bailout can accelerate it
|
- culling is very slow now, it showed that distance bailout can accelerate it
|
||||||
|
|
6
assets.h
6
assets.h
|
@ -42,7 +42,11 @@ static const char *LCR_texts[] =
|
||||||
"exit",
|
"exit",
|
||||||
|
|
||||||
#define LCR_TEXTS_LOADING 10
|
#define LCR_TEXTS_LOADING 10
|
||||||
"loading"
|
"loading",
|
||||||
|
|
||||||
|
#define LCR_TEXTS_SAVED 11
|
||||||
|
|
||||||
|
"saved"
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: define string for CLI arguments for frontends?
|
// TODO: define string for CLI arguments for frontends?
|
||||||
|
|
167
game.h
167
game.h
|
@ -264,6 +264,7 @@ static inline void LCR_gameDrawPixelXYSafe(unsigned int x, unsigned int y,
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint8_t state;
|
uint8_t state;
|
||||||
|
uint32_t statePrev;
|
||||||
uint32_t stateStartTime;
|
uint32_t stateStartTime;
|
||||||
uint32_t time; ///< Current frame's time.
|
uint32_t time; ///< Current frame's time.
|
||||||
uint32_t frame; ///< Current frame number.
|
uint32_t frame; ///< Current frame number.
|
||||||
|
@ -401,6 +402,7 @@ static inline void LCR_gameDrawPixelXYSafe(unsigned int x, unsigned int y,
|
||||||
void LCR_gameSetState(uint8_t state)
|
void LCR_gameSetState(uint8_t state)
|
||||||
{
|
{
|
||||||
LCR_LOG1("changing state");
|
LCR_LOG1("changing state");
|
||||||
|
LCR_game.statePrev = LCR_game.state;
|
||||||
LCR_game.state = state;
|
LCR_game.state = state;
|
||||||
LCR_game.stateStartTime = LCR_game.time;
|
LCR_game.stateStartTime = LCR_game.time;
|
||||||
}
|
}
|
||||||
|
@ -1049,7 +1051,7 @@ void LCR_gameTimeToStr(uint32_t timeMS, char *str)
|
||||||
str[2] = '\'';
|
str[2] = '\'';
|
||||||
}
|
}
|
||||||
|
|
||||||
LCR_gameDrawPopupMessage(void)
|
void LCR_gameDrawPopupMessage(void)
|
||||||
{
|
{
|
||||||
int textH = LCR_rendererComputeTextHeight(5);
|
int textH = LCR_rendererComputeTextHeight(5);
|
||||||
int textW = LCR_rendererComputeTextWidth(LCR_game.popupStr,5);
|
int textW = LCR_rendererComputeTextWidth(LCR_game.popupStr,5);
|
||||||
|
@ -1151,6 +1153,12 @@ void _LCR_gameDataCharWrite(char c)
|
||||||
printf("%c",c);
|
printf("%c",c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LCR_gameSaveReplay(void)
|
||||||
|
{
|
||||||
|
LCR_LOG0("saving replay");
|
||||||
|
LCR_replayOutputStr(_LCR_gameDataCharWrite);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Helper subroutine, handles user input during main loop frame, EXCEPT for the
|
Helper subroutine, handles user input during main loop frame, EXCEPT for the
|
||||||
driving input (that is handled in the loop itself).
|
driving input (that is handled in the loop itself).
|
||||||
|
@ -1160,9 +1168,80 @@ void LCR_gameHandleInput(void)
|
||||||
int tabSwitchedTo = -1;
|
int tabSwitchedTo = -1;
|
||||||
int scrolled = 0;
|
int scrolled = 0;
|
||||||
|
|
||||||
switch (LCR_game.state)
|
if (LCR_game.state != LCR_GAME_STATE_MENU)
|
||||||
|
{
|
||||||
|
if (LCR_game.state == LCR_GAME_STATE_RUN_FINISHED)
|
||||||
|
{
|
||||||
|
if (LCR_game.keyStates[LCR_KEY_A] == 1)
|
||||||
|
{
|
||||||
|
if (LCR_game.runTimeMS <= LCR_currentMap.targetTime * LCR_RACING_TICK_MS
|
||||||
|
&& !LCR_game.ghost.active)
|
||||||
|
{
|
||||||
|
LCR_LOG1("setting new target time");
|
||||||
|
LCR_currentMap.targetTime = LCR_game.runTimeMS / LCR_RACING_TICK_MS;
|
||||||
|
}
|
||||||
|
|
||||||
|
LCR_gameResetRun(LCR_racing.playingReplay,LCR_game.ghost.active);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (LCR_game.state == LCR_GAME_STATE_RUN_STARTING)
|
||||||
|
{
|
||||||
|
if (LCR_game.time - LCR_game.stateStartTime
|
||||||
|
>= 1000 * LCR_SETTING_COUNTDOWN_SECONDS)
|
||||||
|
{
|
||||||
|
LCR_gameSetState(LCR_GAME_STATE_RUN);
|
||||||
|
LCR_gamePopupMessage("");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LCR_gamePopupNumber(LCR_SETTING_COUNTDOWN_SECONDS -
|
||||||
|
(LCR_game.time - LCR_game.stateStartTime) / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LCR_game.keyStates[LCR_KEY_B] == 1)
|
||||||
|
{
|
||||||
|
LCR_LOG1("menu open");
|
||||||
|
LCR_gameSetState(LCR_GAME_STATE_MENU);
|
||||||
|
LCR_game.menu.selectedItem = 0;
|
||||||
|
}
|
||||||
|
else if (LCR_game.cameraMode == LCR_CAMERA_MODE_FREE)
|
||||||
|
{
|
||||||
|
LCR_GameUnit offsets[5];
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; ++i)
|
||||||
|
offsets[i] = 0;
|
||||||
|
|
||||||
|
if (LCR_game.keyStates[LCR_KEY_A])
|
||||||
|
{
|
||||||
|
if (LCR_game.keyStates[LCR_KEY_UP])
|
||||||
|
offsets[4] = LCR_FREE_CAMERA_TURN_STEP;
|
||||||
|
else if (LCR_game.keyStates[LCR_KEY_DOWN])
|
||||||
|
offsets[4] -= LCR_FREE_CAMERA_TURN_STEP;
|
||||||
|
|
||||||
|
if (LCR_game.keyStates[LCR_KEY_RIGHT])
|
||||||
|
offsets[3] -= LCR_FREE_CAMERA_TURN_STEP;
|
||||||
|
else if (LCR_game.keyStates[LCR_KEY_LEFT])
|
||||||
|
offsets[3] = LCR_FREE_CAMERA_TURN_STEP;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (LCR_game.keyStates[LCR_KEY_UP])
|
||||||
|
offsets[0] = LCR_FREE_CAMERA_STEP;
|
||||||
|
else if (LCR_game.keyStates[LCR_KEY_DOWN])
|
||||||
|
offsets[0] -= LCR_FREE_CAMERA_STEP;
|
||||||
|
|
||||||
|
if (LCR_game.keyStates[LCR_KEY_RIGHT])
|
||||||
|
offsets[1] = LCR_FREE_CAMERA_STEP;
|
||||||
|
else if (LCR_game.keyStates[LCR_KEY_LEFT])
|
||||||
|
offsets[1] -= LCR_FREE_CAMERA_STEP;
|
||||||
|
}
|
||||||
|
|
||||||
|
LCR_rendererMoveCamera(offsets,offsets + 3);
|
||||||
|
}
|
||||||
|
else if (LCR_game.keyStates[LCR_KEY_A] == 1)
|
||||||
|
LCR_gameResetRun(LCR_racing.playingReplay,LCR_game.ghost.active);
|
||||||
|
}
|
||||||
|
else // LCR_GAME_STATE_MENU
|
||||||
{
|
{
|
||||||
case LCR_GAME_STATE_MENU:
|
|
||||||
if (LCR_game.keyStates[LCR_KEY_RIGHT] == 1)
|
if (LCR_game.keyStates[LCR_KEY_RIGHT] == 1)
|
||||||
{
|
{
|
||||||
LCR_LOG1("menu tab right");
|
LCR_LOG1("menu tab right");
|
||||||
|
@ -1226,7 +1305,7 @@ void LCR_gameHandleInput(void)
|
||||||
else if (LCR_game.keyStates[LCR_KEY_B] == 1 && LCR_currentMap.blockCount)
|
else if (LCR_game.keyStates[LCR_KEY_B] == 1 && LCR_currentMap.blockCount)
|
||||||
{
|
{
|
||||||
LCR_LOG1("menu quit");
|
LCR_LOG1("menu quit");
|
||||||
LCR_gameSetState(LCR_GAME_STATE_RUN);
|
LCR_gameSetState(LCR_game.statePrev);
|
||||||
}
|
}
|
||||||
else if (LCR_game.keyStates[LCR_KEY_A] == 1)
|
else if (LCR_game.keyStates[LCR_KEY_A] == 1)
|
||||||
{
|
{
|
||||||
|
@ -1252,12 +1331,20 @@ void LCR_gameHandleInput(void)
|
||||||
LCR_gamePopupNumber(LCR_game.musicOn);
|
LCR_gamePopupNumber(LCR_game.musicOn);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
LCR_audio.on = !LCR_audio.on;
|
LCR_audio.on = !LCR_audio.on;
|
||||||
LCR_gamePopupNumber(LCR_audio.on);
|
LCR_gamePopupNumber(LCR_audio.on);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
if (LCR_game.statePrev == LCR_GAME_STATE_RUN_FINISHED)
|
||||||
|
{
|
||||||
|
LCR_gameSaveReplay();
|
||||||
|
LCR_gamePopupMessage(LCR_texts[LCR_TEXTS_SAVED]);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
LCR_gameSetState(LCR_GAME_STATE_END);
|
LCR_gameSetState(LCR_GAME_STATE_END);
|
||||||
break;
|
break;
|
||||||
|
@ -1297,72 +1384,6 @@ void LCR_gameHandleInput(void)
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LCR_GAME_STATE_RUN_FINISHED:
|
|
||||||
if (LCR_game.keyStates[LCR_KEY_A] == 1)
|
|
||||||
LCR_gameResetRun(LCR_racing.playingReplay,LCR_game.ghost.active);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LCR_GAME_STATE_RUN_STARTING:
|
|
||||||
if (LCR_game.time - LCR_game.stateStartTime
|
|
||||||
>= 1000 * LCR_SETTING_COUNTDOWN_SECONDS)
|
|
||||||
{
|
|
||||||
LCR_gameSetState(LCR_GAME_STATE_RUN);
|
|
||||||
LCR_gamePopupMessage("");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LCR_gamePopupNumber(LCR_SETTING_COUNTDOWN_SECONDS -
|
|
||||||
(LCR_game.time - LCR_game.stateStartTime) / 1000);
|
|
||||||
|
|
||||||
// fall through
|
|
||||||
default:
|
|
||||||
if (LCR_game.keyStates[LCR_KEY_B] == 1)
|
|
||||||
{
|
|
||||||
LCR_LOG1("menu open");
|
|
||||||
LCR_gameSetState(LCR_GAME_STATE_MENU);
|
|
||||||
LCR_game.menu.selectedItem = 0;
|
|
||||||
}
|
|
||||||
else if (LCR_game.cameraMode == LCR_CAMERA_MODE_FREE)
|
|
||||||
{
|
|
||||||
LCR_GameUnit offsets[5];
|
|
||||||
|
|
||||||
for (int i = 0; i < 5; ++i)
|
|
||||||
offsets[i] = 0;
|
|
||||||
|
|
||||||
if (LCR_game.keyStates[LCR_KEY_A])
|
|
||||||
{
|
|
||||||
if (LCR_game.keyStates[LCR_KEY_UP])
|
|
||||||
offsets[4] = LCR_FREE_CAMERA_TURN_STEP;
|
|
||||||
else if (LCR_game.keyStates[LCR_KEY_DOWN])
|
|
||||||
offsets[4] -= LCR_FREE_CAMERA_TURN_STEP;
|
|
||||||
|
|
||||||
if (LCR_game.keyStates[LCR_KEY_RIGHT])
|
|
||||||
offsets[3] -= LCR_FREE_CAMERA_TURN_STEP;
|
|
||||||
else if (LCR_game.keyStates[LCR_KEY_LEFT])
|
|
||||||
offsets[3] = LCR_FREE_CAMERA_TURN_STEP;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (LCR_game.keyStates[LCR_KEY_UP])
|
|
||||||
offsets[0] = LCR_FREE_CAMERA_STEP;
|
|
||||||
else if (LCR_game.keyStates[LCR_KEY_DOWN])
|
|
||||||
offsets[0] -= LCR_FREE_CAMERA_STEP;
|
|
||||||
|
|
||||||
if (LCR_game.keyStates[LCR_KEY_RIGHT])
|
|
||||||
offsets[1] = LCR_FREE_CAMERA_STEP;
|
|
||||||
else if (LCR_game.keyStates[LCR_KEY_LEFT])
|
|
||||||
offsets[1] -= LCR_FREE_CAMERA_STEP;
|
|
||||||
}
|
|
||||||
|
|
||||||
LCR_rendererMoveCamera(offsets,offsets + 3);
|
|
||||||
}
|
|
||||||
else if (LCR_game.keyStates[LCR_KEY_A] == 1)
|
|
||||||
LCR_gameResetRun(LCR_racing.playingReplay,LCR_game.ghost.active);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tabSwitchedTo == 0)
|
if (tabSwitchedTo == 0)
|
||||||
|
@ -1441,7 +1462,9 @@ uint8_t LCR_gameStep(uint32_t time)
|
||||||
LCR_game.state != LCR_GAME_STATE_RUN_FINISHED)
|
LCR_game.state != LCR_GAME_STATE_RUN_FINISHED)
|
||||||
{
|
{
|
||||||
LCR_LOG1("finished");
|
LCR_LOG1("finished");
|
||||||
LCR_replayOutputStr(_LCR_gameDataCharWrite);
|
|
||||||
|
if (LCR_game.runTimeMS <= LCR_currentMap.targetTime * LCR_RACING_TICK_MS)
|
||||||
|
LCR_gameSaveReplay();
|
||||||
|
|
||||||
LCR_audioPlaySound(LCR_SOUND_CLICK);
|
LCR_audioPlaySound(LCR_SOUND_CLICK);
|
||||||
LCR_gameSetState(LCR_GAME_STATE_RUN_FINISHED);
|
LCR_gameSetState(LCR_GAME_STATE_RUN_FINISHED);
|
||||||
|
|
2
map.h
2
map.h
|
@ -164,7 +164,7 @@ struct
|
||||||
uint8_t checkpointCount;
|
uint8_t checkpointCount;
|
||||||
|
|
||||||
uint32_t hash; ///< Hash of the processed binary map.
|
uint32_t hash; ///< Hash of the processed binary map.
|
||||||
uint32_t targetTime;
|
uint32_t targetTime; ///< Target time in physics ticks.
|
||||||
|
|
||||||
char name[LCR_MAP_NAME_MAX_LEN + 1];
|
char name[LCR_MAP_NAME_MAX_LEN + 1];
|
||||||
} LCR_currentMap;
|
} LCR_currentMap;
|
||||||
|
|
2
racing.h
2
racing.h
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
typedef int32_t LCR_GameUnit; ///< abstract game unit
|
typedef int32_t LCR_GameUnit; ///< abstract game unit
|
||||||
|
|
||||||
#define LCR_GAME_UNIT 2048 //1024 ///< length of map square in LCR_GameUnits
|
#define LCR_GAME_UNIT 2048 ///< length of map square in LCR_GameUnits
|
||||||
|
|
||||||
#define LCR_RACING_INPUT_FORW 0x01
|
#define LCR_RACING_INPUT_FORW 0x01
|
||||||
#define LCR_RACING_INPUT_RIGHT 0x02
|
#define LCR_RACING_INPUT_RIGHT 0x02
|
||||||
|
|
Loading…
Reference in a new issue