#ifndef JNR_PLAYER_H #define JNR_PLAYER_H #include "engine/entity.h" #include "engine/camera.h" #include "engine/tilemap.h" /* Player physics tuning */ #define PLAYER_SPEED 150.0f /* horizontal speed (px/s) */ #define PLAYER_ACCEL 1200.0f /* ground acceleration */ #define PLAYER_DECEL 1600.0f /* ground deceleration (friction)*/ #define PLAYER_AIR_ACCEL 600.0f /* air acceleration */ #define PLAYER_JUMP_FORCE 320.0f /* initial jump velocity */ #define PLAYER_JUMP_CUT 0.4f /* multiplier when releasing jump*/ #define PLAYER_COYOTE_TIME 0.08f /* seconds after leaving edge */ #define PLAYER_JUMP_BUFFER 0.1f /* seconds before landing */ #define PLAYER_WIDTH 12 #define PLAYER_HEIGHT 16 /* Sprite dimensions (art is larger than hitbox) */ #define PLAYER_SPRITE_W 24 #define PLAYER_SPRITE_H 24 #define PLAYER_DEATH_SPRITE_W 32 #define PLAYER_DEATH_SPRITE_H 32 /* Shooting */ #define PLAYER_SHOOT_COOLDOWN 0.12f /* seconds between shots */ /* Dash / Jetpack */ #define PLAYER_DASH_SPEED 350.0f /* dash velocity (px/s) */ #define PLAYER_DASH_DURATION 0.15f /* seconds the dash lasts */ #define PLAYER_DASH_MAX_CHARGES 3 /* max jetpack charges */ #define PLAYER_DASH_RECHARGE 30.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 */ #define PLAYER_DASH_INV_GRACE 0.15f /* extra invincibility after dash */ /* Aim direction (for shooting) */ typedef enum AimDir { AIM_FORWARD, /* horizontal, based on facing */ AIM_UP, /* straight up */ AIM_DIAG_UP, /* 45 degrees up + forward */ } AimDir; typedef struct PlayerData { float coyote_timer; float jump_buffer_timer; bool jumping; bool was_on_ground; /* on_ground last frame (landing detect) */ float shoot_cooldown; float inv_timer; /* invincibility timer */ /* Dash / Jetpack */ float dash_timer; /* remaining dash time (0=not dashing) */ int dash_charges; /* available jetpack charges */ 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 */ float look_up_timer; /* how long up has been held */ /* Down-arrow double-tap (free downward jetpack) */ float down_tap_timer; /* time since last mid-air down press */ /* Death / Respawn */ float respawn_timer; /* countdown after death anim finishes */ Vec2 spawn_point; /* where to respawn */ } PlayerData; /* Register player entity type with the entity manager */ void player_register(EntityManager *em); /* Entity callbacks */ void player_update(Entity *self, float dt, const Tilemap *map); void player_render(Entity *self, const Camera *cam); void player_destroy(Entity *self); /* Spawn a fully configured player entity */ Entity *player_spawn(EntityManager *em, Vec2 pos); /* Set the entity manager the player lives in (for spawning projectiles) */ void player_set_entity_manager(EntityManager *em); /* Get the player's current look-up offset for the camera */ 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, 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. */ bool player_wants_respawn(const Entity *self); /* Reset the player to alive state at the given position */ void player_respawn(Entity *self, Vec2 pos); #endif /* JNR_PLAYER_H */