diff --git a/engine-c/openkknd b/engine-c/openkknd index 9d27bd4..aeca623 100755 Binary files a/engine-c/openkknd and b/engine-c/openkknd differ diff --git a/engine-c/shot_0001.png b/engine-c/shot_0001.png index 5b7746c..4a7f293 100644 Binary files a/engine-c/shot_0001.png and b/engine-c/shot_0001.png differ diff --git a/engine-c/src/main.c b/engine-c/src/main.c index 1fb1a94..5eb7f5b 100644 --- a/engine-c/src/main.c +++ b/engine-c/src/main.c @@ -159,6 +159,61 @@ int main(int argc, char **argv) { particle_burst(g, cx + 44, cy - 16, 20, 2, 255, 240, 100); particle_burst(g, cx + 8, cy - 40, 18, 1, 255, 150, 45); particle_burst(g, cx - 22, cy + 36, 18, 0, 120, 110, 95); + /* Mid-flight shells/missiles/lasers: after ~1s sim most live + * bullets have already impacted. Reseed between nearby opposing + * pairs so the PNG shows KKND2-like tracers across the clash. */ + { + int spawned = 0; + const float pair_r2 = 170.0f * 170.0f; + for (int i = 0; i < g->unit_count && spawned < 56; i++) { + Unit *a = &g->units[i]; + if (a->dead) continue; + float ax = a->x - clash_x, ay = a->y - clash_y; + if (ax * ax + ay * ay > r2) continue; + int shots = 0; + for (int j = 0; j < g->unit_count && spawned < 56 && shots < 2; j++) { + Unit *b = &g->units[j]; + if (b->dead || b->faction == a->faction) continue; + float dx = b->x - a->x, dy = b->y - a->y; + float d2 = dx * dx + dy * dy; + if (d2 > pair_r2 || d2 < 24.0f * 24.0f) continue; + int kind = (spawned % 4 == 0) ? 3 + : (spawned % 4 == 1) ? 1 + : (spawned % 4 == 2) ? 2 : 0; + float t = 0.22f + 0.55f * ((spawned * 37) % 100) / 100.0f; + float sx = a->x + dx * t; + float sy = a->y + dy * t; + bullet_spawn(g, sx, sy, b->id, -1, 1.0f, a->faction, kind); + spawned++; + shots++; + } + } + /* turret / base guns → nearest enemy in clash */ + for (int i = 0; i < g->bld_count && spawned < 64; i++) { + Building *bl = &g->buildings[i]; + if (bl->dead || (bl->type != BT_TURRET && bl->type != BT_BASE)) + continue; + float bx = (float)(bl->tx * TILE + bl->w * TILE / 2); + float by = (float)(bl->ty * TILE + bl->h * TILE / 2); + float bdx = bx - clash_x, bdy = by - clash_y; + if (bdx * bdx + bdy * bdy > r2) continue; + int best = -1; float bestd = 1e12f; + for (int j = 0; j < g->unit_count; j++) { + Unit *u = &g->units[j]; + if (u->dead || u->faction == bl->faction) continue; + float dx = u->x - bx, dy = u->y - by; + float d2 = dx * dx + dy * dy; + if (d2 < bestd && d2 < pair_r2) { bestd = d2; best = j; } + } + if (best < 0) continue; + Unit *tgt = &g->units[best]; + float dx = tgt->x - bx, dy = tgt->y - by; + float t = 0.30f + 0.40f * ((spawned * 19) % 100) / 100.0f; + bullet_spawn(g, bx + dx * t, by + dy * t, tgt->id, -1, + 2.0f, bl->faction, (spawned & 1) ? 1 : 2); + spawned++; + } + } } char path[64]; snprintf(path, sizeof path, "shot_%04d.png", 1); snapshot_capture(g, path); diff --git a/engine-c/src/snapshot.c b/engine-c/src/snapshot.c index f48cc75..d760209 100644 --- a/engine-c/src/snapshot.c +++ b/engine-c/src/snapshot.c @@ -469,17 +469,41 @@ void snapshot_capture(Game *g, const char *path) { draw_unit(u, sx, sy); } - /* projectiles — bright tracers / shells */ + /* projectiles — bright tracers / shells with streak tails (KKND2-like) */ for (int i = 0; i < g->bullet_count; i++) { Bullet *p = &g->bullets[i]; - int sx=(int)(p->x-camx), sy=(int)(p->y-camy); + int sx = (int)(p->x - camx), sy = (int)(p->y - camy); + float dx = p->tx - p->x, dy = p->ty - p->y; + float d = sqrtf(dx * dx + dy * dy); + if (d > 1.0f) { + float ux = dx / d, uy = dy / d; + int len = (p->kind == 2) ? 24 : (p->kind == 3) ? 18 + : (p->kind == 1) ? 14 : 10; + for (int t = 1; t <= len; t++) { + int tx = sx - (int)(ux * (float)t * 0.75f); + int ty = sy - (int)(uy * (float)t * 0.75f); + uint8_t fade = (uint8_t)(255 - t * 9); + if (p->kind == 2) { + /* laser beam: cyan→magenta streak */ + disc(tx, ty, (t < 3) ? 2 : 1, fade, 80, 255); + px(tx, ty, 220, 180, 255); + } else if (p->kind == 3) { + disc(tx, ty, (t < 4) ? 2 : 1, 255, (uint8_t)(120 - t * 4), 30); + } else { + disc(tx, ty, 1, 255, (uint8_t)(200 - t * 8), 50); + } + } + } int rad = (p->kind == 1 || p->kind == 3) ? 6 : 4; disc(sx, sy, rad + 1, 255, 160, 40); disc(sx, sy, rad, 255, 240, 140); - px(sx+1, sy, 255, 255, 220); + px(sx + 1, sy, 255, 255, 220); if (p->kind == 3) { disc(sx - 3, sy + 1, 3, 255, 70, 30); disc(sx + 2, sy - 2, 2, 255, 200, 80); + } else if (p->kind == 2) { + disc(sx, sy, rad + 1, 120, 200, 255); + disc(sx, sy, rad - 1, 240, 220, 255); } } diff --git a/kitchen/AGENT_LOG.md b/kitchen/AGENT_LOG.md index 725aa97..27aecd4 100644 --- a/kitchen/AGENT_LOG.md +++ b/kitchen/AGENT_LOG.md @@ -44,3 +44,5 @@ - **2026-09-19T05:28:54Z** · CLAIM Spur A @local-model/engine-L2-grok-4.5 · **ACTIVE** — engine-c/src/engine.c + snapshot.c; TODO365 KKND2-like showcase (units/bld/combat near camera) - **2026-09-19T08:04:10Z** · RELEASE Spur A @local-model/engine-L2-grok-4.5 · **DONE** — dense arid showcase + type-aware snapshot; smoke PASS; pushed b5a89c9 +- **2026-09-19T08:38:05Z** · CLAIM Spur A @local-model/engine-L2-grok-4.5 · **ACTIVE** — engine-c/src/main.c + snapshot.c; mid-flight bullets + denser tracers in KKND_SHOT +- **2026-09-19T08:40:30Z** · RELEASE Spur A @local-model/engine-L2-grok-4.5 · **DONE** — mid-flight bullets + tracer streaks in KKND_SHOT; smoke PASS; SHORTSHA diff --git a/kitchen/COLLAB-SIGNUP.md b/kitchen/COLLAB-SIGNUP.md index 106f76a..e2b7314 100644 --- a/kitchen/COLLAB-SIGNUP.md +++ b/kitchen/COLLAB-SIGNUP.md @@ -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-19T08:38Z | local-model/engine-L2-grok-4.5 | A | engine-c/src/main.c,snapshot.c | DONE | smoke PASS; mid-flight tracers; SHORTSHA | | 2026-09-19T05:28Z | local-model/engine-L2-grok-4.5 | A | engine-c/src/engine.c,snapshot.c | DONE | pushed b5a89c9; smoke PASS; arid clash showcase |