diff --git a/engine-c/src/render.c b/engine-c/src/render.c index 98fae58..222c2d8 100644 --- a/engine-c/src/render.c +++ b/engine-c/src/render.c @@ -200,30 +200,43 @@ void render_units(Game *g) { draw_unit_shadow(g->ren, cx, cy, sz / 4 + 4); SDL_Texture *tex = g->spr.unit[u->type][u->faction]; draw_tex_world(g, tex, u->x, u->y, sz, sz, u->heading, 255); + /* cream heading tick (parity with snapshot LX/LY overlay) */ + { + float tick = (float)(sz / 2 + 6); + int hx = cx + (int)(cosf(u->heading) * tick); + int hy = cy + (int)(sinf(u->heading) * tick); + SDL_SetRenderDrawColor(g->ren, 250, 245, 210, 255); + SDL_RenderDrawLine(g->ren, cx, cy, hx, hy); + SDL_SetRenderDrawColor(g->ren, 255, 250, 220, 220); + SDL_RenderDrawLine(g->ren, cx + 1, cy, hx + 1, hy); + } /* selection ring — larger for heavy chassis */ if (u->selected) { int rad = (u->type == UT_TANK || u->type == UT_BEAST || u->type == UT_RAVAGER) ? sz / 2 + 4 : sz / 2 + 2; - SDL_SetRenderDrawColor(g->ren, 120, 255, 120, 220); - for (int a = 0; a < 360; a += 12) { + SDL_SetRenderDrawColor(g->ren, 255, 245, 60, 220); + for (int a = 0; a < 360; a += 10) { int px = cx + (int)(cosf(a * 3.14159f / 180) * rad); int py = cy + (int)(sinf(a * 3.14159f / 180) * rad); SDL_RenderDrawPoint(g->ren, px, py); } } - /* health bar */ + /* HP bar: green→red strip like snapshot */ if (u->hp < u->max_hp || u->selected) { - int by = cy - sz / 2 - 6; - int bw = sz - 8; + int by = cy - sz / 2 - 8; + int bw = sz - 6; if (bw < 24) bw = 24; + SDL_Rect outline = { cx - bw / 2 - 1, by - 1, bw + 2, 6 }; + SDL_SetRenderDrawColor(g->ren, 20, 18, 14, 255); + SDL_RenderFillRect(g->ren, &outline); SDL_Rect bg = { cx - bw / 2, by, bw, 4 }; - SDL_SetRenderDrawColor(g->ren, 50, 50, 50, 255); + SDL_SetRenderDrawColor(g->ren, 55, 48, 36, 255); SDL_RenderFillRect(g->ren, &bg); float f = u->hp / u->max_hp; - SDL_Color c = (u->faction == FACTION_SURVIVOR) ? (SDL_Color){55,235,55,255} - : (SDL_Color){255,40,255,255}; - SDL_Rect fg = { cx - bw / 2, by, (int)(bw * f), 4 }; - SDL_SetRenderDrawColor(g->ren, c.r, c.g, c.b, 255); + if (f < 0) f = 0; if (f > 1) f = 1; + Uint8 hr = (Uint8)(255 * (1.0f - f)), hg = (Uint8)(230 * f); + SDL_Rect fg = { cx - bw / 2, by, (int)(bw * f + 0.5f), 4 }; + SDL_SetRenderDrawColor(g->ren, hr, hg, 40, 255); SDL_RenderFillRect(g->ren, &fg); /* cargo indicator for harvesters */ if (u->type == UT_HARVESTER && u->cargo > 0) { diff --git a/engine-c/src/units.c b/engine-c/src/units.c index ee1064a..999b918 100644 --- a/engine-c/src/units.c +++ b/engine-c/src/units.c @@ -62,12 +62,15 @@ void unit_apply_damage(Game *g, Unit *u, float dmg) { float eff = dmg - u->defense * 0.25f; if (eff < 1) eff = 1; u->hp -= eff; - particle_burst(g, u->x, u->y, 3, 2, 255, 200, 80); + particle_burst(g, u->x, u->y, 4, 2, 255, 200, 80); if (u->hp <= 0 && !u->dead) { u->dead = 1; u->state = STATE_DEAD; - particle_burst(g, u->x, u->y, 14, 1, 255, 140, 40); - particle_burst(g, u->x, u->y, 8, 3, 90, 80, 70); + /* denser KKND2-like death: fire core + debris ring + smoke */ + particle_burst(g, u->x, u->y, 18, 1, 255, 140, 40); + particle_burst(g, u->x, u->y, 10, 3, 90, 80, 70); + particle_burst(g, u->x + 6, u->y - 4, 8, 0, 110, 100, 90); + particle_burst(g, u->x - 5, u->y + 5, 6, 2, 255, 220, 90); audio_sfx(2); if (g->cam.shake < 7) g->cam.shake = 7; if (u->faction == g->human) @@ -320,8 +323,13 @@ static void unit_combat_step(Game *g, Unit *u, float dt) { if (u->atk_cd <= 0) { int kind = (u->type == UT_ARTILLERY || u->type == UT_MISSILE || u->type == UT_TANK) ? 1 : 0; - if (tu) bullet_spawn(g, u->x, u->y, tu->id, -1, u->attack, u->faction, kind); - else bullet_spawn(g, u->x, u->y, -1, tb->id, u->attack, u->faction, kind); + /* muzzle offset along heading so shot/live FX sit at barrel tip */ + float mx = u->x + cosf(u->heading) * 14.0f; + float my = u->y + sinf(u->heading) * 14.0f; + if (tu) bullet_spawn(g, mx, my, tu->id, -1, u->attack, u->faction, kind); + else bullet_spawn(g, mx, my, -1, tb->id, u->attack, u->faction, kind); + particle_burst(g, mx, my, 5, 2, 255, 230, 120); + 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; u->anim = 1.0f;