From bcf692d47196bae29e17da7d854bc9f963473609 Mon Sep 17 00:00:00 2001 From: Miloslav Ciz Date: Wed, 22 Jan 2025 21:39:14 +0100 Subject: [PATCH] Continue ghost --- TODO.txt | 1 + game.h | 144 ++++++++++++++++++++++++++----------------------------- racing.h | 50 +++++++++---------- 3 files changed, 93 insertions(+), 102 deletions(-) diff --git a/TODO.txt b/TODO.txt index 24de835..6ba6875 100644 --- a/TODO.txt +++ b/TODO.txt @@ -23,6 +23,7 @@ =========== BUGS ================= +- why does the ghost stop in front of the finish? - drawing dithered transparent objects fills z-buffer in the transparent parts and then the geometry behind it isn't drawn <- PARTIALLY FIXED NOW diff --git a/game.h b/game.h index dd3c8b9..3cd3964 100644 --- a/game.h +++ b/game.h @@ -355,45 +355,36 @@ void _LCR_gameGetNthGhostSample(unsigned int n, { n *= LCR_GHOST_SAMPLE_SIZE; -position[0] = LCR_game.ghost.samples[n]; -n++; + 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; + position[0] |= ((LCR_GameUnit) (LCR_game.ghost.samples[n] & 0x01)) << 8; + position[1] = LCR_game.ghost.samples[n] >> 1; -n++; + n++; + position[1] |= ((LCR_GameUnit) (LCR_game.ghost.samples[n] & 0x07)) << 7; + position[2] = LCR_game.ghost.samples[n] >> 3; -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++; + n++; + rotation[1] = LCR_game.ghost.samples[n] & 0x0f; + rotation[2] = LCR_game.ghost.samples[n] >> 4; -position[2] |= - ((LCR_GameUnit) (LCR_game.ghost.samples[n] & 0x0f)) << 5; + for (int i = 0; i < 3; ++i) + { + if (i != 1) + position[i] <<= 1; -rotation[0] = LCR_game.ghost.samples[n] >> 4; + position[i] = (position[i] * LCR_GAME_UNIT) / 16; -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; -} + 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, @@ -401,34 +392,38 @@ void LCR_gameGhostGetTransform(uint32_t frame, { unsigned int n = ((frame >> LCR_game.ghost.stretch) / LCR_SETTING_GHOST_STEP); -_LCR_gameGetNthGhostSample(n % 64,position,rotation); + _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) + if (n < LCR_SETTING_GHOST_MAX_SAMPLES - 1) { - position[i] = position[i] + - ((carTransform[i] - position[i]) * n) / + 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; + + // rotations are a bit harder to interpolate (e.g. 1 -> 359 deg.) + carTransform[3 + i] -= rotation[i]; + + if ((carTransform[3 + i] > LCR_GAME_UNIT / 2) || + (carTransform[3 + i] < -1 * LCR_GAME_UNIT / 2)) + carTransform[3 + i] = -1 *( + carTransform[3 + i] > 0 ? + LCR_GAME_UNIT - carTransform[3 + i] : + (-1 * LCR_GAME_UNIT - carTransform[3 + i])); + + rotation[i] = (LCR_GAME_UNIT + (rotation[i] + (n * carTransform[3 + i]) + / LCR_SETTING_GHOST_STEP)) % LCR_GAME_UNIT; + } } - - } - - -} - - void _LCR_gamePrepareGhost(void) { LCR_GameUnit carTransform[6]; @@ -447,45 +442,40 @@ void _LCR_gamePrepareGhost(void) LCR_LOG2("stretching replay step"); LCR_game.ghost.stretch++; } - - while (!LCR_replayHasFinished()) + + while (1) { if (LCR_racing.tick % (LCR_SETTING_GHOST_STEP << LCR_game.ghost.stretch) - == 0) + == 0 || LCR_replayHasFinished()) { LCR_racingGetCarTransform(carTransform,carTransform + 3,0); + for (int i = 0; i < 3; ++i) + { + carTransform[i] += (LCR_MAP_SIZE_BLOCKS / 2) * (i == 1 ? LCR_GAME_UNIT + / 2 : LCR_GAME_UNIT); // make non-negative -for (int i = 0; i < 3; ++i) -{ - // convert positions to unsigned 10 bit values + // convert to 10 bit value: + carTransform[i] = (carTransform[i] * 16) / LCR_GAME_UNIT; -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; -} + // conv. rotations 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] >> 9) & 0x01) | - (carTransform[1] << 1); + ((carTransform[0] >> 9) & 0x01) | (carTransform[1] << 1); currentSample[2] = - ((carTransform[1] >> 7) & 0x07) | - ((carTransform[2] << 2) & 0xf8); + ((carTransform[1] >> 7) & 0x07) | ((carTransform[2] << 2) & 0xf8); currentSample[3] = - ((carTransform[2] >> 5) & 0x0f) | - (carTransform[3] << 4); + ((carTransform[2] >> 6) & 0x0f) | (carTransform[3] << 4); currentSample[4] = - (carTransform[4] & 0x0f) | - (carTransform[5] << 4); + (carTransform[4] & 0x0f) | (carTransform[5] << 4); + + if (LCR_replayHasFinished()) + break; currentSample += LCR_GHOST_SAMPLE_SIZE; } diff --git a/racing.h b/racing.h index c8d16a0..e96d915 100644 --- a/racing.h +++ b/racing.h @@ -1295,34 +1295,34 @@ uint32_t LCR_racingStep(unsigned int input) LCR_racing.carBody.joints[i].velocity[2] = jv.z; } - driftFriction /= 4; + driftFriction /= 4; - if ((!LCR_racing.carDrifting) && - driftFriction > LCR_CAR_DRIFT_THRESHOLD_1) - { - LCR_LOG1("drift start"); - LCR_racing.carDrifting = 1; - } - else if (LCR_racing.carDrifting && - driftFriction < LCR_CAR_DRIFT_THRESHOLD_0) - { - LCR_LOG1("drift end"); - LCR_racing.carDrifting = 0; - } + if ((!LCR_racing.carDrifting) && + driftFriction > LCR_CAR_DRIFT_THRESHOLD_1) + { + LCR_LOG1("drift start"); + LCR_racing.carDrifting = 1; + } + else if (LCR_racing.carDrifting && + driftFriction < LCR_CAR_DRIFT_THRESHOLD_0) + { + LCR_LOG1("drift end"); + LCR_racing.carDrifting = 0; + } - /* The following fixes "sticking to a wall" issue by adding a small spin - to the car when trying to steer at very small velocity. */ - if (steering && - (input & (LCR_RACING_INPUT_FORW | LCR_RACING_INPUT_BACK)) && - (LCR_racing.wheelCollisions & 0x0f) && - LCR_racingGetCarSpeedUnsigned() < (LCR_GAME_UNIT / 25)) - { - LCR_LOG2("spinning car a bit"); + /* The following fixes "sticking to a wall" issue by adding a small spin + to the car when trying to steer at very small velocity. */ + if (steering && + (input & (LCR_RACING_INPUT_FORW | LCR_RACING_INPUT_BACK)) && + (LCR_racing.wheelCollisions & 0x0f) && + LCR_racingGetCarSpeedUnsigned() < (LCR_GAME_UNIT / 25)) + { + LCR_LOG2("spinning car a bit"); - TPE_bodySpin(&LCR_racing.carBody,TPE_vec3(0, - steering == ((input & LCR_RACING_INPUT_LEFT) != 0) ? - TPE_F / 32 : -1 * TPE_F / 32,0)); - } + TPE_bodySpin(&LCR_racing.carBody,TPE_vec3(0, + steering == ((input & LCR_RACING_INPUT_LEFT) != 0) ? + TPE_F / 32 : -1 * TPE_F / 32,0)); + } } if ((!(input & LCR_RACING_INPUT_LEFT)) &&