tracer beginnings

This commit is contained in:
jacob 2025-01-12 11:54:48 -06:00
parent e70047f763
commit a00798fc7a
4 changed files with 120 additions and 43 deletions

View File

@ -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 */

View File

@ -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
* ========================== */

View File

@ -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);
}
}
}

View File

@ -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)) {