Add moon surface intro level with asteroid hazards and unarmed mechanics

Introduce moon01.lvl as the starting level — a pure jump-and-run intro
with no gun and no enemies, just platforming over gaps and dodging falling
asteroids. The player picks up their gun upon transitioning to level01.

New features:
- Moon tileset and PARALLAX_STYLE_MOON with crater terrain backgrounds
- Asteroid entity (ENT_ASTEROID): falls from sky, damages on contact,
  explodes on ground with particles, respawns after delay
- PLAYER_UNARMED directive disables gun for the level
- Pit rescue mechanic: falling costs 1 HP and auto-dashes upward
- Gun powerup entity type for future armed-pickup levels
- Segment-based procedural level generator with themed rooms
- Extended editor with entity palette and improved tile cycling
- Web shell improvements for Emscripten builds
This commit is contained in:
Thomas
2026-03-01 09:20:49 +00:00
parent ea6e16358f
commit fac7085056
30 changed files with 2139 additions and 83 deletions

View File

@@ -33,6 +33,10 @@
#define PLAYER_DASH_MAX_CHARGES 3 /* max jetpack charges */
#define PLAYER_DASH_RECHARGE 3.0f /* seconds to recharge one charge*/
/* Jetpack boost (from powerup) */
#define PLAYER_JETPACK_BOOST_DURATION 15.0f /* seconds the boost lasts */
#define PLAYER_JETPACK_BOOST_RECHARGE 0.5f /* boosted recharge rate (s) */
/* Invincibility after taking damage */
#define PLAYER_INV_TIME 1.5f /* seconds of invincibility */
@@ -56,6 +60,9 @@ typedef struct PlayerData {
int dash_max_charges; /* max charges (for HUD) */
float dash_recharge_timer; /* time until next charge restored*/
Vec2 dash_dir; /* direction of current dash */
float jetpack_boost_timer; /* remaining boost time (0=off) */
/* Weapon */
bool has_gun; /* false until gun powerup picked up */
/* Aiming */
AimDir aim_dir; /* current aim direction */
bool looking_up; /* holding up without moving */
@@ -84,7 +91,13 @@ float player_get_look_up_offset(const Entity *self);
/* Get jetpack dash charge info for HUD (returns false if entity is not player) */
bool player_get_dash_charges(const Entity *self, int *charges, int *max_charges,
float *recharge_pct);
float *recharge_pct, bool *boosted);
/* Arm the player (give them the gun). Safe to call multiple times. */
void player_give_gun(Entity *self);
/* Check if the player has a gun */
bool player_has_gun(const Entity *self);
/* Check if the player is requesting a respawn (death anim finished + timer expired).
* Returns true when respawn should occur. */