Beam raycast now skips the tile the turret is mounted on, so wall-embedded laser turrets can shoot outward. Extract entity_is_enemy() into engine/entity.c as single source of truth for enemy-type checks. Replaces triplicated type lists in level.c, drone.c, and projectile.c that caused the collision bug when new enemy types were added.
88 lines
2.5 KiB
C
88 lines
2.5 KiB
C
#ifndef JNR_ENTITY_H
|
|
#define JNR_ENTITY_H
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include "config.h"
|
|
#include "engine/physics.h"
|
|
#include "engine/animation.h"
|
|
#include "util/vec2.h"
|
|
|
|
/* Forward declarations */
|
|
typedef struct Tilemap Tilemap;
|
|
typedef struct Camera Camera;
|
|
|
|
typedef enum EntityType {
|
|
ENT_NONE = 0,
|
|
ENT_PLAYER,
|
|
ENT_ENEMY_GRUNT,
|
|
ENT_ENEMY_FLYER,
|
|
ENT_PROJECTILE,
|
|
ENT_PICKUP,
|
|
ENT_PARTICLE,
|
|
ENT_TURRET,
|
|
ENT_MOVING_PLATFORM,
|
|
ENT_FLAME_VENT,
|
|
ENT_FORCE_FIELD,
|
|
ENT_POWERUP,
|
|
ENT_DRONE,
|
|
ENT_ASTEROID,
|
|
ENT_SPACECRAFT,
|
|
ENT_LASER_TURRET,
|
|
ENT_ENEMY_CHARGER,
|
|
ENT_SPAWNER,
|
|
ENT_TYPE_COUNT
|
|
} EntityType;
|
|
|
|
/* Entity flags */
|
|
#define ENTITY_INVINCIBLE (1 << 0)
|
|
#define ENTITY_FACING_LEFT (1 << 1)
|
|
#define ENTITY_DEAD (1 << 2)
|
|
#define ENTITY_ALWAYS_UPDATE (1 << 3) /* never culled by distance */
|
|
|
|
typedef struct Entity {
|
|
EntityType type;
|
|
bool active;
|
|
Body body;
|
|
Animation anim;
|
|
int health;
|
|
int max_health;
|
|
int damage;
|
|
uint32_t flags;
|
|
float timer; /* general-purpose timer */
|
|
void *data; /* type-specific data pointer */
|
|
} Entity;
|
|
|
|
/* Function pointer types for entity behaviors */
|
|
typedef void (*EntityUpdateFn)(Entity *self, float dt, const Tilemap *map);
|
|
typedef void (*EntityRenderFn)(Entity *self, const Camera *cam);
|
|
typedef void (*EntityDestroyFn)(Entity *self);
|
|
|
|
typedef struct EntityManager {
|
|
Entity entities[MAX_ENTITIES];
|
|
int count;
|
|
/* dispatch tables */
|
|
EntityUpdateFn update_fn[ENT_TYPE_COUNT];
|
|
EntityRenderFn render_fn[ENT_TYPE_COUNT];
|
|
EntityDestroyFn destroy_fn[ENT_TYPE_COUNT];
|
|
} EntityManager;
|
|
|
|
void entity_manager_init(EntityManager *em);
|
|
Entity *entity_spawn(EntityManager *em, EntityType type, Vec2 pos);
|
|
void entity_destroy(EntityManager *em, Entity *e);
|
|
void entity_update_all(EntityManager *em, float dt, const Tilemap *map,
|
|
const Camera *cam);
|
|
void entity_render_all(EntityManager *em, const Camera *cam);
|
|
void entity_manager_clear(EntityManager *em);
|
|
|
|
/* Register behavior functions for an entity type */
|
|
void entity_register(EntityManager *em, EntityType type,
|
|
EntityUpdateFn update, EntityRenderFn render,
|
|
EntityDestroyFn destroy);
|
|
|
|
/* Returns true if the entity is a hostile enemy type.
|
|
* Single source of truth — add new enemy types here. */
|
|
bool entity_is_enemy(const Entity *e);
|
|
|
|
#endif /* JNR_ENTITY_H */
|