Fix replays

This commit is contained in:
Miloslav Ciz 2025-03-10 21:33:49 +01:00
parent c4bd226d8f
commit 588acd1e7f
6 changed files with 34 additions and 23 deletions

View file

@ -62,7 +62,6 @@
=========== BUGS ================= =========== BUGS =================
- replays are bugged, seem to not steer
- immediately after starting the map countdown seems to be lower - immediately after starting the map countdown seems to be lower
- the pinch collision test seems to sometimes stop the car e.g. after falling - the pinch collision test seems to sometimes stop the car e.g. after falling
from bigger height or when running into ramp at high speed (or not?) - FIX from bigger height or when running into ramp at high speed (or not?) - FIX
@ -71,6 +70,7 @@
- sometimes getting a SLIGHTLY slower time counts as beating it (prolly - sometimes getting a SLIGHTLY slower time counts as beating it (prolly
conversion fail) (SEEMS FIXED NOW) conversion fail) (SEEMS FIXED NOW)
- replays are bugged, seem to not steer
- replay format should probably record game version - replay format should probably record game version
- also there should probably be some version system that says version of - also there should probably be some version system that says version of
physics vs version of everything else; replay could only record physics physics vs version of everything else; replay could only record physics

4
data
View file

@ -4,6 +4,7 @@ Mmap2;4321 1 :=s0s0 :-u0s0 :;w0s0 :,y0s0 :.s0u0 :Is0w0 :'s1y0
#Btestmap; #Btestmap;
#Rrrr;00LCtiny1;8ecff5c0 0000531:0011:03a9:0041:0179:0021:0059:0031:0039:0091:0049:0031:0253:0041:0013:0051:0053:0041:0023:0051:0043:0031:0064:0016:0022:0026:01a4:002c:0040:0042:0013:0081:0053:0102:0050:0021:0049:00e1:0043:0091:0049:01a8:0119:0130:0072:0026:0082:0048:0039:0111:0050:0022:0036:0132:0018:0049:0151:0033:0121:00c3:0041:0059:0041:00d0:0048:0050 #Rrrr;00LCtiny1;8ecff5c0 0000531:0011:03a9:0041:0179:0021:0059:0031:0039:0091:0049:0031:0253:0041:0013:0051:0053:0041:0023:0051:0043:0031:0064:0016:0022:0026:01a4:002c:0040:0042:0013:0081:0053:0102:0050:0021:0049:00e1:0043:0091:0049:01a8:0119:0130:0072:0026:0082:0048:0039:0111:0050:0022:0036:0132:0018:0049:0151:0033:0121:00c3:0041:0059:0041:00d0:0048:0050
#Rrrr;00LCtiny1;8ecff5c0 000531:0011:03a9:0041:0179:0021:059:0031:0039:0091:0049:0031:023:0041:0013:0051:0053:0041:00230051:0043:0031:0064:0016:0022:026:01a4:002c:0040:0042:0013:008:0053:0102:0050:0021:0049:00e1:043:0091:0049:01a8:0119:0130:002:0026:0082:0048:0039:0111:00500022:0036:0132:0018:0049:0151:033:0121:00c3:0041:0059:0041:00d:0048:0050
#Maaaaa;4321 0 #Maaaaa;4321 0
:*B2vJ :*B2vJ
@ -34,3 +35,6 @@ finish
#RLCtiny1;00LCtiny1;8ecff5c0 000381:00a1:02b9:0041:0265:0061:029:0141:0263:0041:0043:0051:003:0041:0033:0031:0033:0052:00260042:0096:0092:0026:0022:0086:02e:001c:0072:0043:00f1:0033:012:0039:0061:0069:0041:00b5:0021:263:0031:00c9:0011 #RLCtiny1;00LCtiny1;8ecff5c0 000381:00a1:02b9:0041:0265:0061:029:0141:0263:0041:0043:0051:003:0041:0033:0031:0033:0052:00260042:0096:0092:0026:0022:0086:02e:001c:0072:0043:00f1:0033:012:0039:0061:0069:0041:00b5:0021:263:0031:00c9:0011
#BLCtiny1; #BLCtiny1;
#RLCtiny1;00LCtiny1;8ecff5c0 000585:00c1:0179:0031:0119:0021:2d5:0039:00d1:0079:0051:00e9:001:0123:0041:0083:00b1:0199:01b101d0:00d1:0063:0072:0040:00c2:033:0011:00d3:00e1:00d3:0122:002:0081:0023:0091:0040:0051:0039:011:0050:0038:003c:0128:0012:003:01e1:0069:0071:00c5:0049:00380059:0151:0053:00c1:0219:0021 #RLCtiny1;00LCtiny1;8ecff5c0 000585:00c1:0179:0031:0119:0021:2d5:0039:00d1:0079:0051:00e9:001:0123:0041:0083:00b1:0199:01b101d0:00d1:0063:0072:0040:00c2:033:0011:00d3:00e1:00d3:0122:002:0081:0023:0091:0040:0051:0039:011:0050:0038:003c:0128:0012:003:01e1:0069:0071:00c5:0049:00380059:0151:0053:00c1:0219:0021
#Rtestmap;00testmap;88676224 000193:0011:0029:0121:0019:0061:0f9:0051:0049:0081:00f9:0028:000:0078:0049:0011:0039:0051:00f00044:0026:0122:0020:0052:0070:038:0029:00c8:0159
#RLCtiny1;00LCtiny1;8ecff5c0 000531:0011:03a9:0041:0179:0021:059:0031:0039:0091:0049:0031:023:0041:0013:0051:0053:0041:00230051:0043:0031:0064:0016:0022:026:01a4:002c:0040:0042:0013:008:0053:0102:0050:0021:0049:00e1:043:0091:0049:01a8:0119:0130:002:0026:0082:0048:0039:0111:00500022:0036:0132:0018:0049:0151:033:0121:00c3:0041:0059:0041:00d:0048:0050
#RLCtiny1;00LCtiny1;8ecff5c0 0000513:04f1:0199:0031:01e9:0021:01a9:00e1:0069:0011:0193:0041:00a3:0031:0093:0061:0033:0071:0095:0071:0019:0038:0149:0068:0069:00b8:0129:0068:0010:0032:0026:00d2:002a:0018:0079:0141:0043:0061:0073:0071:00b5:0041:0049:0098:0089:00d1:0049:0071:0053:0041:00a3:0031:00b9:0041

