424 lines
12 KiB
C
424 lines
12 KiB
C
#ifndef ENTITY_H
|
|
#define ENTITY_H
|
|
|
|
#include "sprite.h"
|
|
#include "mixer.h"
|
|
#include "phys.h"
|
|
#include "client.h"
|
|
|
|
enum entity_prop {
|
|
ENTITY_PROP_NONE,
|
|
|
|
ENTITY_PROP_ACTIVE,
|
|
|
|
ENTITY_PROP_RELEASE_THIS_TICK,
|
|
ENTITY_PROP_RELEASE_NEXT_TICK,
|
|
|
|
ENTITY_PROP_PHYSICAL_DYNAMIC,
|
|
ENTITY_PROP_PHYSICAL_KINEMATIC,
|
|
|
|
ENTITY_PROP_COLLISION_DEBUG,
|
|
ENTITY_PROP_CONTACT_CONSTRAINT,
|
|
ENTITY_PROP_MOTOR_JOINT,
|
|
ENTITY_PROP_MOUSE_JOINT,
|
|
ENTITY_PROP_SENSOR,
|
|
|
|
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_TRACER,
|
|
|
|
ENTITY_PROP_QUAKE,
|
|
|
|
ENTITY_PROP_ATTACHED,
|
|
|
|
/* Test props */
|
|
|
|
ENTITY_PROP_TEST,
|
|
ENTITY_PROP_TEST_SOUND_EMITTER,
|
|
|
|
ENTITY_PROP_COUNT
|
|
};
|
|
|
|
struct entity_store {
|
|
b32 valid;
|
|
struct arena arena;
|
|
u64 allocated;
|
|
u64 reserved;
|
|
struct entity_handle first_free;
|
|
struct entity_handle root;
|
|
struct entity *entities;
|
|
};
|
|
|
|
struct entity_lookup_key {
|
|
u64 hash;
|
|
};
|
|
|
|
struct entity_lookup_entry {
|
|
struct entity_lookup_key key;
|
|
struct entity_handle entity;
|
|
struct entity_lookup_entry *next;
|
|
struct entity_lookup_entry *prev;
|
|
};
|
|
|
|
struct entity_lookup_bucket {
|
|
struct entity_lookup_entry *first;
|
|
struct entity_lookup_entry *last;
|
|
};
|
|
|
|
struct entity_lookup {
|
|
struct arena arena;
|
|
struct entity_lookup_bucket *buckets;
|
|
u64 num_buckets;
|
|
struct entity_lookup_entry *first_free_entry;
|
|
};
|
|
|
|
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;
|
|
|
|
/* The handle of the top level parent of the entity */
|
|
struct entity_handle 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;
|
|
|
|
/* ====================================================================== */
|
|
/* Activation */
|
|
|
|
/* If 0, the entity will auto activate at start of next tick if not already active. */
|
|
u64 activation_tick;
|
|
|
|
/* ====================================================================== */
|
|
/* Layer */
|
|
|
|
i32 layer;
|
|
i32 final_layer; /* Calculated each tick from entity tree */
|
|
|
|
/* ====================================================================== */
|
|
/* Collider */
|
|
|
|
struct collider_shape local_collider;
|
|
|
|
#if COLLIDER_DEBUG
|
|
struct phys_collision_debug collision_debug_data;
|
|
#endif
|
|
|
|
struct space_entry_handle space_handle;
|
|
|
|
/* ====================================================================== */
|
|
/* Contact constraint */
|
|
|
|
/* ENTITY_PROP_CONSTRAINT_CONTACT */
|
|
struct phys_contact_constraint contact_constraint_data;
|
|
|
|
/* ====================================================================== */
|
|
/* Motor joint */
|
|
|
|
/* ENTITY_PROP_MOTOR_JOINT */
|
|
struct phys_motor_joint motor_joint_data;
|
|
|
|
/* ====================================================================== */
|
|
/* Mouse joint */
|
|
|
|
/* ENTITY_PROP_MOUSE_JOINT */
|
|
struct phys_mouse_joint mouse_joint_data;
|
|
|
|
/* ====================================================================== */
|
|
/* Player */
|
|
|
|
/* ENTITY_PROP_PLAYER_CONTROLLED */
|
|
struct client_handle controlling_client;
|
|
|
|
/* ====================================================================== */
|
|
/* Control */
|
|
|
|
f32 control_force; /* How much force is applied to achieve desired control movement */
|
|
f32 control_force_max_speed; /* Maximum linear velocity achieved by force (m/s) */
|
|
|
|
f32 control_torque; /* How much torque is applied when turning towards desired focus */
|
|
|
|
struct {
|
|
struct v2 move; /* Movement direction vector (speed of 0 -> 1) */
|
|
struct v2 focus; /* Focus direction vector (where should the entity look) */
|
|
} control;
|
|
|
|
struct entity_handle move_joint;
|
|
struct entity_handle aim_joint;
|
|
|
|
/* ====================================================================== */
|
|
/* Physics */
|
|
|
|
/* ENTITY_PROP_PHYSICAL_DYNAMIC */
|
|
|
|
//f32 density; /* Density in kg/m^2 */
|
|
|
|
f32 friction;
|
|
|
|
f32 mass_unscaled; /* Mass of entity in kg before any transformations */
|
|
f32 inertia_unscaled; /* Inertia of entity in kg*m^2 before any transformations */
|
|
|
|
struct entity_handle ground_friction_joint;
|
|
f32 linear_ground_friction;
|
|
f32 angular_ground_friction;
|
|
|
|
/* Use entity_set_linear_velocity & entity_set_angular_velocity to set */
|
|
struct v2 linear_velocity; /* m/s */
|
|
f32 angular_velocity; /* rad/s */
|
|
|
|
struct v2 force;
|
|
f32 torque;
|
|
|
|
f32 linear_damping;
|
|
f32 angular_damping;
|
|
|
|
/* ====================================================================== */
|
|
/* Sprite */
|
|
|
|
struct sprite_tag sprite;
|
|
struct string sprite_span_name;
|
|
u32 sprite_tint;
|
|
|
|
struct string sprite_collider_slice; /* Collider will sync to bounds of this slice if set */
|
|
|
|
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 entity_handle bullet_tracer;
|
|
struct v2 bullet_src_pos;
|
|
struct v2 bullet_src_dir;
|
|
f32 bullet_impulse;
|
|
f32 bullet_knockback;
|
|
b32 bullet_has_hit;
|
|
|
|
/* ====================================================================== */
|
|
/* Tracer */
|
|
|
|
/* ENTITY_PROP_TRACER */
|
|
|
|
struct v2 tracer_start;
|
|
struct v2 tracer_start_velocity;
|
|
f32 tracer_fade_duration; /* Time for tracer to fade from opacity of 1 to 0 */
|
|
|
|
/* calculated each frame */
|
|
struct v2 tracer_gradient_start;
|
|
struct v2 tracer_gradient_end;
|
|
|
|
/* ====================================================================== */
|
|
/* Quake */
|
|
|
|
/* ENTITY_PROP_QUAKE */
|
|
|
|
f32 quake_intensity;
|
|
f32 quake_frequency;
|
|
f32 quake_fade; /* How much intensity to lose per second */
|
|
|
|
/* ====================================================================== */
|
|
/* 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;
|
|
|
|
/* ====================================================================== */
|
|
/* Camera */
|
|
|
|
/* 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 */
|
|
|
|
f32 shake;
|
|
};
|
|
|
|
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_handle_nil(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));
|
|
}
|
|
|
|
INLINE b32 entity_is_valid_and_active(struct entity *ent)
|
|
{
|
|
return ent->valid && entity_has_prop(ent, ENTITY_PROP_ACTIVE);
|
|
}
|
|
|
|
/* ========================== *
|
|
* 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);
|
|
|
|
/* 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);
|
|
|
|
/* Movement */
|
|
INLINE void entity_set_linear_velocity(struct entity *ent, struct v2 velocity) { ent->linear_velocity = v2_clamp_len(velocity, GAME_MAX_LINEAR_VELOCITY); }
|
|
INLINE void entity_set_angular_velocity(struct entity *ent, f32 velocity) { ent->angular_velocity = clamp_f32(velocity, -GAME_MAX_ANGULAR_VELOCITY, GAME_MAX_ANGULAR_VELOCITY); }
|
|
void entity_apply_linear_impulse(struct entity *ent, struct v2 impulse, struct v2 world_point);
|
|
void entity_apply_linear_impulse_to_center(struct entity *ent, struct v2 impulse);
|
|
void entity_apply_force_to_center(struct entity *ent, struct v2 force);
|
|
void entity_apply_angular_impulse(struct entity *ent, f32 impulse);
|
|
void entity_apply_torque(struct entity *ent, f32 torque);
|
|
|
|
/* Query */
|
|
struct entity_store *entity_store_from_entity(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_from_parent(struct entity *ent);
|
|
|
|
/* Lookup */
|
|
struct entity_lookup entity_lookup_alloc(u64 num_buckets);
|
|
void entity_lookup_release(struct entity_lookup *l);
|
|
struct entity_lookup_entry *entity_lookup_get(struct entity_lookup *l, struct entity_lookup_key key);
|
|
void entity_lookup_set(struct entity_lookup *l, struct entity_lookup_key key, struct entity_handle handle);
|
|
void entity_lookup_remove(struct entity_lookup *l, struct entity_lookup_entry *entry);
|
|
struct entity_lookup_key entity_lookup_key_from_two_handles(struct entity_handle h0, struct entity_handle h1);
|
|
|
|
/* Activate */
|
|
void entity_activate(struct entity *ent, u64 current_tick_id);
|
|
|
|
#endif
|