Files
major_tom/src/game/sprites.c
Thomas bb0b9ddce1 Add jetpack fuel pickup and slow base recharge to 30s
Jetpack charges now take 30s to passively recharge (up from 3s),
making fuel management a core gameplay loop. A new fuel canister
powerup (POWERUP_FUEL) restores exactly one charge on pickup.

The existing jetpack powerup remains as the rare full-refill + 15s
boost. Fuel pickups replace most procedural jetpack spawns at higher
spawn rates to compensate for the weaker per-pickup value. Fuel
canisters also appear in corridors and arenas.

Adds orange canister pixel art, editor icon, entity registry entry,
and places fuel pickups throughout moon01.
2026-03-01 18:06:32 +00:00

1351 lines
76 KiB
C

#include "game/sprites.h"
#include <string.h>
#include <stdio.h>
SDL_Texture *g_spritesheet = NULL;
/* ── Pixel art data ─────────────────────────────────
* Each sprite is defined as a 16x16 grid of hex color values.
* 0x00000000 = transparent
* Colors are RGBA packed as 0xRRGGBBAA
*/
#define T 0x00000000 /* transparent */
/* Color palette */
#define BLK 0x1a1a2eFF /* black/dark */
#define WHT 0xeeeeeaFF /* white */
#define SKN 0xe8b796FF /* skin tone */
#define SKD 0xc48e6aFF /* skin dark */
#define BLU 0x4a7cbdFF /* blue */
#define BLD 0x365e8fFF /* blue dark */
#define BLL 0x6fa8dcFF /* blue light */
#define RED 0xd94444FF /* red */
#define RDD 0xa83232FF /* red dark */
#define RDL 0xff6666FF /* red light */
#define GRN 0x4caf50FF /* green */
#define GRD 0x388e3cFF /* green dark */
#define YLW 0xffd54fFF /* yellow */
#define YLD 0xd4a017FF /* yellow dark */
#define ORG 0xff9800FF /* orange */
#define ORD 0xcc7a00FF /* orange dark */
#define PRP 0x9c27b0FF /* purple */
#define PRD 0x7b1fa2FF /* purple dark */
#define PRL 0xce93d8FF /* purple light */
#define GRY 0x888888FF /* grey */
#define GYD 0x555555FF /* grey dark */
#define GYL 0xbbbbbbFF /* grey light */
#define BRN 0x8d6e63FF /* brown */
#define BRD 0x5d4037FF /* brown dark */
#define CYN 0x4dd0e1FF /* cyan */
#define CYD 0x00acc1FF /* cyan dark */
/* ── Player sprites ────────────────────────────────── */
/* Player idle frame 1 - heroic adventurer */
static const uint32_t player_idle1[16*16] = {
T, T, T, T, T, BLU, BLU, BLU, BLU, BLU, T, T, T, T, T, T,
T, T, T, T, BLU, BLL, BLL, BLL, BLL, BLU, BLU, T, T, T, T, T,
T, T, T, T, BLU, BLL, BLL, BLL, BLL, BLL, BLU, T, T, T, T, T,
T, T, T, T, BLK, SKN, SKN, SKN, SKN, BLK, T, T, T, T, T, T,
T, T, T, BLK, SKN, SKN, SKN, SKN, SKN, SKN, BLK, T, T, T, T, T,
T, T, T, BLK, SKN, BLK, SKN, SKN, BLK, SKN, BLK, T, T, T, T, T,
T, T, T, T, SKN, SKN, SKN, SKD, SKN, SKN, T, T, T, T, T, T,
T, T, T, T, SKN, SKN, SKD, SKD, SKN, SKN, T, T, T, T, T, T,
T, T, T, BLU, BLU, BLU, BLU, BLU, BLU, BLU, BLU, T, T, T, T, T,
T, T, T, BLD, BLU, BLU, BLU, BLU, BLU, BLU, BLD, T, T, T, T, T,
T, T, SKN, BLD, BLU, BLU, BLU, BLU, BLU, BLU, BLD, SKN, T, T, T, T,
T, T, SKN, T, BLU, BLU, BLU, BLU, BLU, BLU, T, SKN, T, T, T, T,
T, T, T, T, BLD, BLD, BLU, BLU, BLD, BLD, T, T, T, T, T, T,
T, T, T, T, BLD, BLD, T, T, BLD, BLD, T, T, T, T, T, T,
T, T, T, T, BRN, BRN, T, T, BRN, BRN, T, T, T, T, T, T,
T, T, T, T, BRD, BRD, T, T, BRD, BRD, T, T, T, T, T, T,
};
/* Player idle frame 2 - slight bob */
static const uint32_t player_idle2[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, BLU, BLU, BLU, BLU, BLU, T, T, T, T, T, T,
T, T, T, T, BLU, BLL, BLL, BLL, BLL, BLU, BLU, T, T, T, T, T,
T, T, T, T, BLU, BLL, BLL, BLL, BLL, BLL, BLU, T, T, T, T, T,
T, T, T, T, BLK, SKN, SKN, SKN, SKN, BLK, T, T, T, T, T, T,
T, T, T, BLK, SKN, SKN, SKN, SKN, SKN, SKN, BLK, T, T, T, T, T,
T, T, T, BLK, SKN, BLK, SKN, SKN, BLK, SKN, BLK, T, T, T, T, T,
T, T, T, T, SKN, SKN, SKN, SKD, SKN, SKN, T, T, T, T, T, T,
T, T, T, T, SKN, SKN, SKD, SKD, SKN, SKN, T, T, T, T, T, T,
T, T, T, BLU, BLU, BLU, BLU, BLU, BLU, BLU, BLU, T, T, T, T, T,
T, T, T, BLD, BLU, BLU, BLU, BLU, BLU, BLU, BLD, T, T, T, T, T,
T, T, SKN, BLD, BLU, BLU, BLU, BLU, BLU, BLU, BLD, SKN, T, T, T, T,
T, T, T, T, BLD, BLD, BLU, BLU, BLD, BLD, T, T, T, T, T, T,
T, T, T, T, BLD, BLD, T, T, BLD, BLD, T, T, T, T, T, T,
T, T, T, T, BRN, BRN, T, T, BRN, BRN, T, T, T, T, T, T,
T, T, T, T, BRD, BRD, T, T, BRD, BRD, T, T, T, T, T, T,
};
/* Player run frame 1 */
static const uint32_t player_run1[16*16] = {
T, T, T, T, T, BLU, BLU, BLU, BLU, BLU, T, T, T, T, T, T,
T, T, T, T, BLU, BLL, BLL, BLL, BLL, BLU, BLU, T, T, T, T, T,
T, T, T, T, BLU, BLL, BLL, BLL, BLL, BLL, BLU, T, T, T, T, T,
T, T, T, T, BLK, SKN, SKN, SKN, SKN, BLK, T, T, T, T, T, T,
T, T, T, BLK, SKN, SKN, SKN, SKN, SKN, SKN, BLK, T, T, T, T, T,
T, T, T, BLK, SKN, BLK, SKN, SKN, BLK, SKN, BLK, T, T, T, T, T,
T, T, T, T, SKN, SKN, SKN, SKD, SKN, SKN, T, T, T, T, T, T,
T, T, T, T, SKN, SKN, SKD, SKD, SKN, SKN, T, T, T, T, T, T,
T, T, T, BLU, BLU, BLU, BLU, BLU, BLU, BLU, BLU, T, T, T, T, T,
T, T, SKN, BLD, BLU, BLU, BLU, BLU, BLU, BLU, BLD, T, T, T, T, T,
T, T, SKN, BLD, BLU, BLU, BLU, BLU, BLU, BLU, BLD, SKN, T, T, T, T,
T, T, T, T, BLU, BLU, BLU, BLU, BLU, BLU, T, SKN, T, T, T, T,
T, T, T, T, T, BLD, BLU, BLU, BLD, T, T, T, T, T, T, T,
T, T, T, T, T, BLD, T, T, T, BLD, T, T, T, T, T, T,
T, T, T, T, BRN, BRN, T, T, T, BRN, BRN, T, T, T, T, T,
T, T, T, BRD, BRD, T, T, T, T, T, BRD, T, T, T, T, T,
};
/* Player run frame 2 */
static const uint32_t player_run2[16*16] = {
T, T, T, T, T, BLU, BLU, BLU, BLU, BLU, T, T, T, T, T, T,
T, T, T, T, BLU, BLL, BLL, BLL, BLL, BLU, BLU, T, T, T, T, T,
T, T, T, T, BLU, BLL, BLL, BLL, BLL, BLL, BLU, T, T, T, T, T,
T, T, T, T, BLK, SKN, SKN, SKN, SKN, BLK, T, T, T, T, T, T,
T, T, T, BLK, SKN, SKN, SKN, SKN, SKN, SKN, BLK, T, T, T, T, T,
T, T, T, BLK, SKN, BLK, SKN, SKN, BLK, SKN, BLK, T, T, T, T, T,
T, T, T, T, SKN, SKN, SKN, SKD, SKN, SKN, T, T, T, T, T, T,
T, T, T, T, SKN, SKN, SKD, SKD, SKN, SKN, T, T, T, T, T, T,
T, T, T, BLU, BLU, BLU, BLU, BLU, BLU, BLU, BLU, T, T, T, T, T,
T, T, T, BLD, BLU, BLU, BLU, BLU, BLU, BLU, BLD, SKN, T, T, T, T,
T, T, T, BLD, BLU, BLU, BLU, BLU, BLU, BLU, BLD, SKN, T, T, T, T,
T, T, SKN, T, BLU, BLU, BLU, BLU, BLU, BLU, T, T, T, T, T, T,
T, T, T, T, BLD, T, BLU, BLU, T, BLD, T, T, T, T, T, T,
T, T, T, T, BLD, T, T, T, BLD, T, T, T, T, T, T, T,
T, T, T, T, T, BRN, T, BRN, BRN, T, T, T, T, T, T, T,
T, T, T, T, T, BRD, T, BRD, T, T, T, T, T, T, T, T,
};
/* Player run frame 3 */
static const uint32_t player_run3[16*16] = {
T, T, T, T, T, BLU, BLU, BLU, BLU, BLU, T, T, T, T, T, T,
T, T, T, T, BLU, BLL, BLL, BLL, BLL, BLU, BLU, T, T, T, T, T,
T, T, T, T, BLU, BLL, BLL, BLL, BLL, BLL, BLU, T, T, T, T, T,
T, T, T, T, BLK, SKN, SKN, SKN, SKN, BLK, T, T, T, T, T, T,
T, T, T, BLK, SKN, SKN, SKN, SKN, SKN, SKN, BLK, T, T, T, T, T,
T, T, T, BLK, SKN, BLK, SKN, SKN, BLK, SKN, BLK, T, T, T, T, T,
T, T, T, T, SKN, SKN, SKN, SKD, SKN, SKN, T, T, T, T, T, T,
T, T, T, T, SKN, SKN, SKD, SKD, SKN, SKN, T, T, T, T, T, T,
T, T, T, BLU, BLU, BLU, BLU, BLU, BLU, BLU, BLU, T, T, T, T, T,
T, T, T, BLD, BLU, BLU, BLU, BLU, BLU, BLU, BLD, T, T, T, T, T,
T, T, SKN, BLD, BLU, BLU, BLU, BLU, BLU, BLU, BLD, SKN, T, T, T, T,
T, T, SKN, T, BLU, BLU, BLU, BLU, BLU, BLU, T, SKN, T, T, T, T,
T, T, T, T, BLD, BLD, BLU, BLU, BLD, BLD, T, T, T, T, T, T,
T, T, T, BLD, T, T, T, T, T, T, BLD, T, T, T, T, T,
T, T, BRN, BRN, T, T, T, T, T, BRN, BRN, T, T, T, T, T,
T, T, T, BRD, T, T, T, T, BRD, BRD, T, T, T, T, T, T,
};
/* Player run frame 4 - same as run2 mirrored leg positions */
static const uint32_t player_run4[16*16] = {
T, T, T, T, T, BLU, BLU, BLU, BLU, BLU, T, T, T, T, T, T,
T, T, T, T, BLU, BLL, BLL, BLL, BLL, BLU, BLU, T, T, T, T, T,
T, T, T, T, BLU, BLL, BLL, BLL, BLL, BLL, BLU, T, T, T, T, T,
T, T, T, T, BLK, SKN, SKN, SKN, SKN, BLK, T, T, T, T, T, T,
T, T, T, BLK, SKN, SKN, SKN, SKN, SKN, SKN, BLK, T, T, T, T, T,
T, T, T, BLK, SKN, BLK, SKN, SKN, BLK, SKN, BLK, T, T, T, T, T,
T, T, T, T, SKN, SKN, SKN, SKD, SKN, SKN, T, T, T, T, T, T,
T, T, T, T, SKN, SKN, SKD, SKD, SKN, SKN, T, T, T, T, T, T,
T, T, T, BLU, BLU, BLU, BLU, BLU, BLU, BLU, BLU, T, T, T, T, T,
T, T, SKN, BLD, BLU, BLU, BLU, BLU, BLU, BLU, BLD, T, T, T, T, T,
T, T, T, BLD, BLU, BLU, BLU, BLU, BLU, BLU, BLD, SKN, T, T, T, T,
T, T, SKN, T, BLU, BLU, BLU, BLU, BLU, BLU, T, T, T, T, T, T,
T, T, T, T, T, BLD, BLU, BLU, BLD, T, T, T, T, T, T, T,
T, T, T, BLD, T, T, T, T, T, BLD, T, T, T, T, T, T,
T, T, BRN, BRN, T, T, T, T, BRN, BRN, T, T, T, T, T, T,
T, T, BRD, T, T, T, T, T, T, BRD, T, T, T, T, T, T,
};
/* Player jump */
static const uint32_t player_jump[16*16] = {
T, T, T, T, T, BLU, BLU, BLU, BLU, BLU, T, T, T, T, T, T,
T, T, T, T, BLU, BLL, BLL, BLL, BLL, BLU, BLU, T, T, T, T, T,
T, T, T, T, BLU, BLL, BLL, BLL, BLL, BLL, BLU, T, T, T, T, T,
T, T, T, T, BLK, SKN, SKN, SKN, SKN, BLK, T, T, T, T, T, T,
T, T, T, BLK, SKN, SKN, SKN, SKN, SKN, SKN, BLK, T, T, T, T, T,
T, T, T, BLK, SKN, BLK, SKN, SKN, BLK, SKN, BLK, T, T, T, T, T,
T, T, T, T, SKN, SKN, SKN, SKD, SKN, SKN, T, T, T, T, T, T,
T, T, SKN, T, SKN, SKN, SKD, SKD, SKN, SKN, T, SKN, T, T, T, T,
T, T, SKN, BLU, BLU, BLU, BLU, BLU, BLU, BLU, BLU, SKN, T, T, T, T,
T, T, T, BLD, BLU, BLU, BLU, BLU, BLU, BLU, BLD, T, T, T, T, T,
T, T, T, BLD, BLU, BLU, BLU, BLU, BLU, BLU, BLD, T, T, T, T, T,
T, T, T, T, BLU, BLU, BLU, BLU, BLU, BLU, T, T, T, T, T, T,
T, T, T, T, BLD, BLD, T, T, BLD, BLD, T, T, T, T, T, T,
T, T, T, BRN, BRN, T, T, T, BRN, BRN, T, T, T, T, T, T,
T, T, T, BRD, BRD, T, T, T, T, BRN, BRN, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, BRD, BRD, T, T, T, T, T,
};
/* Player fall */
static const uint32_t player_fall[16*16] = {
T, T, T, T, T, BLU, BLU, BLU, BLU, BLU, T, T, T, T, T, T,
T, T, T, T, BLU, BLL, BLL, BLL, BLL, BLU, BLU, T, T, T, T, T,
T, T, T, T, BLU, BLL, BLL, BLL, BLL, BLL, BLU, T, T, T, T, T,
T, T, T, T, BLK, SKN, SKN, SKN, SKN, BLK, T, T, T, T, T, T,
T, T, T, BLK, SKN, SKN, SKN, SKN, SKN, SKN, BLK, T, T, T, T, T,
T, T, T, BLK, SKN, BLK, SKN, SKN, BLK, SKN, BLK, T, T, T, T, T,
T, T, T, T, SKN, SKN, SKN, SKD, SKN, SKN, T, T, T, T, T, T,
T, T, T, T, SKN, SKN, SKD, SKD, SKN, SKN, T, T, T, T, T, T,
T, SKN, SKN, BLU, BLU, BLU, BLU, BLU, BLU, BLU, BLU, SKN, SKN, T, T, T,
T, T, T, BLD, BLU, BLU, BLU, BLU, BLU, BLU, BLD, T, T, T, T, T,
T, T, T, BLD, BLU, BLU, BLU, BLU, BLU, BLU, BLD, T, T, T, T, T,
T, T, T, T, BLU, BLU, BLU, BLU, BLU, BLU, T, T, T, T, T, T,
T, T, T, T, BLD, BLD, T, T, BLD, BLD, T, T, T, T, T, T,
T, T, T, T, BRN, BRN, T, T, T, BRN, T, T, T, T, T, T,
T, T, T, BRN, BRD, T, T, T, T, BRN, T, T, T, T, T, T,
T, T, T, BRD, T, T, T, T, T, BRD, T, T, T, T, T, T,
};
/* ── Grunt enemy sprites ───────────────────────────── */
/* Grunt: Red spiky enemy that patrols back and forth */
static const uint32_t grunt_idle1[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, RED, T, T, T, T, T, RED, T, T, T, T, T,
T, T, T, T, RED, RED, T, T, T, RED, RED, T, T, T, T, T,
T, T, T, T, RDD, RED, RED, RED, RED, RED, RDD, T, T, T, T, T,
T, T, T, RDD, RED, RED, RED, RED, RED, RED, RED, RDD, T, T, T, T,
T, T, T, RDD, RED, RED, RED, RED, RED, RED, RED, RDD, T, T, T, T,
T, T, T, RDD, RED, WHT, BLK, RED, WHT, BLK, RED, RDD, T, T, T, T,
T, T, T, RDD, RED, RED, RED, RED, RED, RED, RED, RDD, T, T, T, T,
T, T, T, RDD, RED, RED, BLK, BLK, BLK, RED, RED, RDD, T, T, T, T,
T, T, T, T, RDD, RED, RED, RED, RED, RED, RDD, T, T, T, T, T,
T, T, T, T, RDD, RED, RED, RED, RED, RED, RDD, T, T, T, T, T,
T, T, T, T, T, RDD, RED, RED, RDD, T, T, T, T, T, T, T,
T, T, T, T, RDD, RDD, T, T, RDD, RDD, T, T, T, T, T, T,
T, T, T, T, RDD, RDD, T, T, RDD, RDD, T, T, T, T, T, T,
T, T, T, T, BLK, BLK, T, T, BLK, BLK, T, T, T, T, T, T,
};
static const uint32_t grunt_idle2[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, RED, T, T, T, T, T, RED, T, T, T, T, T,
T, T, T, T, RED, RED, T, T, T, RED, RED, T, T, T, T, T,
T, T, T, T, RDD, RED, RED, RED, RED, RED, RDD, T, T, T, T, T,
T, T, T, RDD, RED, RED, RED, RED, RED, RED, RED, RDD, T, T, T, T,
T, T, T, RDD, RED, RED, RED, RED, RED, RED, RED, RDD, T, T, T, T,
T, T, T, RDD, RED, WHT, BLK, RED, WHT, BLK, RED, RDD, T, T, T, T,
T, T, T, RDD, RED, RED, RED, RED, RED, RED, RED, RDD, T, T, T, T,
T, T, T, RDD, RED, RED, BLK, BLK, BLK, RED, RED, RDD, T, T, T, T,
T, T, T, T, RDD, RED, RED, RED, RED, RED, RDD, T, T, T, T, T,
T, T, T, T, T, RDD, RED, RED, RDD, T, T, T, T, T, T, T,
T, T, T, T, RDD, RDD, T, T, RDD, RDD, T, T, T, T, T, T,
T, T, T, T, RDD, RDD, T, T, RDD, RDD, T, T, T, T, T, T,
T, T, T, T, BLK, BLK, T, T, BLK, BLK, T, T, T, T, T, T,
};
/* Grunt walk frames (same body, different leg positions) */
static const uint32_t grunt_walk1[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, RED, T, T, T, T, T, RED, T, T, T, T, T,
T, T, T, T, RED, RED, T, T, T, RED, RED, T, T, T, T, T,
T, T, T, T, RDD, RED, RED, RED, RED, RED, RDD, T, T, T, T, T,
T, T, T, RDD, RED, RED, RED, RED, RED, RED, RED, RDD, T, T, T, T,
T, T, T, RDD, RED, RED, RED, RED, RED, RED, RED, RDD, T, T, T, T,
T, T, T, RDD, RED, WHT, BLK, RED, WHT, BLK, RED, RDD, T, T, T, T,
T, T, T, RDD, RED, RED, RED, RED, RED, RED, RED, RDD, T, T, T, T,
T, T, T, RDD, RED, RED, BLK, BLK, BLK, RED, RED, RDD, T, T, T, T,
T, T, T, T, RDD, RED, RED, RED, RED, RED, RDD, T, T, T, T, T,
T, T, T, T, RDD, RED, RED, RED, RED, RED, RDD, T, T, T, T, T,
T, T, T, T, T, RDD, RED, RED, RDD, T, T, T, T, T, T, T,
T, T, T, T, T, RDD, T, T, RDD, T, T, T, T, T, T, T,
T, T, T, T, RDD, T, T, T, T, RDD, T, T, T, T, T, T,
T, T, T, T, BLK, T, T, T, T, BLK, T, T, T, T, T, T,
};
static const uint32_t grunt_walk2[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, RED, T, T, T, T, T, RED, T, T, T, T, T,
T, T, T, T, RED, RED, T, T, T, RED, RED, T, T, T, T, T,
T, T, T, T, RDD, RED, RED, RED, RED, RED, RDD, T, T, T, T, T,
T, T, T, RDD, RED, RED, RED, RED, RED, RED, RED, RDD, T, T, T, T,
T, T, T, RDD, RED, RED, RED, RED, RED, RED, RED, RDD, T, T, T, T,
T, T, T, RDD, RED, WHT, BLK, RED, WHT, BLK, RED, RDD, T, T, T, T,
T, T, T, RDD, RED, RED, RED, RED, RED, RED, RED, RDD, T, T, T, T,
T, T, T, RDD, RED, RED, BLK, BLK, BLK, RED, RED, RDD, T, T, T, T,
T, T, T, T, RDD, RED, RED, RED, RED, RED, RDD, T, T, T, T, T,
T, T, T, T, RDD, RED, RED, RED, RED, RED, RDD, T, T, T, T, T,
T, T, T, T, T, RDD, RED, RED, RDD, T, T, T, T, T, T, T,
T, T, T, T, RDD, T, T, T, T, RDD, T, T, T, T, T, T,
T, T, T, T, T, RDD, T, T, RDD, T, T, T, T, T, T, T,
T, T, T, T, T, BLK, T, T, BLK, T, T, T, T, T, T, T,
};
/* Grunt death frame */
static const uint32_t grunt_death[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, RDD, RED, RED, RED, RED, RED, RED, RED, RDD, T, T, T, T,
T, T, RDD, RED, RED, RED, RED, RED, RED, RED, RED, RED, RDD, T, T, T,
T, T, RDD, RED, RED, BLK, BLK, RED, BLK, BLK, RED, RED, RDD, T, T, T,
T, T, RDD, RED, RED, RED, RED, BLK, RED, RED, RED, RED, RDD, T, T, T,
T, T, T, RDD, RED, RED, RED, RED, RED, RED, RED, RDD, T, T, T, T,
T, T, T, T, RDD, RDD, RDD, RDD, RDD, RDD, RDD, T, T, T, T, T,
};
/* ── Flyer enemy sprites ───────────────────────────── */
/* Flying enemy: Purple bat-like creature */
static const uint32_t flyer_idle1[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, PRP, PRP, PRP, PRP, PRP, T, T, T, T, T, T,
T, T, T, T, PRP, PRP, PRP, PRP, PRP, PRP, PRP, T, T, T, T, T,
T, T, T, PRP, PRP, YLW, BLK, PRP, YLW, BLK, PRP, PRP, T, T, T, T,
T, T, T, PRD, PRP, PRP, PRP, PRP, PRP, PRP, PRP, PRD, T, T, T, T,
T, T, T, PRD, PRP, PRP, BLK, BLK, PRP, PRP, PRP, PRD, T, T, T, T,
T, T, PRL, PRD, PRP, PRP, PRP, PRP, PRP, PRP, PRP, PRD, PRL, T, T, T,
T, PRL, PRL, T, PRD, PRP, PRP, PRP, PRP, PRP, PRD, T, PRL, PRL, T, T,
PRL, PRL, T, T, T, PRD, PRP, PRP, PRD, T, T, T, T, PRL, PRL, T,
PRL, T, T, T, T, T, PRD, PRD, T, T, T, T, T, T, PRL, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
static const uint32_t flyer_idle2[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, PRP, PRP, PRP, PRP, PRP, T, T, T, T, T, T,
T, T, T, T, PRP, PRP, PRP, PRP, PRP, PRP, PRP, T, T, T, T, T,
T, T, T, PRP, PRP, YLW, BLK, PRP, YLW, BLK, PRP, PRP, T, T, T, T,
T, T, T, PRD, PRP, PRP, PRP, PRP, PRP, PRP, PRP, PRD, T, T, T, T,
T, T, T, PRD, PRP, PRP, BLK, BLK, PRP, PRP, PRP, PRD, T, T, T, T,
T, T, T, PRD, PRP, PRP, PRP, PRP, PRP, PRP, PRP, PRD, T, T, T, T,
T, PRL, T, T, PRD, PRP, PRP, PRP, PRP, PRP, PRD, T, T, PRL, T, T,
PRL, PRL, PRL, T, T, PRD, PRP, PRP, PRD, T, T, T, PRL, PRL, PRL, T,
T, T, PRL, PRL, T, T, PRD, PRD, T, T, T, PRL, PRL, T, T, T,
T, T, T, PRL, PRL, T, T, T, T, T, PRL, PRL, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* Flyer death */
static const uint32_t flyer_death[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, PRP, PRP, PRP, PRP, PRP, T, T, T, T, T, T,
T, T, T, T, PRP, PRP, PRP, PRP, PRP, PRP, PRP, T, T, T, T, T,
T, T, T, PRP, PRP, BLK, BLK, PRP, BLK, BLK, PRP, PRP, T, T, T, T,
T, T, T, PRD, PRP, PRP, PRP, PRP, PRP, PRP, PRP, PRD, T, T, T, T,
T, T, T, PRD, PRP, PRP, PRP, BLK, PRP, PRP, PRP, PRD, T, T, T, T,
T, T, T, T, PRD, PRP, PRP, PRP, PRP, PRP, PRD, T, T, T, T, T,
T, T, T, PRL, T, PRD, PRP, PRP, PRD, T, PRL, T, T, T, T, T,
T, T, PRL, T, T, T, PRD, PRD, T, T, T, PRL, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* ── Projectile sprites ────────────────────────────── */
/* Player bullet frame 1 */
static const uint32_t bullet1[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, CYD, CYN, CYN, CYD, T, T, T, T, T, T,
T, T, T, T, T, CYD, CYN, WHT, WHT, CYN, CYD, T, T, T, T, T,
T, T, T, T, T, CYN, WHT, WHT, WHT, WHT, CYN, T, T, T, T, T,
T, T, T, T, T, CYN, WHT, WHT, WHT, WHT, CYN, T, T, T, T, T,
T, T, T, T, T, CYD, CYN, WHT, WHT, CYN, CYD, T, T, T, T, T,
T, T, T, T, T, T, CYD, CYN, CYN, CYD, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* Player bullet frame 2 - glow variation */
static const uint32_t bullet2[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, CYD, CYD, T, T, T, T, T, T, T,
T, T, T, T, T, T, CYN, WHT, WHT, CYN, T, T, T, T, T, T,
T, T, T, T, T, CYN, WHT, WHT, WHT, WHT, CYN, T, T, T, T, T,
T, T, T, T, CYD, WHT, WHT, WHT, WHT, WHT, WHT, CYD, T, T, T, T,
T, T, T, T, CYD, WHT, WHT, WHT, WHT, WHT, WHT, CYD, T, T, T, T,
T, T, T, T, T, CYN, WHT, WHT, WHT, WHT, CYN, T, T, T, T, T,
T, T, T, T, T, T, CYN, WHT, WHT, CYN, T, T, T, T, T, T,
T, T, T, T, T, T, T, CYD, CYD, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* Impact effect frame 1 */
static const uint32_t impact1[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, WHT, T, T, T, T, T, T, T, T,
T, T, T, T, T, WHT, T, T, T, WHT, T, T, T, T, T, T,
T, T, T, T, T, T, T, CYN, T, T, T, T, T, T, T, T,
T, T, T, T, T, CYN, CYN, WHT, CYN, CYN, T, T, T, T, T, T,
T, T, T, T, T, CYN, WHT, WHT, WHT, CYN, T, T, T, T, T, T,
T, T, WHT, T, CYN, WHT, WHT, WHT, WHT, WHT, CYN, T, WHT, T, T, T,
T, T, T, T, T, CYN, WHT, WHT, WHT, CYN, T, T, T, T, T, T,
T, T, T, T, T, CYN, CYN, WHT, CYN, CYN, T, T, T, T, T, T,
T, T, T, T, T, T, T, CYN, T, T, T, T, T, T, T, T,
T, T, T, T, T, WHT, T, T, T, WHT, T, T, T, T, T, T,
T, T, T, T, T, T, T, WHT, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* Impact effect frame 2 - expanding */
static const uint32_t impact2[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, CYD, T, T, T, T, T, CYD, T, T, T, T, T,
T, T, T, T, T, T, CYN, T, CYN, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, CYN, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, CYN, WHT, CYN, T, T, T, T, T, T, T,
T, T, T, CYN, T, CYN, T, WHT, T, CYN, T, CYN, T, T, T, T,
T, T, T, T, CYN, WHT, WHT, WHT, WHT, WHT, CYN, T, T, T, T, T,
T, T, T, CYN, T, CYN, T, WHT, T, CYN, T, CYN, T, T, T, T,
T, T, T, T, T, T, CYN, WHT, CYN, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, CYN, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, CYN, T, CYN, T, T, T, T, T, T, T,
T, T, T, T, CYD, T, T, T, T, T, CYD, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* Impact effect frame 3 - fading */
static const uint32_t impact3[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, CYD, T, T, T, T, T, T, T, CYD, T, T, T, T,
T, T, T, T, T, T, T, CYD, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, CYD, T, CYD, T, T, T, T, T, T, T,
T, T, T, T, T, CYD, T, T, T, CYD, T, T, T, T, T, T,
T, T, T, T, T, T, CYD, T, CYD, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, CYD, T, T, T, T, T, T, T, T,
T, T, T, CYD, T, T, T, T, T, T, T, CYD, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* Enemy bullet */
static const uint32_t enemy_bullet1[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, ORD, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, ORG, YLW, ORG, T, T, T, T, T, T, T,
T, T, T, T, T, ORD, YLW, WHT, YLW, ORD, T, T, T, T, T, T,
T, T, T, T, T, ORD, YLW, WHT, YLW, ORD, T, T, T, T, T, T,
T, T, T, T, T, T, ORG, YLW, ORG, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, ORD, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
static const uint32_t enemy_bullet2[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, ORD, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, ORG, YLW, ORG, T, T, T, T, T, T, T,
T, T, T, T, T, ORG, YLW, WHT, YLW, ORG, T, T, T, T, T, T,
T, T, T, T, ORD, YLW, WHT, WHT, WHT, YLW, ORD, T, T, T, T, T,
T, T, T, T, ORD, YLW, WHT, WHT, WHT, YLW, ORD, T, T, T, T, T,
T, T, T, T, T, ORG, YLW, WHT, YLW, ORG, T, T, T, T, T, T,
T, T, T, T, T, T, ORG, YLW, ORG, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, ORD, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* ── Hazard sprites ─────────────────────────────────── */
/* Turret idle - metallic gun turret mounted on wall/floor */
static const uint32_t turret_idle1[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, T, T, T,
T, T, T, T, GYD, GRY, GRY, GRY, GRY, GRY, GRY, GRY, GRY, GYD, T, T,
T, T, T, T, GYD, GRY, GYL, GRY, GRY, GYL, GRY, GRY, GRY, GYD, T, T,
T, T, T, GYD, GRY, GRY, GRY, RED, RED, GRY, GRY, GRY, GRY, GRY, GYD, T,
T, T, T, GYD, GRY, GRY, GRY, RDD, RDD, GRY, GRY, GRY, GRY, GRY, GYD, T,
T, T, T, T, GYD, GRY, GYL, GRY, GRY, GYL, GRY, GRY, GRY, GYD, T, T,
T, T, T, T, GYD, GRY, GRY, GRY, GRY, GRY, GRY, GRY, GRY, GYD, T, T,
T, T, T, T, T, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, T, T, T,
T, T, T, T, T, T, GYD, GRY, GRY, GYD, T, T, T, T, T, T,
T, T, T, T, T, GYD, GRY, GRY, GRY, GRY, GYD, T, T, T, T, T,
T, T, T, T, GYD, GRY, GRY, GRY, GRY, GRY, GRY, GYD, T, T, T, T,
T, T, T, T, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, T, T, T, T,
};
/* Turret fire - barrel flash */
static const uint32_t turret_fire1[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, ORG, T, T,
T, T, T, T, T, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, YLW, ORG, T,
T, T, T, T, GYD, GRY, GRY, GRY, GRY, GRY, GRY, GRY, GRY, WHT, YLW, T,
T, T, T, T, GYD, GRY, GYL, GRY, GRY, GYL, GRY, GRY, GRY, WHT, YLW, T,
T, T, T, GYD, GRY, GRY, GRY, RED, RED, GRY, GRY, GRY, GRY, YLW, ORG, T,
T, T, T, GYD, GRY, GRY, GRY, RDD, RDD, GRY, GRY, GRY, GRY, YLW, ORG, T,
T, T, T, T, GYD, GRY, GYL, GRY, GRY, GYL, GRY, GRY, GRY, WHT, YLW, T,
T, T, T, T, GYD, GRY, GRY, GRY, GRY, GRY, GRY, GRY, GRY, WHT, YLW, T,
T, T, T, T, T, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, YLW, ORG, T,
T, T, T, T, T, T, GYD, GRY, GRY, GYD, T, T, T, ORG, T, T,
T, T, T, T, T, GYD, GRY, GRY, GRY, GRY, GYD, T, T, T, T, T,
T, T, T, T, GYD, GRY, GRY, GRY, GRY, GRY, GRY, GYD, T, T, T, T,
T, T, T, T, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, T, T, T, T,
};
/* Moving platform - metallic platform with glowing edges */
#define PLT 0x3a6ea5FF /* platform blue */
#define PLD 0x2a5080FF /* platform blue dark */
#define PLL 0x5a9ed5FF /* platform blue light */
static const uint32_t platform1[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
CYN, CYN, CYN, CYN, CYN, CYN, CYN, CYN, CYN, CYN, CYN, CYN, CYN, CYN, CYN, CYN,
PLL, PLL, PLT, PLT, PLT, PLT, PLT, PLT, PLT, PLT, PLT, PLT, PLT, PLT, PLL, PLL,
PLT, PLT, PLT, PLD, PLT, PLT, PLD, PLT, PLT, PLD, PLT, PLT, PLD, PLT, PLT, PLT,
PLT, PLT, PLT, PLD, PLT, PLT, PLD, PLT, PLT, PLD, PLT, PLT, PLD, PLT, PLT, PLT,
PLD, PLD, PLD, PLD, PLD, PLD, PLD, PLD, PLD, PLD, PLD, PLD, PLD, PLD, PLD, PLD,
GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* Flame vent base - metallic grate on floor */
#define FLB 0x2244aaFF /* flame blue */
#define FLD 0x1a3388FF /* flame blue dark */
#define FLL 0x4488ffFF /* flame blue light */
static const uint32_t flame_vent_idle1[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, FLB, FLB, T, T, T, T, T, T, T,
GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD,
GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD,
GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY,
GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD,
GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD,
};
/* Flame vent active - blue flames shooting up from grate */
static const uint32_t flame_vent_active1[16*16] = {
T, T, T, T, T, T, FLD, T, T, FLD, T, T, T, T, T, T,
T, T, T, T, T, FLD, FLB, FLD, FLD, FLB, FLD, T, T, T, T, T,
T, T, T, T, FLD, FLB, FLL, FLB, FLB, FLL, FLB, FLD, T, T, T, T,
T, T, T, FLD, FLB, FLL, WHT, FLL, FLL, WHT, FLL, FLB, FLD, T, T, T,
T, T, T, FLB, FLL, WHT, WHT, FLL, FLL, WHT, WHT, FLL, FLB, T, T, T,
T, T, FLD, FLB, FLL, WHT, WHT, WHT, WHT, WHT, WHT, FLL, FLB, FLD, T, T,
T, T, FLB, FLL, WHT, WHT, WHT, WHT, WHT, WHT, WHT, WHT, FLL, FLB, T, T,
T, T, FLB, FLL, WHT, WHT, WHT, WHT, WHT, WHT, WHT, WHT, FLL, FLB, T, T,
T, T, FLD, FLB, FLL, WHT, WHT, WHT, WHT, WHT, WHT, FLL, FLB, FLD, T, T,
T, T, T, FLB, FLL, FLL, WHT, WHT, WHT, WHT, FLL, FLL, FLB, T, T, T,
T, T, T, T, FLB, FLL, FLL, FLB, FLB, FLL, FLL, FLB, T, T, T, T,
GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD,
GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD,
GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY,
GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD,
GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD,
};
/* Flame vent active frame 2 - flame flicker */
static const uint32_t flame_vent_active2[16*16] = {
T, T, T, T, T, T, T, FLD, FLD, T, T, T, T, T, T, T,
T, T, T, T, T, T, FLD, FLB, FLB, FLD, T, T, T, T, T, T,
T, T, T, T, T, FLD, FLB, FLL, FLL, FLB, FLD, T, T, T, T, T,
T, T, T, T, FLD, FLB, FLL, WHT, WHT, FLL, FLB, FLD, T, T, T, T,
T, T, T, FLD, FLB, FLL, WHT, WHT, WHT, WHT, FLL, FLB, FLD, T, T, T,
T, T, T, FLB, FLL, WHT, WHT, WHT, WHT, WHT, WHT, FLL, FLB, T, T, T,
T, T, FLD, FLB, FLL, WHT, WHT, WHT, WHT, WHT, WHT, FLL, FLB, FLD, T, T,
T, T, FLB, FLL, WHT, WHT, WHT, WHT, WHT, WHT, WHT, WHT, FLL, FLB, T, T,
T, T, FLB, FLL, FLL, WHT, WHT, WHT, WHT, WHT, WHT, FLL, FLL, FLB, T, T,
T, T, T, FLB, FLL, FLL, WHT, WHT, WHT, WHT, FLL, FLL, FLB, T, T, T,
T, T, T, T, FLB, FLB, FLL, FLB, FLB, FLL, FLB, FLB, T, T, T, T,
GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD,
GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD,
GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY,
GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD, GRY, GYD,
GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD, GYD,
};
/* Force field on - vertical energy barrier */
#define FFB 0x4466ffFF /* force field blue */
#define FFD 0x2244ccFF /* force field dark */
#define FFL 0x88aaFFFF /* force field light */
static const uint32_t force_field_on1[16*16] = {
T, T, T, FFD, T, FFD, FFB, FFL, FFL, FFB, FFD, T, FFD, T, T, T,
T, T, FFD, FFB, FFD, FFB, FFL, WHT, WHT, FFL, FFB, FFD, FFB, FFD, T, T,
T, T, T, FFB, FFB, FFL, WHT, WHT, WHT, WHT, FFL, FFB, FFB, T, T, T,
T, T, FFD, FFB, FFL, WHT, WHT, FFL, FFL, WHT, WHT, FFL, FFB, FFD, T, T,
T, T, T, FFB, FFL, WHT, FFL, FFB, FFB, FFL, WHT, FFL, FFB, T, T, T,
T, T, FFD, FFB, FFB, FFL, FFB, FFD, FFD, FFB, FFL, FFB, FFB, FFD, T, T,
T, T, T, FFB, FFL, FFB, FFD, FFB, FFB, FFD, FFB, FFL, FFB, T, T, T,
T, T, FFD, FFB, FFB, FFD, FFB, FFL, FFL, FFB, FFD, FFB, FFB, FFD, T, T,
T, T, T, FFB, FFD, FFB, FFL, WHT, WHT, FFL, FFB, FFD, FFB, T, T, T,
T, T, FFD, FFB, FFB, FFL, WHT, WHT, WHT, WHT, FFL, FFB, FFB, FFD, T, T,
T, T, T, FFB, FFL, WHT, WHT, FFL, FFL, WHT, WHT, FFL, FFB, T, T, T,
T, T, FFD, FFB, FFB, FFL, FFB, FFD, FFD, FFB, FFL, FFB, FFB, FFD, T, T,
T, T, T, FFB, FFL, FFB, FFD, FFB, FFB, FFD, FFB, FFL, FFB, T, T, T,
T, T, FFD, FFB, FFD, FFB, FFL, FFL, FFL, FFL, FFB, FFD, FFB, FFD, T, T,
T, T, T, FFD, T, FFD, FFB, FFL, FFL, FFB, FFD, T, FFD, T, T, T,
T, T, T, T, T, T, FFD, FFD, FFD, FFD, T, T, T, T, T, T,
};
/* Force field on frame 2 - shimmer */
static const uint32_t force_field_on2[16*16] = {
T, T, T, T, T, FFD, FFB, FFB, FFB, FFB, FFD, T, T, T, T, T,
T, T, T, FFD, FFD, FFB, FFL, FFL, FFL, FFL, FFB, FFD, FFD, T, T, T,
T, T, FFD, FFB, FFB, FFL, WHT, FFL, FFL, WHT, FFL, FFB, FFB, FFD, T, T,
T, T, T, FFB, FFL, WHT, FFL, FFB, FFB, FFL, WHT, FFL, FFB, T, T, T,
T, T, FFD, FFB, FFB, FFL, FFB, FFD, FFD, FFB, FFL, FFB, FFB, FFD, T, T,
T, T, T, FFB, FFL, FFB, FFD, FFB, FFB, FFD, FFB, FFL, FFB, T, T, T,
T, T, FFD, FFB, FFB, FFD, FFB, FFL, FFL, FFB, FFD, FFB, FFB, FFD, T, T,
T, T, T, FFB, FFD, FFB, FFL, WHT, WHT, FFL, FFB, FFD, FFB, T, T, T,
T, T, FFD, FFB, FFB, FFL, WHT, WHT, WHT, WHT, FFL, FFB, FFB, FFD, T, T,
T, T, T, FFB, FFL, WHT, FFL, FFB, FFB, FFL, WHT, FFL, FFB, T, T, T,
T, T, FFD, FFB, FFB, FFL, FFB, FFD, FFD, FFB, FFL, FFB, FFB, FFD, T, T,
T, T, T, FFB, FFL, FFB, FFD, FFB, FFB, FFD, FFB, FFL, FFB, T, T, T,
T, T, FFD, FFB, FFD, FFB, FFL, FFL, FFL, FFL, FFB, FFD, FFB, FFD, T, T,
T, T, T, FFD, T, FFD, FFB, FFL, FFL, FFB, FFD, T, FFD, T, T, T,
T, T, T, T, T, T, FFD, FFB, FFB, FFD, T, T, T, T, T, T,
T, T, T, T, T, T, T, FFD, FFD, T, T, T, T, T, T, T,
};
/* Force field off - just dim posts/emitters */
static const uint32_t force_field_off1[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, FFD, FFD, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, FFD, FFD, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, FFD, FFD, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, FFD, FFD, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, FFD, FFD, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, FFD, FFD, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* ── Powerup sprites ────────────────────────────────── */
/* Health powerup — red cross / heart icon */
static const uint32_t powerup_health1[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, RDL, RDL, T, T, RDL, RDL, T, T, T, T, T,
T, T, T, T, RDL, RED, RED, RDL, RDL, RED, RED, RDL, T, T, T, T,
T, T, T, RDL, RED, RED, RED, RED, RED, RED, RED, RED, RDL, T, T, T,
T, T, T, RDL, RED, RED, WHT, RED, RED, WHT, RED, RED, RDL, T, T, T,
T, T, T, RDL, RED, RED, RED, WHT, WHT, RED, RED, RED, RDL, T, T, T,
T, T, T, RDL, RED, RED, RED, RED, RED, RED, RED, RED, RDL, T, T, T,
T, T, T, T, RDL, RED, RED, RED, RED, RED, RED, RDL, T, T, T, T,
T, T, T, T, T, RDL, RED, RED, RED, RED, RDL, T, T, T, T, T,
T, T, T, T, T, T, RDL, RED, RED, RDL, T, T, T, T, T, T,
T, T, T, T, T, T, T, RDD, RDD, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* Health powerup frame 2 — slight glow/pulse */
static const uint32_t powerup_health2[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, RDL, RDL, T, T, RDL, RDL, T, T, T, T, T,
T, T, T, T, RDL, RED, RED, RDL, RDL, RED, RED, RDL, T, T, T, T,
T, T, T, RDL, RED, RED, RED, RED, RED, RED, RED, RED, RDL, T, T, T,
T, T, RDL, RED, RED, RED, RED, RED, RED, RED, RED, RED, RED, RDL, T, T,
T, T, RDL, RED, RED, RED, WHT, WHT, WHT, WHT, RED, RED, RED, RDL, T, T,
T, T, RDL, RED, RED, WHT, WHT, WHT, WHT, WHT, WHT, RED, RED, RDL, T, T,
T, T, RDL, RED, RED, RED, WHT, WHT, WHT, WHT, RED, RED, RED, RDL, T, T,
T, T, T, RDL, RED, RED, RED, RED, RED, RED, RED, RED, RDL, T, T, T,
T, T, T, T, RDL, RED, RED, RED, RED, RED, RED, RDL, T, T, T, T,
T, T, T, T, T, RDL, RED, RED, RED, RED, RDL, T, T, T, T, T,
T, T, T, T, T, T, RDD, RDD, RDD, RDD, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* Jetpack recharge powerup — orange lightning bolt */
static const uint32_t powerup_jetpack1[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, ORG, ORG, ORG, T, T, T, T, T, T,
T, T, T, T, T, T, ORG, YLW, YLW, ORG, T, T, T, T, T, T,
T, T, T, T, T, ORG, YLW, YLW, ORG, T, T, T, T, T, T, T,
T, T, T, T, ORG, YLW, YLW, ORG, T, T, T, T, T, T, T, T,
T, T, T, ORG, YLW, WHT, YLW, ORG, ORG, ORG, ORG, T, T, T, T, T,
T, T, T, ORG, YLW, WHT, WHT, YLW, YLW, YLW, ORG, T, T, T, T, T,
T, T, T, T, ORG, ORG, ORG, YLW, WHT, YLW, ORG, T, T, T, T, T,
T, T, T, T, T, T, T, ORG, YLW, ORG, T, T, T, T, T, T,
T, T, T, T, T, T, ORG, YLW, ORG, T, T, T, T, T, T, T,
T, T, T, T, T, ORG, YLW, ORG, T, T, T, T, T, T, T, T,
T, T, T, T, T, ORG, ORG, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* Jetpack powerup frame 2 — brighter glow */
static const uint32_t powerup_jetpack2[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, YLW, YLW, YLW, T, T, T, T, T, T,
T, T, T, T, T, T, YLW, WHT, WHT, YLW, T, T, T, T, T, T,
T, T, T, T, T, YLW, WHT, WHT, YLW, T, T, T, T, T, T, T,
T, T, T, T, YLW, WHT, WHT, YLW, T, T, T, T, T, T, T, T,
T, T, T, YLW, WHT, WHT, WHT, YLW, YLW, YLW, YLW, T, T, T, T, T,
T, T, T, YLW, WHT, WHT, WHT, WHT, WHT, WHT, YLW, T, T, T, T, T,
T, T, T, T, YLW, YLW, YLW, WHT, WHT, WHT, YLW, T, T, T, T, T,
T, T, T, T, T, T, T, YLW, WHT, YLW, T, T, T, T, T, T,
T, T, T, T, T, T, YLW, WHT, YLW, T, T, T, T, T, T, T,
T, T, T, T, T, YLW, WHT, YLW, T, T, T, T, T, T, T, T,
T, T, T, T, T, YLW, YLW, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* Drone powerup — cyan spinning gear/orb */
static const uint32_t powerup_drone1[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, CYD, CYD, T, T, T, T, T, T, T,
T, T, T, T, T, CYD, CYN, CYN, CYN, CYN, CYD, T, T, T, T, T,
T, T, T, T, CYD, CYN, CYN, WHT, WHT, CYN, CYN, CYD, T, T, T, T,
T, T, T, CYD, CYN, CYN, WHT, WHT, WHT, WHT, CYN, CYN, CYD, T, T, T,
T, T, T, CYN, CYN, WHT, WHT, CYN, CYN, WHT, WHT, CYN, CYN, T, T, T,
T, T, CYD, CYN, WHT, WHT, CYN, CYD, CYD, CYN, WHT, WHT, CYN, CYD, T, T,
T, T, CYD, CYN, WHT, WHT, CYN, CYD, CYD, CYN, WHT, WHT, CYN, CYD, T, T,
T, T, T, CYN, CYN, WHT, WHT, CYN, CYN, WHT, WHT, CYN, CYN, T, T, T,
T, T, T, CYD, CYN, CYN, WHT, WHT, WHT, WHT, CYN, CYN, CYD, T, T, T,
T, T, T, T, CYD, CYN, CYN, WHT, WHT, CYN, CYN, CYD, T, T, T, T,
T, T, T, T, T, CYD, CYN, CYN, CYN, CYN, CYD, T, T, T, T, T,
T, T, T, T, T, T, T, CYD, CYD, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* Drone powerup frame 2 — rotated highlight */
static const uint32_t powerup_drone2[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, CYD, CYD, T, T, T, T, T, T, T,
T, T, T, T, T, CYD, CYN, CYN, CYN, CYN, CYD, T, T, T, T, T,
T, T, T, T, CYD, CYN, WHT, WHT, CYN, CYN, CYN, CYD, T, T, T, T,
T, T, T, CYD, CYN, WHT, WHT, CYN, CYN, CYN, CYN, CYN, CYD, T, T, T,
T, T, T, CYN, WHT, WHT, CYN, CYD, CYD, CYN, CYN, CYN, CYN, T, T, T,
T, T, CYD, CYN, WHT, CYN, CYD, CYD, CYD, CYD, CYN, WHT, CYN, CYD, T, T,
T, T, CYD, CYN, WHT, CYN, CYD, CYD, CYD, CYD, CYN, WHT, CYN, CYD, T, T,
T, T, T, CYN, CYN, CYN, CYN, CYD, CYD, CYN, WHT, WHT, CYN, T, T, T,
T, T, T, CYD, CYN, CYN, CYN, CYN, CYN, WHT, WHT, CYN, CYD, T, T, T,
T, T, T, T, CYD, CYN, CYN, CYN, WHT, WHT, CYN, CYD, T, T, T, T,
T, T, T, T, T, CYD, CYN, CYN, CYN, CYN, CYD, T, T, T, T, T,
T, T, T, T, T, T, T, CYD, CYD, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* ── Drone companion sprite ────────────────────────── */
/* Small hovering drone — metallic with cyan thruster */
static const uint32_t drone_frame1[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, GYL, GYL, GYL, GYL, T, T, T, T, T, T,
T, T, T, T, T, GYL, GRY, GRY, GRY, GRY, GYL, T, T, T, T, T,
T, T, T, T, GYL, GRY, GRY, CYN, CYN, GRY, GRY, GYL, T, T, T, T,
T, T, T, T, GYD, GRY, CYN, WHT, WHT, CYN, GRY, GYD, T, T, T, T,
T, T, T, T, GYD, GRY, CYN, WHT, WHT, CYN, GRY, GYD, T, T, T, T,
T, T, T, T, GYL, GRY, GRY, CYN, CYN, GRY, GRY, GYL, T, T, T, T,
T, T, T, T, T, GYD, GRY, GRY, GRY, GRY, GYD, T, T, T, T, T,
T, T, T, T, T, T, GYD, CYD, CYD, GYD, T, T, T, T, T, T,
T, T, T, T, T, T, T, CYN, CYN, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* Drone frame 2 — thruster flicker */
static const uint32_t drone_frame2[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, GYL, GYL, GYL, GYL, T, T, T, T, T, T,
T, T, T, T, T, GYL, GRY, GRY, GRY, GRY, GYL, T, T, T, T, T,
T, T, T, T, GYL, GRY, GRY, CYN, CYN, GRY, GRY, GYL, T, T, T, T,
T, T, T, T, GYD, GRY, CYN, WHT, WHT, CYN, GRY, GYD, T, T, T, T,
T, T, T, T, GYD, GRY, CYN, WHT, WHT, CYN, GRY, GYD, T, T, T, T,
T, T, T, T, GYL, GRY, GRY, CYN, CYN, GRY, GRY, GYL, T, T, T, T,
T, T, T, T, T, GYD, GRY, GRY, GRY, GRY, GYD, T, T, T, T, T,
T, T, T, T, T, T, CYD, CYN, CYN, CYD, T, T, T, T, T, T,
T, T, T, T, T, T, CYN, WHT, WHT, CYN, T, T, T, T, T, T,
T, T, T, T, T, T, T, CYD, CYD, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* ── Gun powerup sprite ────────────────────────────── */
/* Gun powerup — metallic gun icon (grey/cyan) */
static const uint32_t powerup_gun1[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, GYD, GYD, GYD, GYD, GYD, GYD, GYD, T, T, T,
T, T, T, T, GYD, GYD, GRY, GRY, GYL, GYL, GYL, GRY, GRY, GYD, T, T,
T, T, T, GYD, GRY, GRY, GYL, WHT, WHT, WHT, GYL, GRY, GRY, GRY, GYD, T,
T, T, T, GYD, GRY, GYL, WHT, WHT, WHT, WHT, GYL, GRY, GRY, GRY, GYD, T,
T, T, T, T, GYD, GRY, GRY, GYL, GYL, GRY, GRY, GYD, GYD, GYD, T, T,
T, T, T, T, T, T, GYD, GRY, GRY, GYD, T, T, T, T, T, T,
T, T, T, T, T, T, T, GYD, GYD, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* Gun powerup frame 2 — brighter glow */
static const uint32_t powerup_gun2[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, GYD, GYL, GYL, GYL, GYL, GYL, GYL, GYD, T, T, T,
T, T, T, GYD, GYD, GYL, WHT, WHT, WHT, WHT, WHT, GYL, GYL, GYD, T, T,
T, T, T, GYD, GYL, WHT, WHT, WHT, WHT, WHT, WHT, GYL, GYL, GYL, GYD, T,
T, T, T, GYD, GYL, WHT, WHT, WHT, WHT, WHT, WHT, GYL, GYL, GYL, GYD, T,
T, T, T, T, GYD, GYL, GYL, WHT, WHT, GYL, GYL, GYD, GYD, GYD, T, T,
T, T, T, T, T, T, GYD, GYL, GYL, GYD, T, T, T, T, T, T,
T, T, T, T, T, T, T, GYD, GYD, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* ── Fuel powerup sprite ───────────────────────────── */
/* Fuel canister — orange/amber napalm canister icon */
static const uint32_t powerup_fuel1[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, GYD, GYD, GYD, T, T, T, T, T, T, T,
T, T, T, T, T, GYD, GYL, GYL, GYL, GYD, T, T, T, T, T, T,
T, T, T, T, T, ORD, ORG, ORG, ORG, ORD, T, T, T, T, T, T,
T, T, T, T, ORD, ORG, YLW, YLW, ORG, ORG, ORD, T, T, T, T, T,
T, T, T, T, ORD, ORG, YLW, YLW, ORG, ORG, ORD, T, T, T, T, T,
T, T, T, T, ORD, ORG, ORG, ORG, ORG, ORG, ORD, T, T, T, T, T,
T, T, T, T, ORD, ORG, YLD, YLD, YLD, ORG, ORD, T, T, T, T, T,
T, T, T, T, ORD, ORG, ORG, ORG, ORG, ORG, ORD, T, T, T, T, T,
T, T, T, T, ORD, ORG, YLW, YLW, ORG, ORG, ORD, T, T, T, T, T,
T, T, T, T, T, ORD, ORG, ORG, ORG, ORD, T, T, T, T, T, T,
T, T, T, T, T, T, ORD, ORD, ORD, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* Fuel canister frame 2 — brighter glow */
static const uint32_t powerup_fuel2[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, GYL, GYL, GYL, T, T, T, T, T, T, T,
T, T, T, T, T, GYL, WHT, WHT, WHT, GYL, T, T, T, T, T, T,
T, T, T, T, T, ORG, YLW, YLW, YLW, ORG, T, T, T, T, T, T,
T, T, T, T, ORG, YLW, WHT, WHT, YLW, YLW, ORG, T, T, T, T, T,
T, T, T, T, ORG, YLW, WHT, WHT, YLW, YLW, ORG, T, T, T, T, T,
T, T, T, T, ORG, YLW, YLW, YLW, YLW, YLW, ORG, T, T, T, T, T,
T, T, T, T, ORG, YLW, ORG, ORG, ORG, YLW, ORG, T, T, T, T, T,
T, T, T, T, ORG, YLW, YLW, YLW, YLW, YLW, ORG, T, T, T, T, T,
T, T, T, T, ORG, YLW, WHT, WHT, YLW, YLW, ORG, T, T, T, T, T,
T, T, T, T, T, ORG, YLW, YLW, YLW, ORG, T, T, T, T, T, T,
T, T, T, T, T, T, ORG, ORG, ORG, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* ── Asteroid sprite ────────────────────────────────── */
/* Asteroid-specific greys — cold, cratered moonrock */
#define AST 0x9a9a9aFF /* asteroid surface mid-grey */
#define ASL 0xc0c0c0FF /* asteroid light (rim highlight) */
#define ASD 0x606060FF /* asteroid dark (crater shadow) */
#define ASK 0x404040FF /* asteroid darkest (deep crater) */
#define ASO 0x787878FF /* asteroid outline */
/* Asteroid frame 1 — jagged cratered boulder, irregular silhouette */
static const uint32_t asteroid1[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, ASO, ASO, ASO, T, T, T, T, T, T, T, T,
T, T, T, T, ASO, ASL, AST, ASO, ASO, T, T, T, T, T, T, T,
T, T, T, ASO, ASL, AST, AST, ASD, AST, ASO, ASO, T, T, T, T, T,
T, T, ASO, ASL, AST, AST, ASD, ASK, ASD, AST, AST, ASO, T, T, T, T,
T, T, ASO, AST, AST, ASD, ASK, ASD, AST, AST, ASL, AST, ASO, T, T, T,
T, ASO, AST, AST, ASD, ASD, AST, AST, AST, ASD, AST, AST, ASO, T, T, T,
T, ASO, AST, AST, AST, AST, ASD, ASO, AST, AST, ASD, AST, ASO, T, T, T,
T, ASO, AST, ASD, AST, AST, AST, AST, ASD, ASK, ASD, AST, ASO, ASO, T, T,
T, T, ASO, AST, AST, ASD, ASK, ASD, AST, ASD, AST, AST, AST, ASO, T, T,
T, T, ASO, AST, AST, AST, ASD, AST, AST, AST, AST, ASL, ASO, T, T, T,
T, T, T, ASO, AST, AST, AST, ASD, AST, AST, ASO, ASO, T, T, T, T,
T, T, T, T, ASO, ASO, AST, AST, ASO, ASO, T, T, T, T, T, T,
T, T, T, T, T, ASO, ASO, ASO, ASO, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* Asteroid frame 2 — shifted crater highlights for tumble animation */
static const uint32_t asteroid2[16*16] = {
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, ASO, ASO, ASO, T, T, T, T, T, T, T,
T, T, T, T, T, ASO, AST, ASL, ASO, ASO, T, T, T, T, T, T,
T, T, T, T, ASO, AST, AST, AST, ASD, ASL, ASO, T, T, T, T, T,
T, T, T, ASO, AST, ASD, ASK, ASD, AST, AST, AST, ASO, T, T, T, T,
T, T, ASO, AST, AST, AST, ASD, AST, AST, ASD, ASK, ASD, ASO, T, T, T,
T, T, ASO, AST, ASL, AST, AST, ASD, AST, AST, ASD, AST, ASO, T, T, T,
T, ASO, AST, AST, AST, ASD, AST, ASO, ASD, AST, AST, AST, ASO, T, T, T,
T, ASO, AST, AST, ASD, ASK, ASD, AST, AST, AST, AST, ASO, ASO, T, T, T,
T, T, ASO, AST, AST, ASD, AST, AST, ASD, ASK, ASD, AST, ASO, T, T, T,
T, T, ASO, ASL, AST, AST, AST, ASD, AST, ASD, AST, ASO, T, T, T, T,
T, T, T, ASO, AST, AST, ASD, AST, AST, ASO, ASO, T, T, T, T, T,
T, T, T, T, ASO, AST, AST, ASO, ASO, T, T, T, T, T, T, T,
T, T, T, T, T, ASO, ASO, ASO, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
};
/* ── Spritesheet generation ────────────────────────── */
/* All sprite definitions for the sheet - row, column, pixel data */
typedef struct SpriteDef {
int row;
int col;
const uint32_t *pixels;
} SpriteDef;
static const SpriteDef s_sprite_defs[] = {
/* Row 0: Player */
{0, 0, player_idle1},
{0, 1, player_idle2},
{0, 2, player_run1},
{0, 3, player_run2},
{0, 4, player_run3},
{0, 5, player_run4},
{0, 6, player_jump},
{0, 7, player_fall},
/* Row 1: Grunt */
{1, 0, grunt_idle1},
{1, 1, grunt_idle2},
{1, 2, grunt_walk1},
{1, 3, grunt_walk2},
{1, 4, grunt_walk1}, /* reuse frame */
{1, 5, grunt_walk2}, /* reuse frame */
{1, 6, grunt_death},
/* Row 2: Flyer */
{2, 0, flyer_idle1},
{2, 1, flyer_idle2},
{2, 2, flyer_idle1}, /* reuse for fly anim */
{2, 3, flyer_idle2},
{2, 4, flyer_idle1},
{2, 5, flyer_idle2},
{2, 6, flyer_death},
/* Row 3: Projectiles */
{3, 0, bullet1},
{3, 1, bullet2},
{3, 2, impact1},
{3, 3, impact2},
{3, 4, impact3},
{3, 5, enemy_bullet1},
{3, 6, enemy_bullet2},
/* Row 4: Hazards */
{4, 0, turret_idle1},
{4, 1, turret_fire1},
{4, 2, platform1},
{4, 3, flame_vent_idle1},
{4, 4, flame_vent_active1},
{4, 5, flame_vent_active2},
{4, 6, force_field_on1},
{4, 7, force_field_on2},
/* Row 5: Hazards continued + Powerups */
{5, 0, force_field_off1},
{5, 1, powerup_health1},
{5, 2, powerup_health2},
{5, 3, powerup_jetpack1},
{5, 4, powerup_jetpack2},
{5, 5, powerup_drone1},
{5, 6, powerup_drone2},
/* Row 6: Drone companion + Gun powerup + Asteroid */
{6, 0, drone_frame1},
{6, 1, drone_frame2},
{6, 2, powerup_gun1},
{6, 3, powerup_gun2},
{6, 4, asteroid1},
{6, 5, asteroid2},
{6, 6, powerup_fuel1},
{6, 7, powerup_fuel2},
};
#define SHEET_COLS 8
#define SHEET_ROWS 7
SDL_Texture *sprites_generate(SDL_Renderer *renderer) {
int w = SHEET_COLS * SPRITE_CELL;
int h = SHEET_ROWS * SPRITE_CELL;
SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(
0, w, h, 32, SDL_PIXELFORMAT_RGBA8888);
if (!surface) {
fprintf(stderr, "Failed to create sprite surface: %s\n", SDL_GetError());
return NULL;
}
/* Clear to transparent */
SDL_FillRect(surface, NULL, 0);
/* Blit each sprite definition */
int count = sizeof(s_sprite_defs) / sizeof(s_sprite_defs[0]);
for (int i = 0; i < count; i++) {
const SpriteDef *def = &s_sprite_defs[i];
int ox = def->col * SPRITE_CELL;
int oy = def->row * SPRITE_CELL;
uint32_t *pixels = (uint32_t *)surface->pixels;
int pitch = surface->pitch / 4; /* pitch in uint32_t */
for (int y = 0; y < SPRITE_CELL; y++) {
for (int x = 0; x < SPRITE_CELL; x++) {
uint32_t rgba = def->pixels[y * SPRITE_CELL + x];
if (rgba == 0) continue; /* transparent */
/* Convert from our RRGGBBAA to surface format */
uint8_t r = (rgba >> 24) & 0xFF;
uint8_t g = (rgba >> 16) & 0xFF;
uint8_t b = (rgba >> 8) & 0xFF;
uint8_t a = (rgba) & 0xFF;
pixels[(oy + y) * pitch + (ox + x)] =
SDL_MapRGBA(surface->format, r, g, b, a);
}
}
}
SDL_Texture *tex = SDL_CreateTextureFromSurface(renderer, surface);
SDL_FreeSurface(surface);
if (!tex) {
fprintf(stderr, "Failed to create sprite texture: %s\n", SDL_GetError());
return NULL;
}
SDL_SetTextureBlendMode(tex, SDL_BLENDMODE_BLEND);
g_spritesheet = tex;
printf("Generated spritesheet: %dx%d (%d sprites)\n", w, h, count);
return tex;
}
/* ── Animation definitions ─────────────────────────── */
#define FRAME(col, row, dur) \
{ .src = {(col)*SPRITE_CELL, (row)*SPRITE_CELL, SPRITE_CELL, SPRITE_CELL}, .duration = (dur) }
/* Player */
static AnimFrame s_player_idle_frames[] = {
FRAME(0, 0, 0.6f),
FRAME(1, 0, 0.6f),
};
static AnimFrame s_player_run_frames[] = {
FRAME(2, 0, 0.1f),
FRAME(3, 0, 0.1f),
FRAME(4, 0, 0.1f),
FRAME(5, 0, 0.1f),
};
static AnimFrame s_player_jump_frames[] = {
FRAME(6, 0, 1.0f),
};
static AnimFrame s_player_fall_frames[] = {
FRAME(7, 0, 1.0f),
};
/* Grunt */
static AnimFrame s_grunt_idle_frames[] = {
FRAME(0, 1, 0.5f),
FRAME(1, 1, 0.5f),
};
static AnimFrame s_grunt_walk_frames[] = {
FRAME(2, 1, 0.15f),
FRAME(3, 1, 0.15f),
FRAME(4, 1, 0.15f),
FRAME(5, 1, 0.15f),
};
static AnimFrame s_grunt_death_frames[] = {
FRAME(6, 1, 0.3f),
};
/* Flyer */
static AnimFrame s_flyer_idle_frames[] = {
FRAME(0, 2, 0.3f),
FRAME(1, 2, 0.3f),
};
static AnimFrame s_flyer_fly_frames[] = {
FRAME(2, 2, 0.12f),
FRAME(3, 2, 0.12f),
FRAME(4, 2, 0.12f),
FRAME(5, 2, 0.12f),
};
static AnimFrame s_flyer_death_frames[] = {
FRAME(6, 2, 0.3f),
};
/* Projectiles */
static AnimFrame s_bullet_frames[] = {
FRAME(0, 3, 0.08f),
FRAME(1, 3, 0.08f),
};
static AnimFrame s_impact_frames[] = {
FRAME(2, 3, 0.05f),
FRAME(3, 3, 0.05f),
FRAME(4, 3, 0.08f),
};
static AnimFrame s_enemy_bullet_frames[] = {
FRAME(5, 3, 0.1f),
FRAME(6, 3, 0.1f),
};
/* Hazard animations */
static AnimFrame s_turret_idle_frames[] = {
FRAME(0, 4, 1.0f),
};
static AnimFrame s_turret_fire_frames[] = {
FRAME(1, 4, 0.15f),
};
static AnimFrame s_platform_frames[] = {
FRAME(2, 4, 1.0f),
};
static AnimFrame s_flame_vent_idle_frames[] = {
FRAME(3, 4, 1.0f),
};
static AnimFrame s_flame_vent_active_frames[] = {
FRAME(4, 4, 0.08f),
FRAME(5, 4, 0.08f),
};
static AnimFrame s_force_field_on_frames[] = {
FRAME(6, 4, 0.15f),
FRAME(7, 4, 0.15f),
};
static AnimFrame s_force_field_off_frames[] = {
FRAME(0, 5, 1.0f),
};
/* Powerups */
static AnimFrame s_powerup_health_frames[] = {
FRAME(1, 5, 0.4f),
FRAME(2, 5, 0.4f),
};
static AnimFrame s_powerup_jetpack_frames[] = {
FRAME(3, 5, 0.3f),
FRAME(4, 5, 0.3f),
};
static AnimFrame s_powerup_drone_frames[] = {
FRAME(5, 5, 0.3f),
FRAME(6, 5, 0.3f),
};
/* Fuel powerup */
static AnimFrame s_powerup_fuel_frames[] = {
FRAME(6, 6, 0.35f),
FRAME(7, 6, 0.35f),
};
/* Gun powerup */
static AnimFrame s_powerup_gun_frames[] = {
FRAME(2, 6, 0.4f),
FRAME(3, 6, 0.4f),
};
/* Asteroid */
static AnimFrame s_asteroid_frames[] = {
FRAME(4, 6, 0.15f),
FRAME(5, 6, 0.15f),
};
/* Drone companion */
static AnimFrame s_drone_frames[] = {
FRAME(0, 6, 0.2f),
FRAME(1, 6, 0.2f),
};
/* Exported animation definitions */
AnimDef anim_player_idle;
AnimDef anim_player_run;
AnimDef anim_player_jump;
AnimDef anim_player_fall;
AnimDef anim_grunt_idle;
AnimDef anim_grunt_walk;
AnimDef anim_grunt_death;
AnimDef anim_flyer_idle;
AnimDef anim_flyer_fly;
AnimDef anim_flyer_death;
AnimDef anim_bullet;
AnimDef anim_bullet_impact;
AnimDef anim_enemy_bullet;
AnimDef anim_turret_idle;
AnimDef anim_turret_fire;
AnimDef anim_platform;
AnimDef anim_flame_vent_idle;
AnimDef anim_flame_vent_active;
AnimDef anim_force_field_on;
AnimDef anim_force_field_off;
AnimDef anim_powerup_health;
AnimDef anim_powerup_jetpack;
AnimDef anim_powerup_fuel;
AnimDef anim_powerup_drone;
AnimDef anim_powerup_gun;
AnimDef anim_asteroid;
AnimDef anim_drone;
void sprites_init_anims(void) {
anim_player_idle = (AnimDef){s_player_idle_frames, 2, true, NULL};
anim_player_run = (AnimDef){s_player_run_frames, 4, true, NULL};
anim_player_jump = (AnimDef){s_player_jump_frames, 1, false, NULL};
anim_player_fall = (AnimDef){s_player_fall_frames, 1, false, NULL};
anim_grunt_idle = (AnimDef){s_grunt_idle_frames, 2, true, NULL};
anim_grunt_walk = (AnimDef){s_grunt_walk_frames, 4, true, NULL};
anim_grunt_death = (AnimDef){s_grunt_death_frames, 1, false, NULL};
anim_flyer_idle = (AnimDef){s_flyer_idle_frames, 2, true, NULL};
anim_flyer_fly = (AnimDef){s_flyer_fly_frames, 4, true, NULL};
anim_flyer_death = (AnimDef){s_flyer_death_frames, 1, false, NULL};
anim_bullet = (AnimDef){s_bullet_frames, 2, true, NULL};
anim_bullet_impact = (AnimDef){s_impact_frames, 3, false, NULL};
anim_enemy_bullet = (AnimDef){s_enemy_bullet_frames, 2, true, NULL};
anim_turret_idle = (AnimDef){s_turret_idle_frames, 1, true, NULL};
anim_turret_fire = (AnimDef){s_turret_fire_frames, 1, false, NULL};
anim_platform = (AnimDef){s_platform_frames, 1, true, NULL};
anim_flame_vent_idle = (AnimDef){s_flame_vent_idle_frames, 1, true, NULL};
anim_flame_vent_active = (AnimDef){s_flame_vent_active_frames, 2, true, NULL};
anim_force_field_on = (AnimDef){s_force_field_on_frames, 2, true, NULL};
anim_force_field_off = (AnimDef){s_force_field_off_frames, 1, true, NULL};
anim_powerup_health = (AnimDef){s_powerup_health_frames, 2, true, NULL};
anim_powerup_jetpack = (AnimDef){s_powerup_jetpack_frames, 2, true, NULL};
anim_powerup_fuel = (AnimDef){s_powerup_fuel_frames, 2, true, NULL};
anim_powerup_drone = (AnimDef){s_powerup_drone_frames, 2, true, NULL};
anim_powerup_gun = (AnimDef){s_powerup_gun_frames, 2, true, NULL};
anim_asteroid = (AnimDef){s_asteroid_frames, 2, true, NULL};
anim_drone = (AnimDef){s_drone_frames, 2, true, NULL};
}