Add particles

This commit is contained in:
Miloslav Ciz 2025-04-20 19:38:13 +02:00
parent 06c1d1c42e
commit d905718bab
6 changed files with 105 additions and 51 deletions

View file

@ -1,7 +1,5 @@
=========== GENERAL ============== =========== GENERAL ==============
- add simple particle effects for grass/dirt/drift? Can be just a few squares
animated from the projected backwheels.
- fix the ramp map again due to new physics - fix the ramp map again due to new physics
- keyboard ghosting is an issue, particularly when initiating drift with brake - keyboard ghosting is an issue, particularly when initiating drift with brake
(arrow keys must be used with S for braking for left drift to work) -- think (arrow keys must be used with S for braking for left drift to work) -- think
@ -78,6 +76,8 @@
=========== HANDLED ============== =========== HANDLED ==============
- MAP4: one triangle in top section is missing! - MAP4: one triangle in top section is missing!
- add simple particle effects for grass/dirt/drift? Can be just a few squares
animated from the projected backwheels.
- FPS logging for optim - FPS logging for optim
- 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

2
data
View file

@ -133,3 +133,5 @@ details
:+018 :f213 :!v05 :f311 :+018 :f213 :!v05 :f311
#RLC1;00LC1;8bd6e314 0000475:0011:0199:0041:00a9:0051:0029:0091:0049:0041:0049:0041:0249:0091:0015:0031:0019:01a1:0049:0041:0119:0031:0069:0041:0049:0041:0059:0031:00d9:0031:00f9:0021:0155:0041:01d3:0061:0113:00f1:0043:00c1:0083:0051:0203:0021:0513:0031 #RLC1;00LC1;8bd6e314 0000475:0011:0199:0041:00a9:0051:0029:0091:0049:0041:0049:0041:0249:0091:0015:0031:0019:01a1:0049:0041:0119:0031:0069:0041:0049:0041:0059:0031:00d9:0031:00f9:0021:0155:0041:01d3:0061:0113:00f1:0043:00c1:0083:0051:0203:0021:0513:0031
#RLC1;00LC1;8bd6e314 0000455:0011:0169:0041:00a9:0031:0049:00a1:0059:0051:0059:0031:01e9:0071:0045:0039:00e1:0019:00d1:0079:0041:0049:0021:0049:0031:0039:0031:0069:0071:0029:0041:00c3:0041:00e9:0021:0145:0041:0253:01b1:00b3:0051:00a9:0071:0073:0031:00a3:0021:03b3:0031:00a9:0021:0073:0021 #RLC1;00LC1;8bd6e314 0000455:0011:0169:0041:00a9:0031:0049:00a1:0059:0051:0059:0031:01e9:0071:0045:0039:00e1:0019:00d1:0079:0041:0049:0021:0049:0031:0039:0031:0069:0071:0029:0041:00c3:0041:00e9:0021:0145:0041:0253:01b1:00b3:0051:00a9:0071:0073:0031:00a3:0021:03b3:0031:00a9:0021:0073:0021
#RLCtiny5;00LCtiny5;5c14d8b6 0000306:00a1:0083:0041:0019:0051:0049:0041:0029:00a1:00c9:0051:0073:00e1:0019:00e1:0013:0211:0049:0051:0033:0051:0039:00c1:0023:00f1:0049:0041:0033:0071:0013:0041:0053:0061:0093:0041:0043:0041:0175:0041:00a3:0041:00b9:0021
#BLCtiny5;

14
game.h
View file

