From dc66182afb7448c6a9188ca809fdeea7c7e14f63 Mon Sep 17 00:00:00 2001 From: Miloslav Ciz Date: Wed, 22 Jan 2025 15:35:58 +0100 Subject: [PATCH] Continue ghost --- TODO.txt | 1 + data | 2 + game.h | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 111 insertions(+), 10 deletions(-) create mode 100644 data diff --git a/TODO.txt b/TODO.txt index c2a15bd..24de835 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,5 +1,6 @@ =========== GENERAL ============== +- test if the replay stretching works - replay validation - ghosts: if the replay for the ghost is too long (too many samples for the preallocated array), we can subdivide the sample resolution (i.e. "stretch" diff --git a/data b/data new file mode 100644 index 0000000..f3324aa --- /dev/null +++ b/data @@ -0,0 +1,2 @@ +#Mmap2;4321 1 :*H1k0J :,s0s0 :fd190 +#Rrep2;testmap;482f70f9 00000843:0173:0081:0029:0111:0039:0071:00a3:0061:0169:0051:00b3:0041:0073:0081:0033:0041:0033:0231:0030:0098:0029:0011:0163:00f1:0053:0081:0033:0051:0023:0031:00f0:0032:0023:0131:00b9:0081:0023:00a1:0119:00e1:00c9:0071:0039:00a1:00d3:0021:01f9:0091:0079:0091:0039:0051:0049:0021:0083:0031:0083:0031:0083:0061:0089:0121:00a0:0058:002c:0048:0061:0013:0150:0052:00c0:00a1:0053:0041:0043:0031:0020:0092:0063:0181:0010:00a2:0013:0071:00e0:0028:00e9:0078:00a9:0043:0032:0123:0042:0080:0038:004c:01a8:0050:0032:0033:0101 diff --git a/game.h b/game.h index ae3791f..dd3c8b9 100644 --- a/game.h +++ b/game.h @@ -278,7 +278,7 @@ struct { uint8_t active; uint8_t samples[LCR_SETTING_GHOST_MAX_SAMPLES * LCR_GHOST_SAMPLE_SIZE]; - /**< Samples, each 5 bytes: 9 bits for X and Z, 10 for Z, + /**< Samples, each 5 bytes: 9 bits for X and Z, 10 for Y, 4 for each rotation component. */ uint8_t stretch; /**< Stretch of the base sample step, as a bit shift (i.e. 1 means the step will be 2x as long etc.). This @@ -350,19 +350,90 @@ void LCR_gameResetRun(uint8_t replay, uint8_t ghost) LCR_game.runTimeMS = 0; } +void _LCR_gameGetNthGhostSample(unsigned int n, + LCR_GameUnit position[3], LCR_GameUnit rotation[3]) +{ + n *= LCR_GHOST_SAMPLE_SIZE; + +position[0] = LCR_game.ghost.samples[n]; +n++; + +position[0] |= + ((LCR_GameUnit) (LCR_game.ghost.samples[n] & 0x01)) << 8; +position[1] = LCR_game.ghost.samples[n] >> 1; + +n++; + +position[1] |= +((LCR_GameUnit) (LCR_game.ghost.samples[n] & 0x07)) << 7; +position[2] = LCR_game.ghost.samples[n] >> 3; + +n++; + +position[2] |= + ((LCR_GameUnit) (LCR_game.ghost.samples[n] & 0x0f)) << 5; + +rotation[0] = LCR_game.ghost.samples[n] >> 4; + +n++; + +rotation[1] = LCR_game.ghost.samples[n] & 0x0f; +rotation[2] = LCR_game.ghost.samples[n] >> 4; + +for (int i = 0; i < 3; ++i) +{ + if (i != 2) + position[i] <<= 1; + + position[i] = (position[i] * LCR_GAME_UNIT) / 16; + + position[i] -= + (LCR_MAP_SIZE_BLOCKS / 2) * + (i == 1 ? LCR_GAME_UNIT / 2 : LCR_GAME_UNIT); + + rotation[i] = (rotation[i] * LCR_GAME_UNIT) / 16; +} + +} + void LCR_gameGhostGetTransform(uint32_t frame, LCR_GameUnit position[3], LCR_GameUnit rotation[3]) { - -LCR_racingGetCarTransform(position,rotation,0); + unsigned int n = ((frame >> LCR_game.ghost.stretch) / LCR_SETTING_GHOST_STEP); + +_LCR_gameGetNthGhostSample(n % 64,position,rotation); + + +if (n < LCR_SETTING_GHOST_MAX_SAMPLES - 1) +{ + LCR_GameUnit carTransform[6]; + + // interpolate + + _LCR_gameGetNthGhostSample((n % 64) + 1,carTransform,carTransform + 3); + + n = (frame >> LCR_game.ghost.stretch) % LCR_SETTING_GHOST_STEP; + + for (int i = 0; i < 3; ++i) + { + position[i] = position[i] + + ((carTransform[i] - position[i]) * n) / + LCR_SETTING_GHOST_STEP; + } + + +} + + } + void _LCR_gamePrepareGhost(void) { LCR_GameUnit carTransform[6]; LCR_LOG1("preparing ghost"); - + LCR_gameResetRun(1,0); uint8_t *currentSample = LCR_game.ghost.samples; @@ -384,18 +455,36 @@ void _LCR_gamePrepareGhost(void) { LCR_racingGetCarTransform(carTransform,carTransform + 3,0); - currentSample[0] = carTransform[0]; + +for (int i = 0; i < 3; ++i) +{ + // convert positions to unsigned 10 bit values + +carTransform[i] += // make non-negative + (LCR_MAP_SIZE_BLOCKS / 2) * (i == 1 ? LCR_GAME_UNIT / 2 : LCR_GAME_UNIT); + +// convert to 10 bit value +carTransform[i] = (carTransform[i] * 16) / LCR_GAME_UNIT; + +// conv. rots to 4 bits, we rely on them being non-negative! +carTransform[3 + i] = + (carTransform[3 + i] * 16) / LCR_GAME_UNIT; +} + + // format: XXXXXXXX YYYYYYYX ZZZZZYYY AAAAZZZZ CCCCBBBB + + currentSample[0] = carTransform[0] >> 1; currentSample[1] = - ((carTransform[0] >> 8) & 0x01) | + ((carTransform[0] >> 9) & 0x01) | (carTransform[1] << 1); currentSample[2] = - ((carTransform[1] >> 7) & 0x03) | - (carTransform[2] << 2); + ((carTransform[1] >> 7) & 0x07) | + ((carTransform[2] << 2) & 0xf8); currentSample[3] = - ((carTransform[2] >> 6) & 0x0f) | + ((carTransform[2] >> 5) & 0x0f) | (carTransform[3] << 4); currentSample[4] = - (carTransform[4] >> 4) | + (carTransform[4] & 0x0f) | (carTransform[5] << 4); currentSample += LCR_GHOST_SAMPLE_SIZE; @@ -403,6 +492,15 @@ void _LCR_gamePrepareGhost(void) LCR_racingStep(0); } + + while ( // fill the rest with the last sample + currentSample >= LCR_game.ghost.samples + LCR_GHOST_SAMPLE_SIZE && + currentSample < LCR_game.ghost.samples + + LCR_SETTING_GHOST_MAX_SAMPLES * LCR_GHOST_SAMPLE_SIZE) + { + *currentSample = *(currentSample - LCR_GHOST_SAMPLE_SIZE); + currentSample++; + } } LCR_GameUnit LCR_carSpeedKMH(void)