forked from tas/major_tom
Implement four feature phases: Phase 1 - Pause menu: extract bitmap font into shared engine/font module, add MODE_PAUSED with Resume/Restart/Quit overlay. Phase 2 - Laser turret hazard: ENT_LASER_TURRET with charge/fire/ cooldown state machine, per-pixel beam raycast, two variants (fixed and tracking). Registered in entity registry with editor icons. Phase 3 - Charger and Spawner enemies: charger ground patrol with detect/telegraph/charge/stun cycle (2s charge timeout), spawner that periodically creates grunts up to a global cap of 3. Phase 4 - Mars campaign: two handcrafted levels (mars01 surface, mars02 base), mars_tileset.png, PARALLAX_STYLE_MARS with salmon sky and red mesas, THEME_MARS_SURFACE/THEME_MARS_BASE for the procedural generator with per-theme gravity/tileset/parallax. Moon campaign now chains moon03 -> mars01 -> mars02 -> victory. Also fix review findings: deterministic seed on generated level restart, NULL checks on calloc in spawn functions, charge timeout to prevent infinite charge on flat terrain, and stop suppressing stderr in Makefile web-serve target so real errors are visible.
96 lines
3.7 KiB
C
96 lines
3.7 KiB
C
#ifndef JNR_ENEMY_H
|
|
#define JNR_ENEMY_H
|
|
|
|
#include "engine/entity.h"
|
|
#include "engine/camera.h"
|
|
#include "engine/tilemap.h"
|
|
|
|
/* ── Grunt enemy ───────────────────────────────────── */
|
|
/* A ground-patrolling enemy that walks back and forth */
|
|
|
|
#define GRUNT_WIDTH 12
|
|
#define GRUNT_HEIGHT 16
|
|
#define GRUNT_SPEED 40.0f /* horizontal walk speed (px/s) */
|
|
#define GRUNT_HEALTH 2
|
|
|
|
typedef struct GruntData {
|
|
float patrol_dir; /* 1.0 or -1.0 */
|
|
float death_timer; /* countdown after dying */
|
|
} GruntData;
|
|
|
|
void grunt_register(EntityManager *em);
|
|
Entity *grunt_spawn(EntityManager *em, Vec2 pos);
|
|
|
|
/* ── Flyer enemy ───────────────────────────────────── */
|
|
/* A flying enemy that bobs up and down, moves toward */
|
|
/* the player when in range */
|
|
|
|
#define FLYER_WIDTH 14
|
|
#define FLYER_HEIGHT 12
|
|
#define FLYER_SPEED 50.0f /* horizontal chase speed (px/s) */
|
|
#define FLYER_BOB_AMP 20.0f /* vertical bob amplitude */
|
|
#define FLYER_BOB_SPD 2.5f /* bob frequency (radians/s) */
|
|
#define FLYER_HEALTH 1
|
|
#define FLYER_DETECT 120.0f /* detection range (px) */
|
|
#define FLYER_SHOOT_CD 2.0f /* seconds between shots */
|
|
|
|
typedef struct FlyerData {
|
|
float bob_timer; /* for sine wave bobbing */
|
|
float base_y; /* original y position */
|
|
float death_timer;
|
|
float shoot_timer; /* cooldown for shooting */
|
|
} FlyerData;
|
|
|
|
void flyer_register(EntityManager *em);
|
|
Entity *flyer_spawn(EntityManager *em, Vec2 pos);
|
|
|
|
/* ── Charger enemy ─────────────────────────────────── */
|
|
/* Ground patrol that detects the player, telegraphs */
|
|
/* briefly, then charges at high speed. Stuns on wall. */
|
|
|
|
#define CHARGER_WIDTH 14
|
|
#define CHARGER_HEIGHT 16
|
|
#define CHARGER_PATROL_SPEED 30.0f /* slow patrol (px/s) */
|
|
#define CHARGER_CHARGE_SPEED 150.0f /* charge rush speed (px/s) */
|
|
#define CHARGER_DETECT_RANGE 200.0f /* horizontal detect (px) */
|
|
#define CHARGER_CHARGE_TIME 2.0f /* max charge duration (s) */
|
|
#define CHARGER_HEALTH 2
|
|
|
|
typedef enum ChargerState {
|
|
CHARGER_PATROL,
|
|
CHARGER_ALERT, /* telegraph before charging */
|
|
CHARGER_CHARGE, /* full-speed horizontal rush */
|
|
CHARGER_STUNNED, /* hit a wall, briefly vulnerable */
|
|
} ChargerState;
|
|
|
|
typedef struct ChargerData {
|
|
ChargerState state;
|
|
float patrol_dir; /* 1.0 or -1.0 */
|
|
float state_timer; /* countdown for current state */
|
|
float death_timer;
|
|
} ChargerData;
|
|
|
|
void charger_register(EntityManager *em);
|
|
Entity *charger_spawn(EntityManager *em, Vec2 pos);
|
|
|
|
/* ── Spawner enemy ─────────────────────────────────── */
|
|
/* Stationary, periodically spawns grunt enemies up to */
|
|
/* a cap. Destructible. */
|
|
|
|
#define SPAWNER_WIDTH 16
|
|
#define SPAWNER_HEIGHT 16
|
|
#define SPAWNER_HEALTH 3
|
|
#define SPAWNER_INTERVAL 4.5f /* seconds between spawns */
|
|
#define SPAWNER_MAX_ALIVE 3 /* max grunts alive at once */
|
|
|
|
typedef struct SpawnerData {
|
|
float spawn_timer; /* countdown to next spawn */
|
|
float death_timer;
|
|
float pulse_timer; /* visual pulse before spawn */
|
|
} SpawnerData;
|
|
|
|
void spawner_register(EntityManager *em);
|
|
Entity *spawner_spawn(EntityManager *em, Vec2 pos);
|
|
|
|
#endif /* JNR_ENEMY_H */
|