From a00798fc7a9f580d634ac714055370ffdc6b5fd5 Mon Sep 17 00:00:00 2001 From: jacob Date: Sun, 12 Jan 2025 11:54:48 -0600 Subject: [PATCH] tracer beginnings --- src/entity.h | 16 ++++++- src/game.c | 125 ++++++++++++++++++++++++++++++++++++--------------- src/phys.c | 8 ++-- src/user.c | 14 +++++- 4 files changed, 120 insertions(+), 43 deletions(-) diff --git a/src/entity.h b/src/entity.h index 647bddaf..9a66b7df 100644 --- a/src/entity.h +++ b/src/entity.h @@ -10,8 +10,8 @@ enum entity_prop { ENTITY_PROP_ACTIVE, - ENTITY_PROP_RELEASE_BEFORE_PUBLISH, - ENTITY_PROP_RELEASE_AFTER_PUBLISH, + ENTITY_PROP_RELEASE_THIS_TICK, + ENTITY_PROP_RELEASE_NEXT_TICK, ENTITY_PROP_PHYSICAL_DYNAMIC, ENTITY_PROP_PHYSICAL_KINEMATIC, @@ -32,6 +32,7 @@ enum entity_prop { ENTITY_PROP_TRIGGER_NEXT_TICK, ENTITY_PROP_BULLET, + ENTITY_PROP_TRACER, ENTITY_PROP_ATTACHED, @@ -222,9 +223,20 @@ struct entity { /* Bullet */ struct entity_handle bullet_src; + struct entity_handle bullet_tracer; struct v2 bullet_src_pos; struct v2 bullet_src_dir; f32 bullet_impulse; + b32 bullet_has_hit; + + /* ====================================================================== */ + /* Tracer */ + + f64 tracer_start_time; + struct v2 tracer_start; + f32 tracer_fade; /* How many seconds for tracer to fade to transparency */ + + struct v2 tracer_tail; /* ====================================================================== */ /* Testing */ diff --git a/src/game.c b/src/game.c index dcf5d184..38d98d24 100644 --- a/src/game.c +++ b/src/game.c @@ -300,6 +300,9 @@ INTERNAL void release_entities_with_prop(enum entity_prop prop) struct temp_arena scratch = scratch_begin_no_conflict(); struct entity_store *store = G.tick.entity_store; + /* TODO: Breadth first iteration to only release parent entities (since + * child entities will be released along with parent anyway) */ + struct entity **ents_to_release = arena_dry_push(scratch.arena, struct entity *); u64 ents_to_release_count = 0; for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) { @@ -349,27 +352,39 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, array) (UNUSED)target; (UNUSED)src; - if (entity_handle_eq(src->top, target->top)) { - /* Ignore collision if weapon and target share same top level parent */ + if (bullet->bullet_has_hit || entity_handle_eq(src->top, target->top)) { + /* Ignore collision if bullet already spent or if weapon and + * target share same top level parent */ constraint->skip_solve = true; - continue; - } + } else { + struct v2 point = data->point; + struct v2 normal = data->normal; - /* Disable bullet */ - entity_enable_prop(bullet, ENTITY_PROP_RELEASE_BEFORE_PUBLISH); - entity_disable_prop(bullet, ENTITY_PROP_ACTIVE); + /* Update bullet */ + bullet->bullet_has_hit = true; + entity_enable_prop(bullet, ENTITY_PROP_RELEASE_THIS_TICK); - /* Create test blood */ - /* TODO: Remove this */ - { - struct xform xf = XFORM_TRS(.t = data->point); - struct entity *decal = entity_alloc(root); - decal->sprite = sprite_tag_from_path(STR("res/graphics/blood.ase")); - entity_set_xform(decal, xf); + /* Update tracer */ + struct entity *tracer = entity_from_handle(store, bullet->bullet_tracer); + if (entity_is_valid_and_active(tracer)) { + struct xform xf = entity_get_xform(tracer); + xf.og = point; + entity_set_xform(tracer, xf); + tracer->linear_velocity = V2(0, 0); + } - entity_enable_prop(decal, ENTITY_PROP_PHYSICAL_KINEMATIC); - decal->linear_velocity = v2_mul(v2_norm(data->normal), 0.5f); - decal->angular_velocity = 1 - (((f32)sys_rand_u32() / (f32)U32_MAX) * 2); + /* Create test blood */ + /* TODO: Remove this */ + { + struct xform xf = XFORM_TRS(.t = point); + struct entity *decal = entity_alloc(root); + decal->sprite = sprite_tag_from_path(STR("res/graphics/blood.ase")); + entity_set_xform(decal, xf); + + entity_enable_prop(decal, ENTITY_PROP_PHYSICAL_KINEMATIC); + decal->linear_velocity = v2_mul(v2_norm(normal), 0.5f); + decal->angular_velocity = 1 - (((f32)sys_rand_u32() / (f32)U32_MAX) * 2); + } } } } @@ -476,6 +491,12 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) }; } + /* ========================== * + * Release entities + * ========================== */ + + release_entities_with_prop(ENTITY_PROP_RELEASE_NEXT_TICK); + /* ========================== * * Activate entities * ========================== */ @@ -545,7 +566,6 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) } /* Update sprite local xform */ - { struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("pivot"), ent->animation_frame); struct v2 sprite_size = v2_div(sheet->frame_size, (f32)PIXELS_PER_UNIT); @@ -785,24 +805,36 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) struct v2 rel_pos = xform_mul_v2(sprite_local_xform, out_slice.center); struct v2 rel_dir = xform_basis_mul_v2(sprite_local_xform, out_slice.dir); + /* Spawn bullet */ + struct entity *bullet; { - /* Spawn bullet */ - struct entity *bullet = entity_alloc(root); - bullet->sprite = sprite_tag_from_path(STR("res/graphics/bullet.ase")); + bullet = entity_alloc(root); bullet->bullet_src = ent->handle; bullet->bullet_src_pos = rel_pos; bullet->bullet_src_dir = rel_dir; //bullet->bullet_impulse = 0.1f; - //bullet->bullet_impulse = 0.25f; - bullet->bullet_impulse = 5.f; + bullet->bullet_impulse = 0.25f; + //bullet->bullet_impulse = 5.f; bullet->mass_unscaled = 0.04f; bullet->inertia_unscaled = 0.00001f; - bullet->sprite_collider_slice = STR("shape"); + + /* Point collider */ + bullet->local_collider.points[0] = V2(0, 0); + bullet->local_collider.count = 1; entity_enable_prop(bullet, ENTITY_PROP_BULLET); entity_enable_prop(bullet, ENTITY_PROP_SENSOR); } + + /* Spawn tracer */ + { + struct entity *tracer = entity_alloc(root); + tracer->tracer_fade = 0.5f; + entity_enable_prop(tracer, ENTITY_PROP_TRACER); + + bullet->bullet_tracer = tracer->handle; + } } } @@ -1006,10 +1038,11 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) { struct entity *ent = &store->entities[entity_index]; if (!entity_is_valid_and_active(ent)) continue; + if (!entity_has_prop(ent, ENTITY_PROP_BULLET)) continue; /* FIXME: Apply src entity velocity to bullet velocity */ - if (entity_has_prop(ent, ENTITY_PROP_BULLET) && ent->activation_tick == G.tick.tick_id) { + if (ent->activation_tick == G.tick.tick_id) { struct entity *src = entity_from_handle(store, ent->bullet_src); struct xform src_xf = entity_get_xform(src); @@ -1022,9 +1055,38 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) entity_enable_prop(ent, ENTITY_PROP_PHYSICAL_KINEMATIC); entity_apply_linear_impulse_to_center(ent, impulse); + + /* Initialize tracer */ + struct entity *tracer = entity_from_handle(store, ent->bullet_tracer); + if (entity_is_valid_and_active(tracer)) { + entity_set_xform(tracer, xf); + entity_enable_prop(tracer, ENTITY_PROP_PHYSICAL_KINEMATIC); + tracer->linear_velocity = ent->linear_velocity; + tracer->tracer_start_time = time; + tracer->tracer_start = pos; + tracer->tracer_tail = pos; + } } } + /* ========================== * + * Update tracers + * ========================== */ + +#if 0 + for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) { + struct entity *ent = &store->entities[entity_index]; + if (!entity_is_valid_and_active(ent)) continue; + if (!entity_has_prop(ent, ENTITY_PROP_TRACER)) continue; + + struct v2 start = ent->tracer_start; + struct v2 tail = ent->tracer_tail; + struct v2 end = entity_get_xform(ent).og; + + + } +#endif + /* ========================== * * Update camera position * ========================== */ @@ -1097,13 +1159,10 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) } /* ========================== * - * Release entities pre-publish + * Release entities * ========================== */ - /* TODO: Breadth first iteration to only release parent entities (since - * child entities will be released along with parent anyway) */ - - release_entities_with_prop(ENTITY_PROP_RELEASE_BEFORE_PUBLISH); + release_entities_with_prop(ENTITY_PROP_RELEASE_THIS_TICK); /* ========================== * * Publish tick @@ -1113,12 +1172,6 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) publish_game_tick(); __profframe("Game"); - /* ========================== * - * Release entities post-publish - * ========================== */ - - release_entities_with_prop(ENTITY_PROP_RELEASE_AFTER_PUBLISH); - /* ========================== * * End frame cache scopes * ========================== */ diff --git a/src/phys.c b/src/phys.c index b21adc64..ab592b06 100644 --- a/src/phys.c +++ b/src/phys.c @@ -364,7 +364,7 @@ void phys_prepare_contacts(struct phys_ctx *ctx) } else { /* Mark constraint for removal */ entity_disable_prop(constraint_ent, ENTITY_PROP_ACTIVE); - entity_enable_prop(constraint_ent, ENTITY_PROP_RELEASE_BEFORE_PUBLISH); + entity_enable_prop(constraint_ent, ENTITY_PROP_RELEASE_THIS_TICK); /* Remove from lookup */ struct entity_lookup_key key = entity_lookup_key_from_two_handles(constraint->e0, constraint->e1); struct entity_lookup_entry *entry = entity_lookup_get(contact_lookup, key); @@ -392,7 +392,7 @@ void phys_prepare_contacts(struct phys_ctx *ctx) || !(entity_has_prop(e1, ENTITY_PROP_PHYSICAL_DYNAMIC) || entity_has_prop(e1, ENTITY_PROP_PHYSICAL_KINEMATIC))) { /* Mark dbg ent for removal */ entity_disable_prop(dbg_ent, ENTITY_PROP_ACTIVE); - entity_enable_prop(dbg_ent, ENTITY_PROP_RELEASE_BEFORE_PUBLISH); + entity_enable_prop(dbg_ent, ENTITY_PROP_RELEASE_THIS_TICK); /* Remove from lookup */ struct entity_lookup_key key = entity_lookup_key_from_two_handles(dbg->e0, dbg->e1); @@ -660,7 +660,7 @@ void phys_prepare_motor_joints(struct phys_ctx *ctx) } else { /* Mark joint for removal */ entity_disable_prop(joint_ent, ENTITY_PROP_ACTIVE); - entity_enable_prop(joint_ent, ENTITY_PROP_RELEASE_BEFORE_PUBLISH); + entity_enable_prop(joint_ent, ENTITY_PROP_RELEASE_THIS_TICK); } } } @@ -887,7 +887,7 @@ void phys_prepare_mouse_joints(struct phys_ctx *ctx) } else { /* Mark joint for removal */ entity_disable_prop(joint_ent, ENTITY_PROP_ACTIVE); - entity_enable_prop(joint_ent, ENTITY_PROP_RELEASE_BEFORE_PUBLISH); + entity_enable_prop(joint_ent, ENTITY_PROP_RELEASE_THIS_TICK); } } } diff --git a/src/user.c b/src/user.c index 98ffdafa..2c848dfa 100644 --- a/src/user.c +++ b/src/user.c @@ -541,6 +541,8 @@ INTERNAL void user_update(void) e->camera_quad_xform = xform_lerp(e0->camera_quad_xform, e1->camera_quad_xform, tick_blend); e->camera_xform_target = xform_lerp(e0->camera_xform_target, e1->camera_xform_target, tick_blend); + + e->tracer_tail = v2_lerp(e0->tracer_tail, e1->tracer_tail, tick_blend); } } } @@ -862,7 +864,7 @@ INTERNAL void user_update(void) for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) { __profscope(user_entity_iter); struct entity *ent = &store->entities[entity_index]; - if (!(ent->valid && entity_has_prop(ent, ENTITY_PROP_ACTIVE))) continue; + if (!entity_is_valid_and_active(ent)) continue; //if (sprite_tag_is_nil(ent->sprite)) continue; struct sprite_tag sprite = ent->sprite; @@ -907,6 +909,16 @@ INTERNAL void user_update(void) } #endif + /* Draw tracer */ + if (entity_has_prop(ent, ENTITY_PROP_TRACER)) { + struct v2 start = ent->tracer_tail; + struct v2 end = xf.og; + + f32 thickness = 0.0025; + u32 color = RGBA_32_F(1, 1, 1, 1); + draw_solid_line(G.world_canvas, start, end, thickness, color); + } + /* Draw sprite */ //if ((false)) { if (!sprite_tag_is_nil(sprite)) {