@ -1621,6 +1621,20 @@ uint8_t LCR_gameStep(uint32_t time)
uint32_t events = paused ? 0 : LCR_racingStep(input); uint32_t events = paused ? 0 : LCR_racingStep(input);
#if LCR_SETTING_PARTICLES
LCR_rendererSetParticles(0);
if (LCR_racingGetCarSpeedUnsigned() > 60)
{
if (LCR_racingCurrentGroundMaterial() == LCR_BLOCK_MATERIAL_GRASS)
LCR_rendererSetParticles(0x538a);
else if (LCR_racingCurrentGroundMaterial() == LCR_BLOCK_MATERIAL_DIRT)
LCR_rendererSetParticles(0x8c2b);
else if (LCR_racingCarIsDrifting())
LCR_rendererSetParticles(0x4208);
}
#endif
#ifdef LCR_FPS_GET_MS #ifdef LCR_FPS_GET_MS
LCR_game.physicsFrameMS += LCR_FPS_GET_MS - frameTime; LCR_game.physicsFrameMS += LCR_FPS_GET_MS - frameTime;
LCR_game.physicsFramesMeasured++; LCR_game.physicsFramesMeasured++;

View file

@ -127,6 +127,8 @@ struct
LCR_GameUnit carSpeeds[2]; /**< Signed speed in game units per tick (negative LCR_GameUnit carSpeeds[2]; /**< Signed speed in game units per tick (negative
if backwards) and its previous value. */ if backwards) and its previous value. */
uint8_t groundMaterial; ///< Material currently under car wheels.
uint16_t crashState; uint16_t crashState;
uint8_t playingReplay; uint8_t playingReplay;
@ -154,6 +156,16 @@ TPE_Vec3 _LCR_TPE_vec3DividePlain(TPE_Vec3 v, TPE_Unit d)
return v; return v;
} }
static inline int LCR_racingCarIsDrifting(void)
{
return LCR_racing.carDrifting;
}
static inline uint8_t LCR_racingCurrentGroundMaterial(void)
{
return LCR_racing.groundMaterial;
}
/** /**
Initializes replay for recording. Initializes replay for recording.
*/ */
@ -1139,11 +1151,12 @@ uint32_t LCR_racingStep(unsigned int input)
uint32_t result = 0; uint32_t result = 0;
TPE_Vec3 carForw, carRight, carUp, carVel; TPE_Vec3 carForw, carRight, carUp, carVel;
uint8_t groundMat = LCR_BLOCK_MATERIAL_CONCRETE; // material under wheels
uint8_t onAccel = 0; // standing on accelerator? uint8_t onAccel = 0; // standing on accelerator?
int groundBlockIndex = -1; int groundBlockIndex = -1;
TPE_Unit driftFriction = 0; // average wheel friction (absolute value) TPE_Unit driftFriction = 0; // average wheel friction (absolute value)
LCR_racing.groundMaterial = LCR_BLOCK_MATERIAL_CONCRETE;
if (LCR_racing.playingReplay) if (LCR_racing.playingReplay)
{ {
if (LCR_racing.tick == 0) if (LCR_racing.tick == 0)
@ -1233,13 +1246,13 @@ uint32_t LCR_racingStep(unsigned int input)
result |= LCR_RACING_EVENT_FAN; result |= LCR_RACING_EVENT_FAN;
} }
groundMat = LCR_mapBlockGetMaterial( LCR_racing.groundMaterial = LCR_mapBlockGetMaterial(
LCR_currentMap.blocks + groundBlockIndex * LCR_BLOCK_SIZE); LCR_currentMap.blocks + groundBlockIndex * LCR_BLOCK_SIZE);
} }
} }
LCR_racing.carBody.friction = LCR_racing.carBody.friction =
_LCR_applyMaterialFactor(LCR_CAR_FORWARD_FRICTION,groundMat); _LCR_applyMaterialFactor(LCR_CAR_FORWARD_FRICTION,LCR_racing.groundMaterial);
if (onAccel) if (onAccel)
{ {
@ -1309,13 +1322,15 @@ uint32_t LCR_racingStep(unsigned int input)
{ {
if (input & LCR_RACING_INPUT_FORW) if (input & LCR_RACING_INPUT_FORW)
{ {
_LCR_racingWheelAccelerate(0,carForw,groundMat,onAccel); _LCR_racingWheelAccelerate(0,carForw,LCR_racing.groundMaterial,onAccel);
_LCR_racingWheelAccelerate(1,carForw,groundMat,onAccel); _LCR_racingWheelAccelerate(1,carForw,LCR_racing.groundMaterial,onAccel);
} }
else if (input & LCR_RACING_INPUT_BACK) else if (input & LCR_RACING_INPUT_BACK)
{ {
_LCR_racingWheelAccelerate(0,TPE_vec3TimesPlain(carForw,-1),groundMat,onAccel); _LCR_racingWheelAccelerate(0,TPE_vec3TimesPlain(carForw,-1),
_LCR_racingWheelAccelerate(1,TPE_vec3TimesPlain(carForw,-1),groundMat,onAccel); LCR_racing.groundMaterial,onAccel);
_LCR_racingWheelAccelerate(1,TPE_vec3TimesPlain(carForw,-1),
LCR_racing.groundMaterial,onAccel);
} }
} }
@ -1347,7 +1362,7 @@ uint32_t LCR_racingStep(unsigned int input)
_LCR_applyMaterialFactor( _LCR_applyMaterialFactor(
LCR_racing.carDrifting ? LCR_racing.carDrifting ?
(LCR_CAR_STEER_FRICTION * LCR_CAR_DRIFT_FACTOR) / 8 : (LCR_CAR_STEER_FRICTION * LCR_CAR_DRIFT_FACTOR) / 8 :
LCR_CAR_STEER_FRICTION,groundMat)) / TPE_F); LCR_CAR_STEER_FRICTION,LCR_racing.groundMaterial)) / TPE_F);
driftFriction += TPE_vec3Len(fric); driftFriction += TPE_vec3Len(fric);

