engine-c: wreck draw + type variety + clash seed for KKND2 battlefield
Snapshot/live wreck silhouettes (type-aware hulls, scorch/smoke), seed ~22 clash wrecks in place_showcase, reset wreck ring on match setup.
This commit is contained in:
parent
252cfd8175
commit
d54d38e8df
5 changed files with 176 additions and 5 deletions
|
|
@ -121,6 +121,46 @@ static void place_start(Game *g, Faction f) {
|
|||
|
||||
/* KKND2-like showcase: extra human base structures + diverse roster +
|
||||
* enemy raid pack near the camera so fog/snapshot show combat. */
|
||||
/* Seed a battlefield wreck (type-aware hulls drawn in snapshot/live render). */
|
||||
static void spawn_showcase_wreck(Game *g, UnitType type, Faction faction,
|
||||
float x, float y, float rot) {
|
||||
if (g->wreck_count >= MAX_WRECKS) return;
|
||||
Wreck *w = &g->wrecks[g->wreck_next];
|
||||
w->x = x; w->y = y; w->type = type;
|
||||
w->faction = faction; w->rot = rot;
|
||||
g->wreck_next = (g->wreck_next + 1) % MAX_WRECKS;
|
||||
if (g->wreck_count < MAX_WRECKS) g->wreck_count++;
|
||||
}
|
||||
|
||||
/* ~22 charred hulls around primary + secondary clash for KKND2 plate shots. */
|
||||
static void seed_clash_wrecks(Game *g, Faction human, Faction enemy,
|
||||
float rx, float ry, float rx2, float ry2) {
|
||||
/* primary NE clash — mixed sides, varied chassis */
|
||||
spawn_showcase_wreck(g, UT_TANK, human, rx - 22, ry + 8, 0.6f);
|
||||
spawn_showcase_wreck(g, UT_TANK, enemy, rx + 14, ry - 12, 2.4f);
|
||||
spawn_showcase_wreck(g, UT_RAVAGER, enemy, rx + 28, ry + 6, 1.1f);
|
||||
spawn_showcase_wreck(g, UT_BUGGY, human, rx - 8, ry - 18, 3.5f);
|
||||
spawn_showcase_wreck(g, UT_BUGGY, enemy, rx + 6, ry + 20, 0.2f);
|
||||
spawn_showcase_wreck(g, UT_JEEP, human, rx - 30, ry - 4, 4.8f);
|
||||
spawn_showcase_wreck(g, UT_ARTILLERY, human, rx - 40, ry + 16, 5.2f);
|
||||
spawn_showcase_wreck(g, UT_FLAME, enemy, rx + 36, ry - 8, 2.0f);
|
||||
spawn_showcase_wreck(g, UT_MISSILE, enemy, rx + 18, ry + 28, 1.7f);
|
||||
spawn_showcase_wreck(g, UT_INFANTRY, human, rx - 14, ry + 24, 0.9f);
|
||||
spawn_showcase_wreck(g, UT_INFANTRY, enemy, rx + 4, ry - 26, 3.1f);
|
||||
spawn_showcase_wreck(g, UT_MUTANT, enemy, rx + 22, ry + 14, 4.2f);
|
||||
spawn_showcase_wreck(g, UT_BEAST, enemy, rx + 42, ry + 10, 0.4f);
|
||||
spawn_showcase_wreck(g, UT_HARVESTER, human, rx - 48, ry - 10, 5.9f);
|
||||
/* secondary SE clash */
|
||||
spawn_showcase_wreck(g, UT_TANK, human, rx2 - 16, ry2 + 6, 1.3f);
|
||||
spawn_showcase_wreck(g, UT_TANK, enemy, rx2 + 12, ry2 - 8, 3.8f);
|
||||
spawn_showcase_wreck(g, UT_BUGGY, enemy, rx2 + 22, ry2 + 14, 0.7f);
|
||||
spawn_showcase_wreck(g, UT_JEEP, human, rx2 - 24, ry2 - 4, 2.6f);
|
||||
spawn_showcase_wreck(g, UT_FLAME, human, rx2 - 8, ry2 + 18, 4.5f);
|
||||
spawn_showcase_wreck(g, UT_RAVAGER, enemy, rx2 + 30, ry2 + 4, 1.9f);
|
||||
spawn_showcase_wreck(g, UT_INFANTRY, human, rx2 + 4, ry2 - 16, 5.5f);
|
||||
spawn_showcase_wreck(g, UT_MUTANT, enemy, rx2 + 16, ry2 + 22, 0.1f);
|
||||
}
|
||||
|
||||
static void place_showcase(Game *g, Faction human, Faction enemy) {
|
||||
int sx = g->map.spawn_x[human], sy = g->map.spawn_y[human];
|
||||
float wx, wy; map_tile_to_world(sx, sy, &wx, &wy);
|
||||
|
|
@ -672,6 +712,9 @@ static void place_showcase(Game *g, Faction human, Faction enemy) {
|
|||
unit_select_single(g, i, 1);
|
||||
nsel++;
|
||||
}
|
||||
|
||||
/* lasting hulls already on the plate (SHOT_T too short for natural deaths) */
|
||||
seed_clash_wrecks(g, human, enemy, rx, ry, rx2, ry2);
|
||||
}
|
||||
|
||||
void engine_setup_match(Game *g, int mission_id) {
|
||||
|
|
@ -695,6 +738,7 @@ void engine_setup_match(Game *g, int mission_id) {
|
|||
g->unit_count = 0; g->unit_next_id = 1;
|
||||
g->bld_count = 0; g->bld_next_id = 1;
|
||||
g->bullet_count = 0; g->particle_count = 0;
|
||||
g->wreck_count = 0; g->wreck_next = 0;
|
||||
g->sel_count = 0; g->placing = 0;
|
||||
g->time = 0; g->frames = 0; g->winner = 0;
|
||||
g->ai_timer = 5.0f;
|
||||
|
|
|
|||
|
|
@ -181,6 +181,9 @@ void render_buildings(Game *g) {
|
|||
}
|
||||
}
|
||||
|
||||
/* Forward: defined below with live unit sizing. */
|
||||
static int unit_screen_sz(UnitType t);
|
||||
|
||||
void render_wrecks(Game *g) {
|
||||
for (int i = 0; i < g->wreck_count; i++) {
|
||||
Wreck *w = &g->wrecks[i];
|
||||
|
|
@ -188,11 +191,43 @@ void render_wrecks(Game *g) {
|
|||
if (!map_in_bounds(&g->map, tx, ty)) continue;
|
||||
if (g->map.fog[ty * g->map.w + tx] == 0) continue;
|
||||
SDL_Color c = faction_color(w->faction);
|
||||
Uint8 dr = (Uint8)(c.r * 0.38f), dg = (Uint8)(c.g * 0.38f), db = (Uint8)(c.b * 0.38f);
|
||||
int sx = (int)(w->x - g->cam.x), sy = (int)(w->y - g->cam.y);
|
||||
SDL_SetRenderDrawColor(g->ren, c.r/2, c.g/2, c.b/2, 200);
|
||||
SDL_RenderFillRect(g->ren, &(SDL_Rect){ sx-12, sy-9, 24, 18 });
|
||||
SDL_SetRenderDrawColor(g->ren, 30, 28, 26, 200);
|
||||
SDL_RenderFillRect(g->ren, &(SDL_Rect){ sx-8, sy-5, 16, 10 });
|
||||
int sz = unit_screen_sz(w->type);
|
||||
int hw = sz / 3, hh = sz / 4;
|
||||
if (hw < 10) hw = 10;
|
||||
if (hh < 7) hh = 7;
|
||||
/* scorch under hull */
|
||||
SDL_SetRenderDrawColor(g->ren, 42, 36, 28, 180);
|
||||
SDL_RenderFillRect(g->ren, &(SDL_Rect){ sx - hw - 2, sy - hh + 2, hw * 2 + 4, hh * 2 });
|
||||
SDL_SetRenderDrawColor(g->ren, 28, 24, 20, 220);
|
||||
SDL_RenderFillRect(g->ren, &(SDL_Rect){ sx - hw, sy - hh, hw * 2, hh * 2 });
|
||||
SDL_SetRenderDrawColor(g->ren, dr, dg, db, 210);
|
||||
SDL_RenderFillRect(g->ren, &(SDL_Rect){ sx - hw + 2, sy - hh + 2, hw * 2 - 4, hh * 2 - 4 });
|
||||
/* type cues: tracks / wheels / crumpled body */
|
||||
if (w->type == UT_TANK || w->type == UT_RAVAGER || w->type == UT_BEAST
|
||||
|| w->type == UT_ARTILLERY) {
|
||||
SDL_SetRenderDrawColor(g->ren, 48, 42, 36, 230);
|
||||
SDL_RenderFillRect(g->ren, &(SDL_Rect){ sx - hw, sy - hh / 2, 4, hh });
|
||||
SDL_RenderFillRect(g->ren, &(SDL_Rect){ sx + hw - 4, sy - hh / 2, 4, hh });
|
||||
SDL_RenderFillRect(g->ren, &(SDL_Rect){ sx - 4, sy - hh - 2, 8, 6 }); /* dead turret */
|
||||
} else if (w->type == UT_HARVESTER || w->type == UT_BUGGY || w->type == UT_JEEP
|
||||
|| w->type == UT_FLAME || w->type == UT_MISSILE || w->type == UT_MEDIC) {
|
||||
SDL_SetRenderDrawColor(g->ren, 30, 28, 26, 230);
|
||||
SDL_RenderFillRect(g->ren, &(SDL_Rect){ sx - hw + 2, sy - hh + 2, 6, 6 });
|
||||
SDL_RenderFillRect(g->ren, &(SDL_Rect){ sx + hw - 8, sy - hh + 2, 6, 6 });
|
||||
SDL_RenderFillRect(g->ren, &(SDL_Rect){ sx - hw + 2, sy + hh - 8, 6, 6 });
|
||||
SDL_RenderFillRect(g->ren, &(SDL_Rect){ sx + hw - 8, sy + hh - 8, 6, 6 });
|
||||
} else {
|
||||
/* infantry/mutant crumpled kit */
|
||||
SDL_SetRenderDrawColor(g->ren, 48, 42, 36, 200);
|
||||
SDL_RenderFillRect(g->ren, &(SDL_Rect){ sx - 5, sy - 4, 10, 8 });
|
||||
SDL_RenderFillRect(g->ren, &(SDL_Rect){ sx + 3, sy + 2, 5, 4 });
|
||||
}
|
||||
/* thin smoke puff */
|
||||
SDL_SetRenderDrawColor(g->ren, 70, 68, 64, 160);
|
||||
SDL_RenderFillRect(g->ren, &(SDL_Rect){ sx + 2, sy - hh - 6, 5, 5 });
|
||||
SDL_RenderFillRect(g->ren, &(SDL_Rect){ sx + 5, sy - hh - 10, 3, 3 });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -456,6 +456,85 @@ static void draw_unit(Unit *u, int sx, int sy) {
|
|||
#undef SI
|
||||
}
|
||||
|
||||
/* Charred wreck silhouettes — dim faction paint + scorch, type-aware hull. */
|
||||
static void draw_wreck(Wreck *w, int sx, int sy) {
|
||||
uint8_t br = faction_r(w->faction), bg = faction_g(w->faction), bb = faction_b(w->faction);
|
||||
uint8_t dr, dg, db;
|
||||
darken3(br, bg, bb, 0.38f, &dr, &dg, &db);
|
||||
uint8_t ok = 28, og = 24, ob = 20;
|
||||
uint8_t ch = 48, cg = 42, cb = 36; /* char */
|
||||
float c = cosf(w->rot), s = sinf(w->rot);
|
||||
const float sc = SHOT_UNIT_SCALE * 0.92f;
|
||||
#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))
|
||||
|
||||
disc(sx + SI(2), sy + SI(4), SI(10), 42, 36, 28); /* scorch stain */
|
||||
|
||||
switch (w->type) {
|
||||
case UT_HARVESTER:
|
||||
fill_rect(sx - SI(14), sy - SI(9), SI(28), SI(18), ok, og, ob);
|
||||
fill_rect(sx - SI(12), sy - SI(7), SI(24), SI(14), dr, dg, db);
|
||||
fill_rect(LX(6, 12) - SI(1), LY(6, 12) - SI(1), SI(10), SI(8), ch, cg, cb);
|
||||
disc(LX(8, 8), LY(8, 8), SI(4), ok, og, ob);
|
||||
disc(LX(22, 8), LY(22, 8), SI(4), ok, og, ob);
|
||||
disc(LX(8, 22), LY(8, 22), SI(4), ok, og, ob);
|
||||
disc(LX(22, 22), LY(22, 22), SI(4), ok, og, ob);
|
||||
fill_rect(sx - SI(4), sy - SI(2), SI(10), SI(5), 55, 48, 40); /* torn bed */
|
||||
break;
|
||||
case UT_TANK:
|
||||
case UT_RAVAGER:
|
||||
case UT_BEAST:
|
||||
fill_rect(sx - SI(13), sy - SI(8), SI(26), SI(16), ok, og, ob);
|
||||
fill_rect(sx - SI(11), sy - SI(6), SI(22), SI(12), dr, dg, db);
|
||||
fill_rect(sx - SI(12), sy - SI(3), SI(4), SI(8), ch, cg, cb); /* track */
|
||||
fill_rect(sx + SI(8), sy - SI(3), SI(4), SI(8), ch, cg, cb);
|
||||
disc(sx, sy - SI(2), SI(6), ok, og, ob);
|
||||
disc(sx, sy - SI(2), SI(4), ch, cg, cb); /* dead turret */
|
||||
line(LX(15, 8), LY(15, 8), LX(15, -2), LY(15, -2), 40, 36, 30); /* bent barrel */
|
||||
break;
|
||||
case UT_ARTILLERY:
|
||||
case UT_MISSILE:
|
||||
fill_rect(sx - SI(12), sy - SI(7), SI(24), SI(14), ok, og, ob);
|
||||
fill_rect(sx - SI(10), sy - SI(5), SI(20), SI(10), dr, dg, db);
|
||||
disc(LX(8, 20), LY(8, 20), SI(4), ok, og, ob);
|
||||
disc(LX(22, 20), LY(22, 20), SI(4), ok, og, ob);
|
||||
line(LX(12, 12), LY(12, 12), LX(22, 2), LY(22, 2), ch, cg, cb);
|
||||
break;
|
||||
case UT_BUGGY:
|
||||
case UT_JEEP:
|
||||
case UT_FLAME:
|
||||
case UT_MEDIC:
|
||||
fill_rect(sx - SI(11), sy - SI(7), SI(22), SI(14), ok, og, ob);
|
||||
fill_rect(sx - SI(9), sy - SI(5), SI(18), SI(10), dr, dg, db);
|
||||
disc(LX(8, 8), LY(8, 8), SI(4), ok, og, ob);
|
||||
disc(LX(22, 8), LY(22, 8), SI(4), ok, og, ob);
|
||||
disc(LX(8, 22), LY(8, 22), SI(4), ok, og, ob);
|
||||
disc(LX(22, 22), LY(22, 22), SI(4), ok, og, ob);
|
||||
fill_rect(LX(10, 10) - SI(1), LY(10, 10) - SI(1), SI(8), SI(5), ch, cg, cb);
|
||||
break;
|
||||
case UT_INFANTRY:
|
||||
case UT_MUTANT:
|
||||
disc(sx + SI(1), sy + SI(2), SI(6), ok, og, ob);
|
||||
disc(sx, sy, SI(5), dr, dg, db);
|
||||
disc(sx - SI(3), sy + SI(4), SI(3), ch, cg, cb); /* crumpled kit */
|
||||
disc(sx + SI(4), sy + SI(3), SI(2), 40, 36, 30);
|
||||
break;
|
||||
default:
|
||||
fill_rect(sx - SI(10), sy - SI(6), SI(20), SI(12), ok, og, ob);
|
||||
fill_rect(sx - SI(8), sy - SI(4), SI(16), SI(8), dr, dg, db);
|
||||
disc(sx - SI(5), sy + SI(2), SI(3), ch, cg, cb);
|
||||
disc(sx + SI(6), sy - SI(1), SI(3), ch, cg, cb);
|
||||
break;
|
||||
}
|
||||
/* smoke puff cue */
|
||||
disc(sx + SI(3), sy - SI(8), SI(3), 70, 68, 64);
|
||||
disc(sx + SI(5), sy - SI(12), SI(2), 90, 88, 82);
|
||||
#undef LX
|
||||
#undef LY
|
||||
#undef SI
|
||||
}
|
||||
|
||||
/* Building silhouettes: bright pad + faction fill, thin black outline. */
|
||||
static void draw_bld(Building *b, int sx, int sy) {
|
||||
int W = b->w * TILE, H = b->h * TILE;
|
||||
|
|
@ -775,6 +854,14 @@ void snapshot_capture(Game *g, const char *path) {
|
|||
draw_bld(b, sx, sy);
|
||||
}
|
||||
|
||||
/* wrecks under living units (battlefield litter) */
|
||||
for (int i = 0; i < g->wreck_count; i++) {
|
||||
Wreck *w = &g->wrecks[i];
|
||||
int sx = (int)(w->x - camx), sy = (int)(w->y - camy);
|
||||
if (sx < -24 || sy < -24 || sx > g_sw + 24 || sy > g_sh + 24) continue;
|
||||
draw_wreck(w, sx, sy);
|
||||
}
|
||||
|
||||
/* units */
|
||||
for (int i = 0; i < g->unit_count; i++) {
|
||||
Unit *u = &g->units[i];
|
||||
|
|
|
|||
|
|
@ -111,3 +111,7 @@ CLAIM Spur A: scrap/resource mounds + denser lingering smoke/fire + secondary cl
|
|||
- status: ACTIVE
|
||||
|
||||
- **2026-09-19T12:46:00Z** · RELEASE Spur A @local-model/engine-L2-grok-4.5 · **DONE** — denser mid-fight fire/smoke/muzzle/impact (main/projectiles/snapshot/render + MAX_PARTICLES SoT); smoke PASS; 01c7ab8
|
||||
|
||||
- **2026-09-19T12:50:47Z** · CLAIM Spur A @local-model/engine-L2-grok-4.5 · **ACTIVE** — engine-c/src/snapshot.c,render.c,engine.c; snapshot wreck draw + type-aware silhouettes + clash wreck seed; TODO365
|
||||
|
||||
- **2026-09-19T14:04:14Z** · local-model/engine-L2-grok-4.5 · Spur A wrecks · **ok** — draw_wreck+render_wrecks+seed_clash_wrecks (~22); wreck_count reset; smoke RUN_ALL PASS; shot 1280x720
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ Core of **TODO=365**: collaborate to **advance the game** and **push directly**
|
|||
|
||||
| When (UTC) | Agent / author slug | Spur | Paths (short) | Status | Note |
|
||||
|------------|---------------------|------|---------------|--------|------|
|
||||
| 2026-09-19T12:50:47Z | local-model/engine-L2-grok-4.5 | A | engine-c/src/snapshot.c,render.c,engine.c | DONE | smoke PASS; wreck draw+type variety+clash seed (~22); cd3d945 |
|
||||
| 2026-09-19T12:38:43Z | local-model/engine-L2-grok-4.5 | A | engine-c/src/main.c,projectiles.c,snapshot.c | DONE | smoke PASS; denser mid-fight fire/smoke/muzzle/impact; 01c7ab8 |
|
||||
| 2026-09-19T12:21:37Z | local-model/engine-L2-grok-4.5 | A | engine-c/src/engine.c,snapshot.c,sprites.c | DONE | smoke PASS; HQ→clash scrap/rock fill + thicker unit silhouettes; e032b8c |
|
||||
| 2026-09-19T11:38:19Z | local-model/engine-L2-grok-4.5 | A | engine-c/src/engine.c,projectiles.c,main.c,snapshot.c | DONE | scrap mounds + lingering FX + secondary SE clash |
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue