power_play/src/entity.h
2024-09-10 16:11:39 -05:00

341 lines
8.4 KiB
C

#ifndef ENTITY_H
#define ENTITY_H
#include "sprite.h"
#include "mixer.h"
enum entity_prop {
ENTITY_PROP_NONE,
ENTITY_PROP_ACTIVE,
ENTITY_PROP_RELEASE,
ENTITY_PROP_PHYSICAL,
ENTITY_PROP_LINEAR_IMPULSE,
ENTITY_PROP_ANGULAR_IMPULSE,
ENTITY_PROP_FORCE,
ENTITY_PROP_TORQUE,
ENTITY_PROP_PLAYER_CONTROLLED,
ENTITY_PROP_CAMERA,
ENTITY_PROP_CAMERA_ACTIVE,
ENTITY_PROP_WEAPON,
ENTITY_PROP_TRIGGERING_EQUIPPED,
ENTITY_PROP_TRIGGERED_THIS_TICK,
ENTITY_PROP_TRIGGER_NEXT_TICK,
ENTITY_PROP_BULLET,
ENTITY_PROP_ATTACHED,
/* 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;
};
/* TODO: Remove this */
#include "gjk.h"
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;
/* Is this the root entity */
b32 is_root;
/* Is entity a child of 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;
/* TODO: Remove this (testing) */
b32 colliding;
struct entity_handle colliding_with;
struct v2 point;
struct gjk_simplex simplex;
struct gjk_prototype prototype;
struct v2 pendir;
struct xform xf0;
struct xform xf1;
b32 solved;
struct xform predicted_xform;
b32 test_torque_applied;
/* ====================================================================== */
/* Activation */
/* If 0, the entity will auto activate at start of next tick if not already active. */
u64 activation_tick;
/* ====================================================================== */
/* 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 */
f32 control_force; /* How much force is applied to achieve desired control movement */
f32 control_torque; /* How much torque is applied to achieve desired control focus */
struct {
struct v2 move;
struct v2 focus;
} control;
/* ====================================================================== */
/* Physics */
/* ENTITY_PROP_PHYSICAL */
f32 mass_unscaled; /* Mass of entity in kg before any transformations */
f32 inertia_unscaled; /* Inertia of entity in kgm2 before any transformations */
f32 ground_friction;
struct v2 linear_velocity; /* m/s */
f32 angular_velocity; /* rad/s */
/* ====================================================================== */
/* Force */
/* ENTITY_PROP_LINEAR_IMPULSE */
/* ENTITY_PROP_FORCE */
/* Applies force to parent entity */
struct v2 force;
/* ====================================================================== */
/* Force */
/* ENTITY_PROP_ANGULAR_IMPULSE */
/* ENTITY_PROP_TORQUE */
/* Applies torque to parent entity */
f32 torque;
/* ====================================================================== */
/* 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;
/* ====================================================================== */
/* Attachment */
/* ENTITY_PROP_ATTACHED */
/* Slice name on the parent entity's sprite to attach to */
struct string attach_slice;
/* ====================================================================== */
/* 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;
struct v2 bullet_src_pos;
struct v2 bullet_src_dir;
f32 bullet_impulse;
/* ====================================================================== */
/* 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(struct entity *parent, struct entity *child);
void entity_unlink_parent(struct entity *ent);
#endif