View file

@ -112,51 +112,24 @@ struct
unsigned int flatAndTransparent; /**< If non-zero, transparent (dithered) unsigned int flatAndTransparent; /**< If non-zero, transparent (dithered)
polygons will be drawn without texture, polygons will be drawn without texture,
with color stored in this variable. */ with color stored in this variable. */
#if LCR_SETTING_PARTICLES
uint16_t particleColor; /**< 0x0000 means no particles active. */
#endif
} LCR_renderer; } LCR_renderer;
/**
void aaa(void) Sets particle effects drawn around wheels. The parameter says particle color,
0x0000 turns particles off.
*/
void LCR_rendererSetParticles(uint16_t color)
{ {
printf("BAD TRIS (%d):\n",LCR_renderer.mapModel.triangleCount); #if LCR_SETTING_PARTICLES
LCR_renderer.particleColor = color;
for (int i = 0; i < LCR_renderer.mapModel.triangleCount; ++i) #else
{ return;
TPE_Unit sss = #endif
TPE_max(
TPE_abs(LCR_renderer.mapModel.vertices[
LCR_renderer.mapModel.triangles[i * 3] * 3] -
LCR_renderer.mapModel.vertices[
LCR_renderer.mapModel.triangles[i * 3 + 1] * 3]),
TPE_abs(LCR_renderer.mapModel.vertices[
LCR_renderer.mapModel.triangles[i * 3 + 1] * 3] -
LCR_renderer.mapModel.vertices[
LCR_renderer.mapModel.triangles[i * 3 + 2] * 3])
);
if (sss > LCR_RENDERER_UNIT * 2)
printf(" - %d (%d %d %d, %d %d %d, %d %d %d) %d %d %d\n",i,
LCR_renderer.mapModel.vertices[LCR_renderer.mapModel.triangles[3 * i]],
LCR_renderer.mapModel.vertices[LCR_renderer.mapModel.triangles[3 * i] + 1],
LCR_renderer.mapModel.vertices[LCR_renderer.mapModel.triangles[3 * i] + 2],
LCR_renderer.mapModel.vertices[LCR_renderer.mapModel.triangles[3 * i + 1]],
LCR_renderer.mapModel.vertices[LCR_renderer.mapModel.triangles[3 * i + 1] + 1],
LCR_renderer.mapModel.vertices[LCR_renderer.mapModel.triangles[3 * i + 1] + 2],
LCR_renderer.mapModel.vertices[LCR_renderer.mapModel.triangles[3 * i + 2]],
LCR_renderer.mapModel.vertices[LCR_renderer.mapModel.triangles[3 * i + 2] + 1],
LCR_renderer.mapModel.vertices[LCR_renderer.mapModel.triangles[3 * i + 2] + 2],
LCR_renderer.mapModel.triangles[3 * i],
LCR_renderer.mapModel.triangles[3 * i + 1],
LCR_renderer.mapModel.triangles[3 * i + 2]
);
}
} }
void _LCR_rendererSetModelTransform(S3L_Model3D *model, void _LCR_rendererSetModelTransform(S3L_Model3D *model,
LCR_GameUnit position[3], LCR_GameUnit rotation[3]) LCR_GameUnit position[3], LCR_GameUnit rotation[3])
{ {
@ -2100,6 +2073,51 @@ void LCR_rendererDraw3D(void)
LCR_renderer.frame++; LCR_renderer.frame++;
#if LCR_SETTING_PARTICLES
if (LCR_renderer.particleColor)
{
S3L_Vec4 p, r, s;
S3L_rotationToDirections(LCR_renderer.carModel->transform.rotation,
LCR_RENDERER_UNIT / 2,&p,&r,0);
#define LCR_PARTICLE_SIZE (16 << (LCR_EFFECTIVE_RESOLUTION_X / 640))
p.w = LCR_PARTICLE_SIZE;
r.x /= 2;
r.y /= 2;
r.z /= 2;
S3L_vec3Add(&p,LCR_renderer.carModel->transform.translation);
for (int i = 0; i < 2; ++i) // for both wheels
{
S3L_vec3Add(&p,r);
S3L_project3DPointToScreen(p,LCR_renderer.scene.camera,&s);
if (s.w > 0)
for (int j = 0; j < 4; ++j) // 4 particles
{
int pSize =
((LCR_renderer.frame + 4 * j) << 2) % (2 * LCR_PARTICLE_SIZE);
LCR_rendererDrawRect(
s.x - pSize / 2 + ((j % 2) ? -1 * pSize : pSize),
s.y - pSize / 2 + ((j / 2) ? -1 * pSize : pSize),
pSize,pSize,LCR_renderer.particleColor,1);
}
r.x *= -2;
r.y *= -2;
r.z *= -2;
}
}
#undef LCR_PARTICLE_SIZE
#endif
LCR_LOG2("3D rendering (end)"); LCR_LOG2("3D rendering (end)");
LCR_LOG2("rendering frame (end)"); LCR_LOG2("rendering frame (end)");
} }

View file

@ -221,7 +221,7 @@
#ifndef LCR_SETTING_CAR_RENDER_DISTANCE #ifndef LCR_SETTING_CAR_RENDER_DISTANCE
/** Distance in blocks at which player and ghost car will be seen. */ /** Distance in blocks at which player and ghost car will be seen. */
#define LCR_SETTING_CAR_RENDER_DISTANCE 25 #define LCR_SETTING_CAR_RENDER_DISTANCE 30
#endif #endif
#ifndef LCR_SETTING_CRASH_SOUNDS #ifndef LCR_SETTING_CRASH_SOUNDS
@ -241,6 +241,11 @@
#define LCR_SETTING_CAR_TINT 0x07 #define LCR_SETTING_CAR_TINT 0x07
#endif #endif
#ifndef LCR_SETTING_PARTICLES
/** Can turn particle effects on/off. */
#define LCR_SETTING_PARTICLES 1
#endif
#ifndef LCR_SETTING_ONLY_SMALL_MAPS #ifndef LCR_SETTING_ONLY_SMALL_MAPS
/** Turning this on will only include the small maps in the internal data /** Turning this on will only include the small maps in the internal data
file. This option exists for weak devices that couldn't handle big maps file. This option exists for weak devices that couldn't handle big maps