Add time to replays
This commit is contained in:
parent
9d2c6108b1
commit
8d0adf66eb
2 changed files with 44 additions and 13 deletions
5
TODO.txt
5
TODO.txt
|
@ -1,12 +1,13 @@
|
|||
=========== GENERAL ==============
|
||||
|
||||
- replay validation
|
||||
- add time slow down setting
|
||||
- the horizon on background seems too low? maybe add setting to shift it a bit?
|
||||
- add argc/argv to gameInit? could be used to quickly start maps, verify
|
||||
replays etc.
|
||||
- maybe each map could have a target time embedded: when beaten, the map would
|
||||
be marked as such
|
||||
- player name (modifyable via resource file)
|
||||
- player name (modifiable via resource file)
|
||||
- popup messages? would be useful for several things: showing checkpoint times,
|
||||
showing changes in menu etc.
|
||||
- make the racing module usable by itself, e.g. to allow making tools for
|
||||
|
@ -17,7 +18,6 @@
|
|||
lower memory)
|
||||
- at the end check error handling, make sure the game handles garbage data in
|
||||
resource file etc.
|
||||
- replay format
|
||||
|
||||
=========== BUGS =================
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
|||
=========== HANDLED ==============
|
||||
|
||||
- allow stopping car rotation in air like in Trackmania
|
||||
- replay format
|
||||
- prevent time overflow! stop incrementing level frame once it's at maximum
|
||||
- car shadow? probably would have to be done as screen space effect with
|
||||
z-buffer (shadow as 3D model would require collision detection and would make
|
||||
|
|
52
racing.h
52
racing.h
|
@ -13,13 +13,14 @@
|
|||
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
|
||||
current input state.
|
||||
- Replay text format: first there is hexadeciaml hash of the map (exactly 8
|
||||
characters), then the name of the map follows immediately, then the
|
||||
character ';', then the replay data, i.e. the sries of 16 bit words in
|
||||
hexadecimal. The blocks (but nothing else) may be preceeded or followed by
|
||||
blank characters. All hexadecimal letters must be lowercase. The word
|
||||
00000000 may optinally be used to terminate the replay, the rest of the
|
||||
string will be ignored.
|
||||
- Replay text format: first there is the name of the map terminated by ';',
|
||||
then hexadecimal hash of the map follows (exactly 8 characters), then
|
||||
blank character follows, then achieved time as a series of decimal digits
|
||||
expressing the number of milliseconds, then a non-decimal character follows,
|
||||
then the replay data, i.e. the series of 16 bit words in hexadecimal. The
|
||||
blocks (but nothing else) may be preceeded or followed by blank characters.
|
||||
All hexadecimal letters must be lowercase. The word 00000000 may optinally
|
||||
be used to terminate the replay, the rest of the string will be ignored.
|
||||
*/
|
||||
|
||||
typedef int32_t LCR_GameUnit; ///< abstract game unit
|
||||
|
@ -70,11 +71,13 @@ typedef int32_t LCR_GameUnit; ///< abstract game unit
|
|||
#define LCR_CAR_GRASS_FACTOR 5
|
||||
#define LCR_CAR_DIRT_FACTOR 3
|
||||
#define LCR_CAR_ICE_FACTOR 1
|
||||
#define LCR_CAR_DRIFT_FACTOR 2 ///< only affects steering friction
|
||||
#define LCR_CAR_DRIFT_FACTOR 2 ///< only affects steering friction
|
||||
|
||||
#define LCR_CAR_JOINTS 5
|
||||
#define LCR_CAR_CONNECTIONS 10
|
||||
|
||||
#define LCR_REPLAY_EVENT_END 0xff ///< special event fed to replay at the end
|
||||
|
||||
struct
|
||||
{
|
||||
TPE_World physicsWorld;
|
||||
|
@ -114,6 +117,7 @@ struct
|
|||
// for playing
|
||||
uint16_t currentEvent;
|
||||
uint16_t currentFrame;
|
||||
uint32_t achievedTime;
|
||||
} LCR_replay;
|
||||
|
||||
/**
|
||||
|
@ -137,6 +141,7 @@ void LCR_replayInitRecording(void)
|
|||
{
|
||||
LCR_LOG1("initializing replay recording");
|
||||
LCR_replay.eventCount = 0;
|
||||
LCR_replay.achievedTime = 0;
|
||||
}
|
||||
|
||||
void LCR_replayInitPlaying(void)
|
||||
|
@ -172,6 +177,15 @@ void LCR_replayOutputStr(void (*printChar)(char))
|
|||
hash /= 16;
|
||||
}
|
||||
|
||||
printChar(' ');
|
||||
|
||||
// 8 decimal digits are enough to record 24 hours
|
||||
|
||||
#define PUTD(order) printChar('0' + (LCR_replay.achievedTime / order) % 10);
|
||||
PUTD(10000000) PUTD(1000000) PUTD(100000) PUTD(10000)
|
||||
PUTD(1000) PUTD(100) PUTD(10) PUTD(1)
|
||||
#undef PUTD
|
||||
|
||||
for (int i = 0; i < LCR_replay.eventCount; ++i)
|
||||
{
|
||||
uint16_t e = LCR_replay.events[i];
|
||||
|
@ -179,8 +193,8 @@ void LCR_replayOutputStr(void (*printChar)(char))
|
|||
|
||||
for (int j = 0; j < 4; ++j)
|
||||
{
|
||||
printChar(_LCR_hexDigit(e % 16));
|
||||
e /= 16;
|
||||
printChar(_LCR_hexDigit((e >> 12) & 0x0f));
|
||||
e <<= 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,12 +230,23 @@ int LCR_replayHasFinished(void)
|
|||
/**
|
||||
Records another input event. Returns 1 on success, or 0 if the event couldn't
|
||||
be recorded. The event is only added if necessary, i.e. this function can
|
||||
safely be called every frame without worrying about inflating its size.
|
||||
(and must) be called every frame without worrying about inflating its size.
|
||||
When the run ends, the LCR_REPLAY_EVENT_END has to be fed!
|
||||
*/
|
||||
int LCR_replayRecordEvent(uint32_t frame, uint8_t input)
|
||||
{
|
||||
LCR_LOG2("recording replay event");
|
||||
|
||||
if (LCR_replay.achievedTime)
|
||||
return 1; // already finished
|
||||
|
||||
if (input == LCR_REPLAY_EVENT_END)
|
||||
{
|
||||
LCR_replay.achievedTime = frame;
|
||||
LCR_LOG1("replay recording finished");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if LCR_SETTING_REPLAY_MAX_SIZE > 0
|
||||
uint8_t previousInput = 0;
|
||||
uint32_t previousFrame = 0;
|
||||
|
@ -1363,7 +1388,12 @@ uint32_t LCR_racingStep(unsigned int input)
|
|||
}
|
||||
|
||||
if (valid)
|
||||
{
|
||||
result |= LCR_RACING_EVENT_FINISHED;
|
||||
|
||||
if (!LCR_racing.playingReplay)
|
||||
LCR_replayRecordEvent(LCR_racing.tick,LCR_REPLAY_EVENT_END);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue