#ifndef ENTITY_H #define ENTITY_H #include "sprite.h" #include "mixer.h" enum entity_prop { ENTITY_PROP_NONE, ENTITY_PROP_ACTIVE, ENTITY_PROP_RELEASE_AT_END_OF_TICK, ENTITY_PROP_PLAYER_CONTROLLED, ENTITY_PROP_CAMERA, ENTITY_PROP_CAMERA_ACTIVE, ENTITY_PROP_BULLET, ENTITY_PROP_WEAPON, ENTITY_PROP_TRIGGERING_EQUIPPED, ENTITY_PROP_TRIGGERED_THIS_TICK, ENTITY_PROP_TRIGGER_NEXT_TICK, /* Test props */ ENTITY_PROP_TEST, ENTITY_PROP_TEST_SOUND_EMITTER, ENTITY_PROP_COUNT }; struct entity_handle { u64 idx; u64 gen; }; struct entity_store { struct arena arena; u64 allocated; u64 reserved; struct entity_handle first_free; struct entity_handle root; struct entity *entities; }; struct entity { /* Metadata */ b32 valid; /* Is this entity allocated in memory that can be written to (can always be read) */ struct entity_handle handle; u64 continuity_gen; u64 props[(ENTITY_PROP_COUNT + 63) / 64]; struct entity_handle next_free; /* Special value stored in first entity in store array */ u64 store_offset; /* Is this the root entity */ b32 is_root; /* Is the parent the root entity */ b32 is_top; /* Tree */ struct entity_handle parent; struct entity_handle next; struct entity_handle prev; struct entity_handle first; struct entity_handle last; /* ====================================================================== */ /* Position */ /* Access with xform getters/setters */ struct xform local_xform; /* Transform in relation to parent entity (or the world if entity has no parent) */ struct xform cached_global_xform; /* Calculated from entity tree */ b32 cached_global_xform_dirty; /* ====================================================================== */ /* Control */ struct { struct v2 move; struct v2 focus; } control; /* ====================================================================== */ /* Player control */ /* ENTITY_PROP_PLAYER_CONTROLLED */ f32 player_max_speed; f32 player_acceleration; /* ====================================================================== */ /* Physics */ struct v2 acceleration; struct v2 velocity; /* ====================================================================== */ /* Sprite */ struct sprite_tag sprite; struct string sprite_span_name; u32 sprite_tint; struct xform sprite_local_xform; /* Sprite transform in relation to entity */ /* ====================================================================== */ /* Animation */ /* ENTITY_PROP_ANIMATING */ f64 animation_time_in_frame; u32 animation_frame; /* ====================================================================== */ /* Equip */ struct entity_handle equipped; /* ====================================================================== */ /* Triggers */ /* ENTITY_PROP_TRIGGERED_THIS_TICK */ f32 trigger_delay; /* Minimum time between triggers */ f32 last_triggered; /* ====================================================================== */ /* Bullet */ struct entity_handle bullet_src; /* ====================================================================== */ /* Testing */ /* ENTITY_PROP_TEST */ b32 test_initialized; struct xform test_start_local_xform; struct xform test_start_sprite_xform; /* ENTITY_PROP_TEST_SOUND_EMITTER */ struct string sound_name; struct mixer_desc sound_desc; struct mixer_track_handle sound_handle; /* ====================================================================== */ /* ENTITY_PROP_CAMERA */ struct entity_handle camera_follow; struct xform camera_quad_xform; f32 camera_lerp; /* Rate at which camera xform approaches target xform */ u32 camera_lerp_continuity_gen; struct xform camera_xform_target; /* Calculated from camera_follow */ u32 camera_applied_lerp_continuity_gen_plus_one; /* Calculated */ }; struct entity_array { struct entity *entities; u64 count; }; struct entity_prop_array { enum entity_prop *props; u64 count; }; /* ========================== * * Handle helpers * ========================== */ INLINE struct entity_handle entity_nil_handle(void) { return (struct entity_handle) { 0 }; } INLINE b32 entity_handle_eq(struct entity_handle a, struct entity_handle b) { return a.gen == b.gen && a.idx == b.idx; } /* ========================== * * Nil * ========================== */ INLINE struct entity *entity_nil(void) { extern READONLY struct entity _g_entity_nil; return &_g_entity_nil; } INLINE struct entity_store *entity_store_nil(void) { extern READONLY struct entity_store _g_entity_store_nil; return &_g_entity_store_nil; } /* ========================== * * Property helpers * ========================== */ INLINE void entity_enable_prop(struct entity *ent, enum entity_prop prop) { u64 index = prop / 64; u64 bit = prop % 64; ent->props[index] |= ((u64)1 << bit); } INLINE void entity_disable_prop(struct entity *ent, enum entity_prop prop) { u64 index = prop / 64; u64 bit = prop % 64; ent->props[index] &= ~((u64)1 << bit); } INLINE b32 entity_has_prop(struct entity *ent, enum entity_prop prop) { u64 index = prop / 64; u64 bit = prop % 64; return !!(ent->props[index] & ((u64)1 << bit)); } /* ========================== * * Entity functions * ========================== */ /* Entity store */ struct entity_store *entity_store_alloc(void); void entity_store_release(struct entity_store *store); void entity_store_copy_replace(struct entity_store *dest, struct entity_store *src); void entity_store_reset(struct entity_store *store); /* Entity */ struct entity *entity_alloc(struct entity *parent); void entity_release(struct entity_store *store, struct entity *ent); /* Xform */ struct xform entity_get_xform(struct entity *ent); struct xform entity_get_local_xform(struct entity *ent); void entity_set_xform(struct entity *ent, struct xform xf); void entity_set_local_xform(struct entity *ent, struct xform xf); /* Query */ struct entity_store *entity_get_store(struct entity *ent); struct entity *entity_from_handle(struct entity_store *store, struct entity_handle handle); struct entity *entity_find_first_match_one(struct entity_store *store, enum entity_prop prop); struct entity *entity_find_first_match_all(struct entity_store *store, struct entity_prop_array props); /* Tree */ void entity_link_parent_child(struct entity *parent, struct entity *child); void entity_unlink_parent(struct entity *ent); void entity_unlink_children(struct entity *ent); #endif