engine-c: SDL ground shadows + type-scale + richer bld silhouettes

This commit is contained in:
local-model/engine-L2-grok-4.5 2026-09-19 11:31:00 +02:00
parent 86c0d6c0b0
commit 7d880ed2fd
No known key found for this signature in database
3 changed files with 90 additions and 40 deletions

View file

@ -158,6 +158,34 @@ void render_wrecks(Game *g) {
}
}
/* Per-type live silhouette size (parity with snapshot SHOT_UNIT_SCALE kinds). */
static int unit_screen_sz(UnitType t) {
switch (t) {
case UT_INFANTRY: return 36;
case UT_MUTANT: return 38;
case UT_JEEP:
case UT_BUGGY: return 40;
case UT_FLAME:
case UT_MISSILE:
case UT_MEDIC: return 42;
case UT_ARTILLERY:
case UT_HARVESTER: return 46;
case UT_TANK: return 48;
case UT_BEAST: return 50;
case UT_RAVAGER: return 52;
default: return 41;
}
}
/* Unrotated ground shadow disc (must sit under rotated unit tex). */
static void draw_unit_shadow(SDL_Renderer *ren, int cx, int cy, int rad) {
SDL_SetRenderDrawColor(ren, 55, 48, 28, 200);
for (int j = -rad; j <= rad; j++) {
int half = (int)sqrtf((float)(rad * rad - j * j));
SDL_RenderDrawLine(ren, cx - half + 2, cy + j + 3, cx + half + 2, cy + j + 3);
}
}
void render_units(Game *g) {
for (int i = 0; i < g->unit_count; i++) {
Unit *u = &g->units[i];
@ -166,36 +194,40 @@ void render_units(Game *g) {
int tx = (int)(u->x / TILE), ty = (int)(u->y / TILE);
if (!map_in_bounds(&g->map, tx, ty) || g->map.fog[ty*g->map.w + tx] != 2) continue;
}
/* Match snapshot SHOT_UNIT_SCALE 1.45 → live silhouette ~41px */
int sz = 41;
int sz = unit_screen_sz(u->type);
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);
SDL_Texture *tex = g->spr.unit[u->type][u->faction];
draw_tex_world(g, tex, u->x, u->y, sz, sz, u->heading, 255);
/* selection ring */
/* selection ring — larger for heavy chassis */
if (u->selected) {
int cx = (int)(u->x - g->cam.x), cy = (int)(u->y - g->cam.y);
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) {
int px = cx + (int)(cosf(a*3.14159f/180)*22);
int py = cy + (int)(sinf(a*3.14159f/180)*22);
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 */
if (u->hp < u->max_hp || u->selected) {
int cx = (int)(u->x - g->cam.x), by = (int)(u->y - g->cam.y) - 26;
int bw = 32;
SDL_Rect bg = { cx - bw/2, by, bw, 4 };
int by = cy - sz / 2 - 6;
int bw = sz - 8;
if (bw < 24) bw = 24;
SDL_Rect bg = { cx - bw / 2, by, bw, 4 };
SDL_SetRenderDrawColor(g->ren, 50, 50, 50, 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_Rect fg = { cx - bw / 2, by, (int)(bw * f), 4 };
SDL_SetRenderDrawColor(g->ren, c.r, c.g, c.b, 255);
SDL_RenderFillRect(g->ren, &fg);
/* cargo indicator for harvesters */
if (u->type == UT_HARVESTER && u->cargo > 0) {
SDL_Rect cg = { cx - bw/2, by - 4, (int)(bw * u->cargo / 1000), 2 };
SDL_Rect cg = { cx - bw / 2, by - 4, (int)(bw * u->cargo / 1000), 2 };
SDL_SetRenderDrawColor(g->ren, 230, 190, 70, 255);
SDL_RenderFillRect(g->ren, &cg);
}