View file

@ -41,6 +41,10 @@ void LCR_appendDataStr(const char *str)
rewind(dataFile); rewind(dataFile);
else else
{ {
#if LCR_SETTING_LOG_LEVEL > 1
printf("SDL: appending data \"%s\"\n",str);
#endif
fclose(dataFile); fclose(dataFile);
dataFile = fopen(DATA_FILE_NAME,"a"); dataFile = fopen(DATA_FILE_NAME,"a");

22
game.h
View file

@ -233,7 +233,7 @@ static inline void LCR_gameDrawPixelXYSafe(unsigned int x, unsigned int y,
#include "renderer.h" #include "renderer.h"
#define LCR_MENU_MAX_ITEMS 9 // don't change #define LCR_MENU_MAX_ITEMS 9 // don't change
#define LCR_RESOURCE_ITEM_CHUNK (LCR_MENU_MAX_ITEMS - 1) #define LCR_DATA_ITEM_CHUNK (LCR_MENU_MAX_ITEMS - 1)
#define LCR_MENU_TABS 4 #define LCR_MENU_TABS 4
#if LCR_SETTING_GHOST_MAX_SAMPLES == 0 #if LCR_SETTING_GHOST_MAX_SAMPLES == 0
@ -884,9 +884,9 @@ void _LCR_gameDataCharWrite(char c)
while (_LCR_gameDataFileBuffer[i]) while (_LCR_gameDataFileBuffer[i])
{ {
if (i >= LCR_GAME_DATA_FILE_BUFFER_SIZE - 2) if (i >= LCR_GAME_DATA_FILE_BUFFER_SIZE - 3)
{ {
_LCR_gameDataFileBuffer[i] = c; _LCR_gameDataFileBuffer[i + 1] = c;
LCR_appendDataStr(_LCR_gameDataFileBuffer); LCR_appendDataStr(_LCR_gameDataFileBuffer);
_LCR_gameDataFileBuffer[0] = 0; _LCR_gameDataFileBuffer[0] = 0;
return; return;
@ -906,7 +906,7 @@ void _LCR_gameDataCharWrite(char c)
} }
/** /**
Loads up to LCR_RESOURCE_ITEM_CHUNK items of given type, starting at given Loads up to LCR_DATA_ITEM_CHUNK items of given type, starting at given
index (among items of the same type). This will also load the menu item names. index (among items of the same type). This will also load the menu item names.
*/ */
void LCR_gameLoadDataFileChunk(unsigned int startIndex, char magicNumber) void LCR_gameLoadDataFileChunk(unsigned int startIndex, char magicNumber)
@ -959,7 +959,7 @@ void LCR_gameLoadDataFileChunk(unsigned int startIndex, char magicNumber)
state = 255; state = 255;
LCR_game.menu.itemCount++; LCR_game.menu.itemCount++;
if (LCR_game.menu.itemCount >= LCR_RESOURCE_ITEM_CHUNK) if (LCR_game.menu.itemCount >= LCR_DATA_ITEM_CHUNK)
break; break;
} }
else else
@ -1369,7 +1369,7 @@ void LCR_gameHandleInput(void)
else if (LCR_game.menu.selectedTab != 0 && else if (LCR_game.menu.selectedTab != 0 &&
LCR_game.dataFile.firstItemIndex != 0) LCR_game.dataFile.firstItemIndex != 0)
{ {
LCR_game.menu.selectedItem = LCR_RESOURCE_ITEM_CHUNK - 1; LCR_game.menu.selectedItem = LCR_DATA_ITEM_CHUNK - 1;
LCR_audioPlaySound(LCR_SOUND_CLICK); LCR_audioPlaySound(LCR_SOUND_CLICK);
scrolled = -1; scrolled = -1;
} }
@ -1392,7 +1392,7 @@ void LCR_gameHandleInput(void)
LCR_audioPlaySound(LCR_SOUND_CLICK); LCR_audioPlaySound(LCR_SOUND_CLICK);
} }
else if (LCR_game.dataFile.firstItemIndex + else if (LCR_game.dataFile.firstItemIndex +
LCR_RESOURCE_ITEM_CHUNK < LCR_game.dataFile.itemsTotal) LCR_DATA_ITEM_CHUNK < LCR_game.dataFile.itemsTotal)
{ {
LCR_game.menu.selectedItem = 0; LCR_game.menu.selectedItem = 0;
LCR_audioPlaySound(LCR_SOUND_CLICK); LCR_audioPlaySound(LCR_SOUND_CLICK);
@ -1434,7 +1434,8 @@ void LCR_gameHandleInput(void)
break; break;
case 3: case 3:
if (LCR_game.statePrev == LCR_GAME_STATE_RUN_FINISHED) if (LCR_game.statePrev == LCR_GAME_STATE_RUN_FINISHED &&
!LCR_racing.playingReplay)
LCR_gameSaveReplay(); LCR_gameSaveReplay();
else else
LCR_gamePopupMessage(LCR_texts[LCR_TEXTS_FAIL]); LCR_gamePopupMessage(LCR_texts[LCR_TEXTS_FAIL]);
@ -1488,7 +1489,7 @@ void LCR_gameHandleInput(void)
{ {
LCR_gameLoadDataFileChunk( LCR_gameLoadDataFileChunk(
(tabSwitchedTo > 0) ? 0 : (LCR_game.dataFile.firstItemIndex + (tabSwitchedTo > 0) ? 0 : (LCR_game.dataFile.firstItemIndex +
scrolled * LCR_RESOURCE_ITEM_CHUNK), scrolled * LCR_DATA_ITEM_CHUNK),
LCR_game.menu.selectedTab == 1 ? 'M' : 'R'); LCR_game.menu.selectedTab == 1 ? 'M' : 'R');
if (LCR_game.menu.selectedTab == 1) if (LCR_game.menu.selectedTab == 1)
@ -1559,7 +1560,8 @@ uint8_t LCR_gameStep(uint32_t time)
{ {
LCR_LOG1("finished"); LCR_LOG1("finished");
if (LCR_game.runTime <= LCR_currentMap.targetTime) if (LCR_game.runTime <= LCR_currentMap.targetTime &&
!LCR_racing.playingReplay)
{ {
LCR_gameSaveReplay(); LCR_gameSaveReplay();

View file

@ -43,11 +43,12 @@ game and immediately load a map, which is handy when creating new maps.
~~~ GAMEPLAY ~~~ ~~~ GAMEPLAY ~~~
In Licar, unlike in most other racing games, you only race against time, i.e. In Licar, unlike in most other racing games, the player always only attempts
you are alone on the track. There is an option to race against a replay ghost, time attacks, i.e. you only race against time with no physical opponents on the
but the ghost still cannot collide with your car, so the point remains that your track with you. There is an option to race against a replay ghost, but that
final time depends purely on how well you drive, opponents cannot spoil your still cannot collide with your car, so the point remains that your final time
results by crashing with you or blocking your path. depends purely on how well you drive, opponents cannot spoil your results by
crashing with you or blocking your path.
The objective of every map is to drive from start to finish (red octahedron) as The objective of every map is to drive from start to finish (red octahedron) as
fast as possible while collecting all the checkpoints (CP, green octahedron) fast as possible while collecting all the checkpoints (CP, green octahedron)

View file

@ -17,13 +17,6 @@
because the offset is too big (input didn't change for more than 2^12 because the offset is too big (input didn't change for more than 2^12
frames), there must simply be inserted an extra word that just copies the frames), there must simply be inserted an extra word that just copies the
current input state. current input state.
- Physics engine version: LCR_RACING_VERSION1 and LCR_RACING_VERSION2 define
a two-character version string of this module that determines compatibility
of replays. Whenever a change is made to this module that changes the
behavior of physics, the version string must be changed because replays
will stop being compatible. It's still possible to make other changes to
this module (such as optimizations or comments) without having to change
physics version.
- Replay text format: first there are two characters saying the physics - Replay text format: first there are two characters saying the physics
engine version, then immediately the name of the map terminated by ';', then engine version, then immediately the name of the map terminated by ';', then
hexadecimal hash of the map follows (exactly 8 characters), then blank hexadecimal hash of the map follows (exactly 8 characters), then blank
@ -34,6 +27,13 @@
other characters (possible comments). All hexadecimal letters must be other characters (possible comments). All hexadecimal letters must be
lowercase. The word 00000000 may optinally be used to terminate the replay, lowercase. The word 00000000 may optinally be used to terminate the replay,
the rest of the string will be ignored. the rest of the string will be ignored.
- Physics engine version: LCR_RACING_VERSION1 and LCR_RACING_VERSION2 define
a two-character version string of this module that determines compatibility
of replays. Whenever a change is made to this module that changes the
behavior of physics, the version string must be changed because replays
will stop being compatible. It's still possible to make other changes to
this module (such as optimizations or comments) without having to change
physics version.
*/ */
typedef int32_t LCR_GameUnit; ///< abstract game unit typedef int32_t LCR_GameUnit; ///< abstract game unit