engine-c: infantry/mutant walk bob via Unit.anim
This commit is contained in:
parent
e78e010495
commit
5bba757785
3 changed files with 34 additions and 7 deletions
|
|
@ -249,6 +249,9 @@ static int live_unit_tracked(UnitType t) {
|
|||
static int live_unit_rolling(UnitType t) {
|
||||
return live_unit_wheeled(t) || live_unit_tracked(t);
|
||||
}
|
||||
static int live_unit_footed(UnitType t) {
|
||||
return t == UT_INFANTRY || t == UT_MUTANT;
|
||||
}
|
||||
|
||||
/* Spoke (wheeled) / hash (tracked) on tyre discs; phase = Unit.anim rad.
|
||||
* Local 30×30 chassis coords match snapshot LX/LY, scaled to live sz. */
|
||||
|
|
@ -333,8 +336,14 @@ void render_units(Game *g) {
|
|||
int cx = (int)(u->x - g->cam.x), cy = (int)(u->y - g->cam.y);
|
||||
/* Ground shadow before rotated body so units lift off sand. */
|
||||
draw_unit_shadow(g->ren, cx, cy, sz / 4 + 4);
|
||||
/* Foot infantry/mutant: vertical body bob; shadow stays grounded. */
|
||||
float bob_y = 0.0f;
|
||||
if (live_unit_footed(u->type)) {
|
||||
bob_y = sinf(u->anim) * 2.5f;
|
||||
cy += (int)(bob_y + (bob_y >= 0.0f ? 0.5f : -0.5f));
|
||||
}
|
||||
SDL_Texture *tex = g->spr.unit[u->type][u->faction];
|
||||
draw_tex_world(g, tex, u->x, u->y, sz, sz, u->heading, 255);
|
||||
draw_tex_world(g, tex, u->x, u->y + bob_y, sz, sz, u->heading, 255);
|
||||
/* rotating spokes / tread hashes (parity with snapshot tyre_mark) */
|
||||
live_draw_tyre_marks(g->ren, u, cx, cy, sz);
|
||||
/* cream heading tick (parity with snapshot LX/LY overlay) */
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ static void draw_unit(Unit *u, int sx, int sy) {
|
|||
uint8_t mr = 70, mg = 65, mb = 58; /* tyre */
|
||||
float c = cosf(u->heading), s = sinf(u->heading);
|
||||
const float sc = SHOT_UNIT_SCALE;
|
||||
float ph = u->anim; /* continuous roll phase for wheeled/tracked */
|
||||
float ph = u->anim; /* continuous roll/walk phase for wheeled/tracked/footed */
|
||||
#define SI(n) ((int)((n) * sc + 0.5f))
|
||||
#define LX(lx, ly) (sx + (int)((((lx)-15)*sc)*c - (((ly)-15)*sc)*s))
|
||||
#define LY(lx, ly) (sy + (int)((((lx)-15)*sc)*s + (((ly)-15)*sc)*c))
|
||||
|
|
@ -138,6 +138,12 @@ static void draw_unit(Unit *u, int sx, int sy) {
|
|||
/* Ground shadow — depth cue so bodies don't melt into sand. */
|
||||
disc(sx + SI(2), sy + SI(3), SI(9), 55, 48, 28);
|
||||
|
||||
/* Foot infantry/mutant: vertical body bob; shadow stays grounded. */
|
||||
if (u->type == UT_INFANTRY || u->type == UT_MUTANT) {
|
||||
float bob = sinf(ph) * 2.5f * sc;
|
||||
sy += (int)(bob + (bob >= 0.0f ? 0.5f : -0.5f));
|
||||
}
|
||||
|
||||
switch (u->type) {
|
||||
case UT_INFANTRY:
|
||||
disc(sx, sy, SI(9), ok, og, ob);
|
||||
|
|
|
|||
|
|
@ -17,11 +17,20 @@ static int unit_tracked(UnitType t) {
|
|||
static int unit_rolling(UnitType t) {
|
||||
return unit_wheeled(t) || unit_tracked(t);
|
||||
}
|
||||
/* Foot infantry/mutants: Unit.anim is continuous walk phase (rad) for body bob. */
|
||||
static int unit_footed(UnitType t) {
|
||||
return t == UT_INFANTRY || t == UT_MUTANT;
|
||||
}
|
||||
static void unit_roll_phase(Unit *u, float sp) {
|
||||
/* ~1 revolution per ~40 world px */
|
||||
u->anim = fmodf(u->anim + (sp / 40.0f) * (float)(2.0 * M_PI), (float)(2.0 * M_PI));
|
||||
if (u->anim < 0.0f) u->anim += (float)(2.0 * M_PI);
|
||||
}
|
||||
static void unit_walk_phase(Unit *u, float sp) {
|
||||
/* ~1 cycle per ~28 world px (faster bob than tyre roll) */
|
||||
u->anim = fmodf(u->anim + (sp / 28.0f) * (float)(2.0 * M_PI), (float)(2.0 * M_PI));
|
||||
if (u->anim < 0.0f) u->anim += (float)(2.0 * M_PI);
|
||||
}
|
||||
|
||||
Unit *unit_by_id(Game *g, int id) {
|
||||
for (int i = 0; i < g->unit_count; i++)
|
||||
|
|
@ -353,8 +362,8 @@ static void unit_combat_step(Game *g, Unit *u, float dt) {
|
|||
particle_burst(g, mx, my, 3, 1, 255, 160, 50);
|
||||
u->atk_cd = ((u->type == UT_ARTILLERY) ? 2.2f
|
||||
: (u->type == UT_INFANTRY ? 0.8f : 1.0f)) / u->reload_mul;
|
||||
/* rolling chassis keep continuous tyre phase — no fire pulse */
|
||||
if (!unit_rolling(u->type)) u->anim = 1.0f;
|
||||
/* rolling/footed keep continuous phase — no fire pulse */
|
||||
if (!unit_rolling(u->type) && !unit_footed(u->type)) u->anim = 1.0f;
|
||||
audio_sfx(1);
|
||||
}
|
||||
return;
|
||||
|
|
@ -423,7 +432,7 @@ static void unit_harvester_step(Game *g, Unit *u, float dt) {
|
|||
int add = (d->cargo - u->cargo > take) ? take : (int)(d->cargo - u->cargo);
|
||||
u->cargo += add;
|
||||
map_deplete_scrap(&g->map, tx, ty, add);
|
||||
if (!unit_rolling(u->type)) u->anim = 1.0f;
|
||||
if (!unit_rolling(u->type) && !unit_footed(u->type)) u->anim = 1.0f;
|
||||
}
|
||||
if (u->cargo >= d->cargo) {
|
||||
int rid = harvester_find_refinery(g, u);
|
||||
|
|
@ -523,8 +532,9 @@ void unit_update(Game *g, float dt) {
|
|||
for (int i = 0; i < g->unit_count; i++) {
|
||||
Unit *u = &g->units[i];
|
||||
if (u->dead) continue;
|
||||
/* infantry/pulse anim decays; wheeled/tracked keep phase radians */
|
||||
if (!unit_rolling(u->type) && u->anim > 0) u->anim -= dt * 3;
|
||||
/* pulse anim decays; wheeled/tracked/footed keep phase radians */
|
||||
if (!unit_rolling(u->type) && !unit_footed(u->type) && u->anim > 0)
|
||||
u->anim -= dt * 3;
|
||||
if (u->repath_timer > 0) u->repath_timer -= dt;
|
||||
if (u->ability_cd > 0) u->ability_cd -= dt;
|
||||
|
||||
|
|
@ -596,6 +606,7 @@ void unit_update(Game *g, float dt) {
|
|||
u->x += (wx - u->x) / d * sp;
|
||||
u->y += (wy - u->y) / d * sp;
|
||||
if (unit_rolling(u->type)) unit_roll_phase(u, sp);
|
||||
else if (unit_footed(u->type)) unit_walk_phase(u, sp);
|
||||
else u->anim = 1.0f;
|
||||
}
|
||||
}
|
||||
|
|
@ -609,6 +620,7 @@ void unit_update(Game *g, float dt) {
|
|||
u->x += (u->dest_x - u->x)/d * sp;
|
||||
u->y += (u->dest_y - u->y)/d * sp;
|
||||
if (unit_rolling(u->type)) unit_roll_phase(u, sp);
|
||||
else if (unit_footed(u->type)) unit_walk_phase(u, sp);
|
||||
else u->anim = 1.0f;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue