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.
@ -265,6 +265,7 @@ struct xform entity_get_local_xform(struct entity *ent)
|
|||||||
|
|
||||||
void entity_set_xform(struct entity *ent, struct xform xf)
|
void entity_set_xform(struct entity *ent, struct xform xf)
|
||||||
{
|
{
|
||||||
|
if (!xform_eq(xf, ent->cached_global_xform)) {
|
||||||
struct entity_store *store = entity_get_store(ent);
|
struct entity_store *store = entity_get_store(ent);
|
||||||
/* Update local xform */
|
/* Update local xform */
|
||||||
if (ent->is_top) {
|
if (ent->is_top) {
|
||||||
@ -277,13 +278,16 @@ void entity_set_xform(struct entity *ent, struct xform xf)
|
|||||||
ent->cached_global_xform = xf;
|
ent->cached_global_xform = xf;
|
||||||
ent->cached_global_xform_dirty = false;
|
ent->cached_global_xform_dirty = false;
|
||||||
entity_mark_child_xforms_dirty(store, ent);
|
entity_mark_child_xforms_dirty(store, ent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void entity_set_local_xform(struct entity *ent, struct xform xf)
|
void entity_set_local_xform(struct entity *ent, struct xform xf)
|
||||||
{
|
{
|
||||||
|
if (!xform_eq(xf, ent->local_xform)) {
|
||||||
ent->local_xform = xf;
|
ent->local_xform = xf;
|
||||||
ent->cached_global_xform_dirty = true;
|
ent->cached_global_xform_dirty = true;
|
||||||
entity_mark_child_xforms_dirty(entity_get_store(ent), ent);
|
entity_mark_child_xforms_dirty(entity_get_store(ent), ent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
|
|||||||
@ -24,6 +24,8 @@ enum entity_prop {
|
|||||||
|
|
||||||
ENTITY_PROP_BULLET,
|
ENTITY_PROP_BULLET,
|
||||||
|
|
||||||
|
ENTITY_PROP_ATTACHED,
|
||||||
|
|
||||||
/* Test props */
|
/* Test props */
|
||||||
|
|
||||||
ENTITY_PROP_TEST,
|
ENTITY_PROP_TEST,
|
||||||
@ -122,6 +124,13 @@ struct entity {
|
|||||||
f64 animation_time_in_frame;
|
f64 animation_time_in_frame;
|
||||||
u32 animation_frame;
|
u32 animation_frame;
|
||||||
|
|
||||||
|
/* ====================================================================== */
|
||||||
|
/* Attachment */
|
||||||
|
|
||||||
|
/* ENTITY_PROP_ATTACHED */
|
||||||
|
/* Slice name on the parent entity's sprite to attach to */
|
||||||
|
struct string attach_slice;
|
||||||
|
|
||||||
/* ====================================================================== */
|
/* ====================================================================== */
|
||||||
/* Equip */
|
/* Equip */
|
||||||
|
|
||||||
|
|||||||
48
src/game.c
48
src/game.c
@ -118,9 +118,9 @@ INTERNAL void spawn_test_entities(void)
|
|||||||
entity_set_xform(e, xf);
|
entity_set_xform(e, xf);
|
||||||
|
|
||||||
e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase"));
|
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.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);
|
entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED);
|
||||||
e->player_max_speed = 4.f;
|
e->player_max_speed = 4.f;
|
||||||
@ -140,18 +140,14 @@ INTERNAL void spawn_test_entities(void)
|
|||||||
f32 r = PI / 4;
|
f32 r = PI / 4;
|
||||||
struct entity *e = entity_alloc(root);
|
struct entity *e = entity_alloc(root);
|
||||||
#else
|
#else
|
||||||
struct v2 pos = V2(0.1, 0);
|
|
||||||
struct v2 size = V2(1, 1);
|
|
||||||
f32 r = 0;
|
|
||||||
struct entity *e = entity_alloc(player_ent);
|
struct entity *e = entity_alloc(player_ent);
|
||||||
#endif
|
#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"));
|
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);
|
entity_enable_prop(e, ENTITY_PROP_WEAPON);
|
||||||
e->trigger_delay = 1.0 / 10.0;
|
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 (!ent->valid) continue;
|
||||||
|
|
||||||
if (!entity_has_prop(ent, ENTITY_PROP_ACTIVE)) {
|
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);
|
entity_enable_prop(ent, ENTITY_PROP_ACTIVE);
|
||||||
ent->activation_tick = G.tick.tick_id;
|
ent->activation_tick = G.tick.tick_id;
|
||||||
++ent->continuity_gen;
|
++ent->continuity_gen;
|
||||||
@ -360,6 +357,33 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
|||||||
ent->sprite_local_xform = xf;
|
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
|
* 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 = ent->handle;
|
||||||
bullet->bullet_src_pos = rel_pos;
|
bullet->bullet_src_pos = rel_pos;
|
||||||
bullet->bullet_src_dir = rel_dir;
|
bullet->bullet_src_dir = rel_dir;
|
||||||
bullet->bullet_impulse = 25;
|
bullet->bullet_impulse = 5;
|
||||||
|
|
||||||
entity_enable_prop(bullet, ENTITY_PROP_BULLET);
|
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;
|
f32 final_xf_angle;
|
||||||
{
|
{
|
||||||
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, ent->sprite);
|
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;
|
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_from_xform(struct xform m);
|
||||||
INLINE struct trs trs_lerp(struct trs a, struct trs b, f32 t);
|
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)
|
INLINE struct xform xform_from_pos(struct v2 v)
|
||||||
{
|
{
|
||||||
return (struct xform) {
|
return (struct xform) {
|
||||||
|
|||||||
@ -11,6 +11,9 @@
|
|||||||
#define MEMCMP_STRUCT(p1, p2) MEMCMP((p1), (p2), sizeof(*p1))
|
#define MEMCMP_STRUCT(p1, p2) MEMCMP((p1), (p2), sizeof(*p1))
|
||||||
#define MEMCMP(p1, p2, n) memcmp((p1), (p2), (n))
|
#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))
|
#define MEMSET(ptr, val, count) memset((ptr), (val), (count))
|
||||||
|
|
||||||
#if CRTLIB
|
#if CRTLIB
|
||||||
|
|||||||
@ -974,6 +974,8 @@ struct sprite_sheet_slice sprite_sheet_get_slice(struct sprite_sheet *sheet, str
|
|||||||
/* Return 'pivot' by default */
|
/* Return 'pivot' by default */
|
||||||
struct sprite_sheet_slice res = { 0 };
|
struct sprite_sheet_slice res = { 0 };
|
||||||
if (string_eq(name, STR("pivot"))) {
|
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.center_px = v2_mul(sheet->frame_size, 0.5f);
|
||||||
res.dir_px = V2(res.center_px.x, 0);
|
res.dir_px = V2(res.center_px.x, 0);
|
||||||
res.dir = V2(0, -0.5);
|
res.dir = V2(0, -0.5);
|
||||||
@ -1096,10 +1098,10 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sprite_evictor_thread_entry_point, arg)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Check usage time */
|
|
||||||
#if RESOURCE_RELOADING
|
#if RESOURCE_RELOADING
|
||||||
|
/* Check usage time */
|
||||||
/* Only check conditional if RESOURCE_RELOADING is enabled,
|
/* 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)
|
if (cache_over_budget)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user