kitchen: README + MISSIONS/engine-c keep-drop notes
This commit is contained in:
parent
1d351918da
commit
575d7d29b8
130 changed files with 9817 additions and 1 deletions
148
engine-c/src/snapshot.c
Normal file
148
engine-c/src/snapshot.c
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Software snapshot renderer - draws the game world into an RGBA buffer using
|
||||
* only primitive shapes (no SDL gpu readback, which is broken on this box due
|
||||
* to an SDL2/SDL3 conflict). Output is saved as PNG via png_save().
|
||||
*/
|
||||
#include "kknd.h"
|
||||
|
||||
#define SW VIEW_W
|
||||
#define SH VIEW_H
|
||||
|
||||
static uint8_t *g_buf;
|
||||
|
||||
static void px(int x, int y, uint8_t r, uint8_t g, uint8_t b) {
|
||||
if (x < 0 || y < 0 || x >= SW || y >= SH) return;
|
||||
int i = (y * SW + x) * 4;
|
||||
g_buf[i] = r; g_buf[i+1] = g; g_buf[i+2] = b; g_buf[i+3] = 255;
|
||||
}
|
||||
|
||||
static void rectf(int x0, int y0, int x1, int y1, uint8_t r, uint8_t g, uint8_t b) {
|
||||
if (x0 > x1) { int t = x0; x0 = x1; x1 = t; }
|
||||
if (y0 > y1) { int t = y0; y0 = y1; y1 = t; }
|
||||
for (int y = y0; y <= y1; y++)
|
||||
for (int x = x0; x <= x1; x++)
|
||||
px(x, y, r, g, b);
|
||||
}
|
||||
|
||||
static void disc(int cx, int cy, int rad, uint8_t r, uint8_t g, uint8_t b) {
|
||||
for (int y = -rad; y <= rad; y++)
|
||||
for (int x = -rad; x <= rad; x++)
|
||||
if (x*x + y*y <= rad*rad) px(cx+x, cy+y, r, g, b);
|
||||
}
|
||||
|
||||
static uint8_t faction_r(Faction f){ return f==FACTION_SURVIVOR?70 : f==FACTION_EVOLVED?200 : 230; }
|
||||
static uint8_t faction_g(Faction f){ return f==FACTION_SURVIVOR?180: f==FACTION_EVOLVED?70 : 60; }
|
||||
static uint8_t faction_b(Faction f){ return f==FACTION_SURVIVOR?90 : f==FACTION_EVOLVED?210 : 230; }
|
||||
|
||||
static void terrain_color(TerrainType t, uint8_t *r, uint8_t *g, uint8_t *b) {
|
||||
switch (t) {
|
||||
case T_GRASS: *r=46; *g=92; *b=46; break;
|
||||
case T_ROAD: *r=90; *g=90; *b=80; break;
|
||||
case T_RUBBLE:*r=80; *g=72; *b=64; break;
|
||||
case T_ROCK: *r=80; *g=80; *b=86; break;
|
||||
case T_WATER: *r=40; *g=60; *b=120; break;
|
||||
case T_SCRAP: *r=70; *g=64; *b=40; break;
|
||||
default: *r=50; *g=50; *b=50; break;
|
||||
}
|
||||
}
|
||||
|
||||
void snapshot_capture(Game *g, const char *path) {
|
||||
uint8_t *buf = (uint8_t *)malloc((size_t)SW * SH * 4);
|
||||
if (!buf) return;
|
||||
g_buf = buf;
|
||||
for (int i = 0; i < SW*SH; i++) { buf[i*4]=0; buf[i*4+1]=0; buf[i*4+2]=0; buf[i*4+3]=255; }
|
||||
|
||||
/* camera: centre on centroid of human units, else map centre */
|
||||
float cx = MAP_PIX_W/2, cy = MAP_PIX_H/2;
|
||||
int nc = 0;
|
||||
for (int i = 0; i < g->unit_count; i++)
|
||||
if (!g->units[i].dead && g->units[i].faction == g->human) { cx += g->units[i].x; cy += g->units[i].y; nc++; }
|
||||
if (nc) { cx /= nc; cy /= nc; }
|
||||
float camx = cx - SW/2, camy = cy - SH/2;
|
||||
if (camx < 0) camx = 0; if (camy < 0) camy = 0;
|
||||
if (camx > MAP_PIX_W - SW) camx = MAP_PIX_W - SW;
|
||||
if (camy > MAP_PIX_H - SH) camy = MAP_PIX_H - SH;
|
||||
|
||||
/* terrain */
|
||||
int tx0 = (int)camx / TILE, ty0 = (int)camy / TILE;
|
||||
int tx1 = (int)(camx + SW) / TILE, ty1 = (int)(camy + SH) / TILE;
|
||||
for (int ty = ty0; ty <= ty1; ty++) {
|
||||
for (int tx = tx0; tx <= tx1; tx++) {
|
||||
if (tx < 0 || ty < 0 || tx >= MAP_W || ty >= MAP_W) continue;
|
||||
Tile *t = map_tile(&g->map, tx, ty);
|
||||
uint8_t r,g,b; terrain_color(t->terrain, &r,&g,&b);
|
||||
int sx = tx*TILE - (int)camx, sy = ty*TILE - (int)camy;
|
||||
rectf(sx, sy, sx+TILE-1, sy+TILE-1, r, g, b);
|
||||
if (t->terrain == T_SCRAP && t->scrap > 0) {
|
||||
int cc = (sx+TILE/2), cr = (sy+TILE/2);
|
||||
for (int k=0;k<t->scrap/20;k++)
|
||||
disc(cc + ((k*7)%10)-5, cr + ((k*5)%10)-5, 2, 150,140,90);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* fog overlay */
|
||||
for (int ty = ty0; ty <= ty1; ty++)
|
||||
for (int tx = tx0; tx <= tx1; tx++) {
|
||||
if (tx < 0 || ty < 0 || tx >= MAP_W || ty >= MAP_W) continue;
|
||||
int f = g->map.fog[ty*MAP_W + tx];
|
||||
if (f == 0) { int sx=tx*TILE-(int)camx, sy=ty*TILE-(int)camy; rectf(sx,sy,sx+TILE-1,sy+TILE-1,0,0,0); }
|
||||
else if (f == 1) { int sx=tx*TILE-(int)camx, sy=ty*TILE-(int)camy; rectf(sx,sy,sx+TILE-1,sy+TILE-1,0,0,30); }
|
||||
}
|
||||
|
||||
/* buildings */
|
||||
for (int i = 0; i < g->bld_count; i++) {
|
||||
Building *b = &g->buildings[i];
|
||||
if (b->dead) continue;
|
||||
int sx = (int)(b->tx*TILE - camx), sy = (int)(b->ty*TILE - camy);
|
||||
int w = b->w*TILE, h = b->h*TILE;
|
||||
if (sx+w < 0 || sy+h < 0 || sx > SW || sy > SH) continue;
|
||||
uint8_t r=faction_r(b->faction),gg=faction_g(b->faction),bb=faction_b(b->faction);
|
||||
rectf(sx, sy, sx+w-1, sy+h-1, r/2+30, gg/2+30, bb/2+30);
|
||||
rectf(sx+2, sy+2, sx+w-3, sy+h-3, r, gg, bb);
|
||||
if (b->build < 1.0f) rectf(sx, sy, sx+w-1, sy+(int)(h*b->build)-1, 255,255,255);
|
||||
}
|
||||
|
||||
/* units */
|
||||
for (int i = 0; i < g->unit_count; i++) {
|
||||
Unit *u = &g->units[i];
|
||||
if (u->dead) continue;
|
||||
int sx = (int)(u->x - camx), sy = (int)(u->y - camy);
|
||||
if (sx < -10 || sy < -10 || sx > SW+10 || sy > SH+10) continue;
|
||||
uint8_t r=faction_r(u->faction),gg=faction_g(u->faction),bb=faction_b(u->faction);
|
||||
int rad = u->type==UT_TANK||u->type==UT_BEAST?9:u->type==UT_HARVESTER?8:6;
|
||||
disc(sx, sy, rad, r, gg, bb);
|
||||
disc(sx, sy, 2, 255,255,255);
|
||||
int hx = sx + (int)(cosf(u->heading)*rad), hy = sy + (int)(sinf(u->heading)*rad);
|
||||
for (int k=0;k<rad;k++){ int xx=sx+(hx-sx)*k/rad, yy=sy+(hy-sy)*k/rad; px(xx,yy,230,230,230); }
|
||||
if (u->selected) { rectf(sx-rad-2,sy-rad-2,sx+rad+2,sy+rad+2,255,255,120); }
|
||||
}
|
||||
|
||||
/* projectiles */
|
||||
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);
|
||||
px(sx,sy,255,230,120); px(sx+1,sy,255,230,120);
|
||||
}
|
||||
|
||||
/* minimap */
|
||||
int mmx=SW-210, mmy=10, mms=200;
|
||||
rectf(mmx-2,mmy-2,mmx+mms+1,mmy+mms+1,0,0,0);
|
||||
for (int ty=0;ty<MAP_W;ty+=2) for (int tx=0;tx<MAP_W;tx+=2) {
|
||||
int f=g->map.fog[ty*MAP_W+tx];
|
||||
if (f==0) continue;
|
||||
Tile *t=map_tile(&g->map,tx,ty);
|
||||
uint8_t r,g,b; terrain_color(t->terrain,&r,&g,&b);
|
||||
int dx=mmx + tx*mms/MAP_W, dy=mmy + ty*mms/MAP_W;
|
||||
px(dx,dy,r,g,b);
|
||||
}
|
||||
for (int i=0;i<g->bld_count;i++){ Building*b=&g->buildings[i]; if(b->dead)continue;
|
||||
int dx=mmx+b->tx*TILE*mms/(MAP_W*TILE), dy=mmy+b->ty*TILE*mms/(MAP_W*TILE);
|
||||
px(dx,dy,faction_r(b->faction),faction_g(b->faction),faction_b(b->faction)); }
|
||||
for (int i=0;i<g->unit_count;i++){ Unit*u=&g->units[i]; if(u->dead)continue;
|
||||
int dx=mmx+(int)(u->x*mms/MAP_PIX_W), dy=mmy+(int)(u->y*mms/MAP_PIX_H);
|
||||
px(dx,dy,faction_r(u->faction),faction_g(u->faction),faction_b(u->faction)); }
|
||||
|
||||
png_save(path, SW, SH, buf);
|
||||
free(buf);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue