weapon attachment to parent
This commit is contained in:
parent
9424c9c2c9
commit
f48a059397
BIN
res/graphics/gun.ase
(Stored with Git LFS)
BIN
res/graphics/gun.ase
(Stored with Git LFS)
Binary file not shown.
BIN
res/graphics/tim.ase
(Stored with Git LFS)
BIN
res/graphics/tim.ase
(Stored with Git LFS)
Binary file not shown.
32
src/entity.c
32
src/entity.c
@ -265,25 +265,29 @@ struct xform entity_get_local_xform(struct entity *ent)
|
||||
|
||||
void entity_set_xform(struct entity *ent, struct xform xf)
|
||||
{
|
||||
struct entity_store *store = entity_get_store(ent);
|
||||
/* Update local xform */
|
||||
if (ent->is_top) {
|
||||
ent->local_xform = xf;
|
||||
} else {
|
||||
struct entity *parent = entity_from_handle(store, ent->parent);
|
||||
struct xform parent_global = entity_get_xform_w_store(store, parent);
|
||||
ent->local_xform = xform_mul(xform_invert(parent_global), xf);
|
||||
if (!xform_eq(xf, ent->cached_global_xform)) {
|
||||
struct entity_store *store = entity_get_store(ent);
|
||||
/* Update local xform */
|
||||
if (ent->is_top) {
|
||||
ent->local_xform = xf;
|
||||
} else {
|
||||
struct entity *parent = entity_from_handle(store, ent->parent);
|
||||
struct xform parent_global = entity_get_xform_w_store(store, parent);
|
||||
ent->local_xform = xform_mul(xform_invert(parent_global), xf);
|
||||
}
|
||||
ent->cached_global_xform = xf;
|
||||
ent->cached_global_xform_dirty = false;
|
||||
entity_mark_child_xforms_dirty(store, ent);
|
||||
}
|
||||
ent->cached_global_xform = xf;
|
||||
ent->cached_global_xform_dirty = false;
|
||||
entity_mark_child_xforms_dirty(store, ent);
|
||||
}
|
||||
|
||||
void entity_set_local_xform(struct entity *ent, struct xform xf)
|
||||
{
|
||||
ent->local_xform = xf;
|
||||
ent->cached_global_xform_dirty = true;
|
||||
entity_mark_child_xforms_dirty(entity_get_store(ent), ent);
|
||||
if (!xform_eq(xf, ent->local_xform)) {
|
||||
ent->local_xform = xf;
|
||||
ent->cached_global_xform_dirty = true;
|
||||
entity_mark_child_xforms_dirty(entity_get_store(ent), ent);
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
|
||||
@ -24,6 +24,8 @@ enum entity_prop {
|
||||
|
||||
ENTITY_PROP_BULLET,
|
||||
|
||||
ENTITY_PROP_ATTACHED,
|
||||
|
||||
/* Test props */
|
||||
|
||||
ENTITY_PROP_TEST,
|
||||
@ -122,6 +124,13 @@ struct entity {
|
||||
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 */
|
||||
|
||||
|
||||
48
src/game.c
48
src/game.c
@ -118,9 +118,9 @@ INTERNAL void spawn_test_entities(void)
|
||||
entity_set_xform(e, xf);
|
||||
|
||||
e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase"));
|
||||
e->sprite_span_name = STR("idle.unarmed");
|
||||
//e->sprite_span_name = STR("idle.unarmed");
|
||||
//e->sprite_span_name = STR("idle.one_handed");
|
||||
//e->sprite_span_name = STR("idle.two_handed");
|
||||
e->sprite_span_name = STR("idle.two_handed");
|
||||
|
||||
entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED);
|
||||
e->player_max_speed = 4.f;
|
||||
@ -140,18 +140,14 @@ INTERNAL void spawn_test_entities(void)
|
||||
f32 r = PI / 4;
|
||||
struct entity *e = entity_alloc(root);
|
||||
#else
|
||||
struct v2 pos = V2(0.1, 0);
|
||||
struct v2 size = V2(1, 1);
|
||||
f32 r = 0;
|
||||
struct entity *e = entity_alloc(player_ent);
|
||||
#endif
|
||||
|
||||
|
||||
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
|
||||
entity_set_local_xform(e, xf);
|
||||
|
||||
e->sprite = sprite_tag_from_path(STR("res/graphics/gun.ase"));
|
||||
|
||||
entity_enable_prop(e, ENTITY_PROP_ATTACHED);
|
||||
e->attach_slice = STR("attach.wep");
|
||||
|
||||
entity_enable_prop(e, ENTITY_PROP_WEAPON);
|
||||
e->trigger_delay = 1.0 / 10.0;
|
||||
|
||||
@ -284,7 +280,8 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
||||
if (!ent->valid) continue;
|
||||
|
||||
if (!entity_has_prop(ent, ENTITY_PROP_ACTIVE)) {
|
||||
if (ent->activation_tick == 0 || G.tick.tick_id >= ent->activation_tick) {
|
||||
u64 atick = ent->activation_tick;
|
||||
if (atick != 0 || G.tick.tick_id >= atick) {
|
||||
entity_enable_prop(ent, ENTITY_PROP_ACTIVE);
|
||||
ent->activation_tick = G.tick.tick_id;
|
||||
++ent->continuity_gen;
|
||||
@ -360,6 +357,33 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
||||
ent->sprite_local_xform = xf;
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Update attachments
|
||||
* ========================== */
|
||||
|
||||
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
|
||||
struct entity *ent = &store->entities[entity_index];
|
||||
if (!(ent->valid && entity_has_prop(ent, ENTITY_PROP_ACTIVE))) continue;
|
||||
|
||||
if (entity_has_prop(ent, ENTITY_PROP_ATTACHED)) {
|
||||
struct entity *parent = entity_from_handle(store, ent->parent);
|
||||
struct sprite_tag parent_sprite = parent->sprite;
|
||||
struct sprite_sheet *parent_sheet = sprite_sheet_from_tag_await(sprite_frame_scope, parent_sprite);
|
||||
|
||||
struct xform parent_xf = entity_get_xform(parent);
|
||||
struct xform parent_sprite_xf = xform_mul(parent_xf, parent->sprite_local_xform);
|
||||
|
||||
struct sprite_sheet_slice attach_slice = sprite_sheet_get_slice(parent_sheet, ent->attach_slice, parent->animation_frame);
|
||||
struct v2 attach_pos = xform_mul_v2(parent_sprite_xf, attach_slice.center);
|
||||
struct v2 attach_dir = xform_basis_mul_v2(parent_sprite_xf, attach_slice.dir);
|
||||
|
||||
struct xform xf = entity_get_xform(ent);
|
||||
xf.og = attach_pos;
|
||||
xf = xform_with_rotation(xf, v2_angle(attach_dir) + PI / 2);
|
||||
entity_set_xform(ent, xf);
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Update control from player cmds
|
||||
* ========================== */
|
||||
@ -506,7 +530,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
||||
bullet->bullet_src = ent->handle;
|
||||
bullet->bullet_src_pos = rel_pos;
|
||||
bullet->bullet_src_dir = rel_dir;
|
||||
bullet->bullet_impulse = 25;
|
||||
bullet->bullet_impulse = 5;
|
||||
|
||||
entity_enable_prop(bullet, ENTITY_PROP_BULLET);
|
||||
}
|
||||
@ -530,7 +554,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
||||
f32 final_xf_angle;
|
||||
{
|
||||
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, ent->sprite);
|
||||
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("hold"), ent->animation_frame);
|
||||
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("attach.wep"), ent->animation_frame);
|
||||
|
||||
f32 forward_hold_angle_offset;
|
||||
{
|
||||
|
||||
@ -741,6 +741,11 @@ INLINE struct v2 xform_get_scale(struct xform xf);
|
||||
INLINE struct trs trs_from_xform(struct xform m);
|
||||
INLINE struct trs trs_lerp(struct trs a, struct trs b, f32 t);
|
||||
|
||||
INLINE b32 xform_eq(struct xform xf1, struct xform xf2)
|
||||
{
|
||||
return v2_eq(xf1.bx, xf2.bx) && v2_eq(xf1.by, xf2.by) && v2_eq(xf1.og, xf2.og);
|
||||
}
|
||||
|
||||
INLINE struct xform xform_from_pos(struct v2 v)
|
||||
{
|
||||
return (struct xform) {
|
||||
|
||||
@ -11,6 +11,9 @@
|
||||
#define MEMCMP_STRUCT(p1, p2) MEMCMP((p1), (p2), sizeof(*p1))
|
||||
#define MEMCMP(p1, p2, n) memcmp((p1), (p2), (n))
|
||||
|
||||
#define MEMEQ_STRUCT(p1, p2) MEMEQ((p1), (p2), sizeof(*p1))
|
||||
#define MEMEQ(p1, p2, n) (MEMCMP((p1), (p2), (n)) == 0)
|
||||
|
||||
#define MEMSET(ptr, val, count) memset((ptr), (val), (count))
|
||||
|
||||
#if CRTLIB
|
||||
|
||||
10
src/sprite.c
10
src/sprite.c
@ -61,8 +61,8 @@ enum cache_node_state {
|
||||
};
|
||||
|
||||
struct cache_node_refcount {
|
||||
i32 count; /* Number of scopes currently holding a reference to this node */
|
||||
u32 last_modified_cycle; /* Last time that refcount was modified */
|
||||
i32 count; /* Number of scopes currently holding a reference to this node */
|
||||
u32 last_modified_cycle; /* Last time that refcount was modified */
|
||||
};
|
||||
CT_ASSERT(sizeof(struct cache_node_refcount) == 8); /* Must fit into 64 bit atomic */
|
||||
|
||||
@ -974,6 +974,8 @@ struct sprite_sheet_slice sprite_sheet_get_slice(struct sprite_sheet *sheet, str
|
||||
/* Return 'pivot' by default */
|
||||
struct sprite_sheet_slice res = { 0 };
|
||||
if (string_eq(name, STR("pivot"))) {
|
||||
/* 'pivot' slice does not exist, return center */
|
||||
res.center = V2(0, 0);
|
||||
res.center_px = v2_mul(sheet->frame_size, 0.5f);
|
||||
res.dir_px = V2(res.center_px.x, 0);
|
||||
res.dir = V2(0, -0.5);
|
||||
@ -1096,10 +1098,10 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sprite_evictor_thread_entry_point, arg)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check usage time */
|
||||
#if RESOURCE_RELOADING
|
||||
/* Check usage time */
|
||||
/* Only check conditional if RESOURCE_RELOADING is enabled,
|
||||
* since over-budget is assumed to be * true otherwise */
|
||||
* since over-budget is assumed to be true otherwise */
|
||||
if (cache_over_budget)
|
||||
#endif
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user