Continue ghost
This commit is contained in:
parent
dc66182afb
commit
bcf692d471
3 changed files with 93 additions and 102 deletions
1
TODO.txt
1
TODO.txt
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
=========== BUGS =================
|
=========== BUGS =================
|
||||||
|
|
||||||
|
- why does the ghost stop in front of the finish?
|
||||||
- drawing dithered transparent objects fills z-buffer in the transparent parts
|
- drawing dithered transparent objects fills z-buffer in the transparent parts
|
||||||
and then the geometry behind it isn't drawn <- PARTIALLY FIXED NOW
|
and then the geometry behind it isn't drawn <- PARTIALLY FIXED NOW
|
||||||
|
|
||||||
|
|
142
game.h
142
game.h
|
@ -355,45 +355,36 @@ void _LCR_gameGetNthGhostSample(unsigned int n,
|
||||||
{
|
{
|
||||||
n *= LCR_GHOST_SAMPLE_SIZE;
|
n *= LCR_GHOST_SAMPLE_SIZE;
|
||||||
|
|
||||||
position[0] = LCR_game.ghost.samples[n];
|
position[0] = LCR_game.ghost.samples[n];
|
||||||
n++;
|
n++;
|
||||||
|
|
||||||
position[0] |=
|
position[0] |= ((LCR_GameUnit) (LCR_game.ghost.samples[n] & 0x01)) << 8;
|
||||||
((LCR_GameUnit) (LCR_game.ghost.samples[n] & 0x01)) << 8;
|
position[1] = LCR_game.ghost.samples[n] >> 1;
|
||||||
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] |=
|
n++;
|
||||||
((LCR_GameUnit) (LCR_game.ghost.samples[n] & 0x07)) << 7;
|
position[2] |= ((LCR_GameUnit) (LCR_game.ghost.samples[n] & 0x0f)) << 5;
|
||||||
position[2] = LCR_game.ghost.samples[n] >> 3;
|
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] |=
|
for (int i = 0; i < 3; ++i)
|
||||||
((LCR_GameUnit) (LCR_game.ghost.samples[n] & 0x0f)) << 5;
|
{
|
||||||
|
if (i != 1)
|
||||||
|
position[i] <<= 1;
|
||||||
|
|
||||||
rotation[0] = LCR_game.ghost.samples[n] >> 4;
|
position[i] = (position[i] * LCR_GAME_UNIT) / 16;
|
||||||
|
|
||||||
n++;
|
position[i] -= (LCR_MAP_SIZE_BLOCKS / 2) *
|
||||||
|
(i == 1 ? LCR_GAME_UNIT / 2 : LCR_GAME_UNIT);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
rotation[i] = (rotation[i] * LCR_GAME_UNIT) / 16;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LCR_gameGhostGetTransform(uint32_t frame,
|
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);
|
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)
|
||||||
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] +
|
LCR_GameUnit carTransform[6];
|
||||||
((carTransform[i] - position[i]) * n) /
|
|
||||||
|
// 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;
|
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)
|
void _LCR_gamePrepareGhost(void)
|
||||||
{
|
{
|
||||||
LCR_GameUnit carTransform[6];
|
LCR_GameUnit carTransform[6];
|
||||||
|
@ -448,44 +443,39 @@ void _LCR_gamePrepareGhost(void)
|
||||||
LCR_game.ghost.stretch++;
|
LCR_game.ghost.stretch++;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!LCR_replayHasFinished())
|
while (1)
|
||||||
{
|
{
|
||||||
if (LCR_racing.tick % (LCR_SETTING_GHOST_STEP << LCR_game.ghost.stretch)
|
if (LCR_racing.tick % (LCR_SETTING_GHOST_STEP << LCR_game.ghost.stretch)
|
||||||
== 0)
|
== 0 || LCR_replayHasFinished())
|
||||||
{
|
{
|
||||||
LCR_racingGetCarTransform(carTransform,carTransform + 3,0);
|
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 to 10 bit value:
|
||||||
{
|
carTransform[i] = (carTransform[i] * 16) / LCR_GAME_UNIT;
|
||||||
// convert positions to unsigned 10 bit values
|
|
||||||
|
|
||||||
carTransform[i] += // make non-negative
|
// conv. rotations to 4 bits, we rely on them being non-negative!
|
||||||
(LCR_MAP_SIZE_BLOCKS / 2) * (i == 1 ? LCR_GAME_UNIT / 2 : LCR_GAME_UNIT);
|
carTransform[3 + i] = (carTransform[3 + i] * 16) / 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
|
// format: XXXXXXXX YYYYYYYX ZZZZZYYY AAAAZZZZ CCCCBBBB
|
||||||
|
|
||||||
currentSample[0] = carTransform[0] >> 1;
|
currentSample[0] = carTransform[0] >> 1;
|
||||||
currentSample[1] =
|
currentSample[1] =
|
||||||
((carTransform[0] >> 9) & 0x01) |
|
((carTransform[0] >> 9) & 0x01) | (carTransform[1] << 1);
|
||||||
(carTransform[1] << 1);
|
|
||||||
currentSample[2] =
|
currentSample[2] =
|
||||||
((carTransform[1] >> 7) & 0x07) |
|
((carTransform[1] >> 7) & 0x07) | ((carTransform[2] << 2) & 0xf8);
|
||||||
((carTransform[2] << 2) & 0xf8);
|
|
||||||
currentSample[3] =
|
currentSample[3] =
|
||||||
((carTransform[2] >> 5) & 0x0f) |
|
((carTransform[2] >> 6) & 0x0f) | (carTransform[3] << 4);
|
||||||
(carTransform[3] << 4);
|
|
||||||
currentSample[4] =
|
currentSample[4] =
|
||||||
(carTransform[4] & 0x0f) |
|
(carTransform[4] & 0x0f) | (carTransform[5] << 4);
|
||||||
(carTransform[5] << 4);
|
|
||||||
|
if (LCR_replayHasFinished())
|
||||||
|
break;
|
||||||
|
|
||||||
currentSample += LCR_GHOST_SAMPLE_SIZE;
|
currentSample += LCR_GHOST_SAMPLE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
50
racing.h
50
racing.h
|
@ -1295,34 +1295,34 @@ uint32_t LCR_racingStep(unsigned int input)
|
||||||
LCR_racing.carBody.joints[i].velocity[2] = jv.z;
|
LCR_racing.carBody.joints[i].velocity[2] = jv.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
driftFriction /= 4;
|
driftFriction /= 4;
|
||||||
|
|
||||||
if ((!LCR_racing.carDrifting) &&
|
if ((!LCR_racing.carDrifting) &&
|
||||||
driftFriction > LCR_CAR_DRIFT_THRESHOLD_1)
|
driftFriction > LCR_CAR_DRIFT_THRESHOLD_1)
|
||||||
{
|
{
|
||||||
LCR_LOG1("drift start");
|
LCR_LOG1("drift start");
|
||||||
LCR_racing.carDrifting = 1;
|
LCR_racing.carDrifting = 1;
|
||||||
}
|
}
|
||||||
else if (LCR_racing.carDrifting &&
|
else if (LCR_racing.carDrifting &&
|
||||||
driftFriction < LCR_CAR_DRIFT_THRESHOLD_0)
|
driftFriction < LCR_CAR_DRIFT_THRESHOLD_0)
|
||||||
{
|
{
|
||||||
LCR_LOG1("drift end");
|
LCR_LOG1("drift end");
|
||||||
LCR_racing.carDrifting = 0;
|
LCR_racing.carDrifting = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The following fixes "sticking to a wall" issue by adding a small spin
|
/* The following fixes "sticking to a wall" issue by adding a small spin
|
||||||
to the car when trying to steer at very small velocity. */
|
to the car when trying to steer at very small velocity. */
|
||||||
if (steering &&
|
if (steering &&
|
||||||
(input & (LCR_RACING_INPUT_FORW | LCR_RACING_INPUT_BACK)) &&
|
(input & (LCR_RACING_INPUT_FORW | LCR_RACING_INPUT_BACK)) &&
|
||||||
(LCR_racing.wheelCollisions & 0x0f) &&
|
(LCR_racing.wheelCollisions & 0x0f) &&
|
||||||
LCR_racingGetCarSpeedUnsigned() < (LCR_GAME_UNIT / 25))
|
LCR_racingGetCarSpeedUnsigned() < (LCR_GAME_UNIT / 25))
|
||||||
{
|
{
|
||||||
LCR_LOG2("spinning car a bit");
|
LCR_LOG2("spinning car a bit");
|
||||||
|
|
||||||
TPE_bodySpin(&LCR_racing.carBody,TPE_vec3(0,
|
TPE_bodySpin(&LCR_racing.carBody,TPE_vec3(0,
|
||||||
steering == ((input & LCR_RACING_INPUT_LEFT) != 0) ?
|
steering == ((input & LCR_RACING_INPUT_LEFT) != 0) ?
|
||||||
TPE_F / 32 : -1 * TPE_F / 32,0));
|
TPE_F / 32 : -1 * TPE_F / 32,0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!(input & LCR_RACING_INPUT_LEFT)) &&
|
if ((!(input & LCR_RACING_INPUT_LEFT)) &&
|
||||||
|
|
Loading…
Reference in a new issue