From bac3256d1ef34772898ea3a59e4eb2478463e53b Mon Sep 17 00:00:00 2001 From: jacob Date: Mon, 16 Dec 2024 12:23:58 -0600 Subject: [PATCH] hit event testing --- res/graphics/blood.ase | 3 + src/entity.h | 23 +++++++- src/game.c | 124 ++++++++++++++++++++++++++++++++++------- 3 files changed, 129 insertions(+), 21 deletions(-) create mode 100644 res/graphics/blood.ase diff --git a/res/graphics/blood.ase b/res/graphics/blood.ase new file mode 100644 index 00000000..bf1d1afb --- /dev/null +++ b/res/graphics/blood.ase @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c26894f84d4cfd420f7835cac00921ab5eabc6736e6a10434a986fe6369d9b6a +size 732 diff --git a/src/entity.h b/src/entity.h index da165722..eb54bacb 100644 --- a/src/entity.h +++ b/src/entity.h @@ -15,6 +15,9 @@ enum entity_prop { ENTITY_PROP_CONTACT_CONSTRAINT, ENTITY_PROP_MOTOR_JOINT, ENTITY_PROP_MOUSE_JOINT, + ENTITY_PROP_SENSOR, + + ENTITY_PROP_HIT_EVENT, ENTITY_PROP_PLAYER_CONTROLLED, ENTITY_PROP_CAMERA, @@ -80,6 +83,7 @@ struct contact_point { struct contact_constraint { u64 last_updated_tick; /* To avoid checking collisions for the same constraint twice in one tick */ + b32 skip_solve; struct entity_handle e0; struct entity_handle e1; f32 inv_m0; @@ -173,6 +177,16 @@ struct mouse_joint { +struct hit_event { + struct entity_handle e0; + struct entity_handle e1; + struct v2 point; + struct v2 normal; + struct v2 vrel; /* Relative velocity */ +}; + + + @@ -235,6 +249,11 @@ struct entity { /* ENTITY_PROP_MOUSE_JOINT */ struct mouse_joint mouse_joint_data; + /* ====================================================================== */ + /* Hit event */ + + struct hit_event hit_event; + @@ -263,8 +282,8 @@ struct entity { f32 control_torque; /* How much torque is applied when turning towards desired focus */ struct { - struct v2 move; - struct v2 focus; + 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; diff --git a/src/game.c b/src/game.c index 89b3a29e..b28a2251 100644 --- a/src/game.c +++ b/src/game.c @@ -360,6 +360,25 @@ INTERNAL void spawn_test_entities(void) player_ent = e; } + /* Enemy */ + { + struct entity *e = entity_alloc(root); + + struct v2 pos = V2(1, -2); + f32 r = 0; + struct v2 size = V2(1, 1); + struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size); + entity_set_xform(e, xf); + + e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase")); + + entity_enable_prop(e, ENTITY_PROP_PHYSICAL); + e->mass_unscaled = 10; + e->inertia_unscaled = 10; + e->linear_ground_friction = 250; + e->angular_ground_friction = 200; + } + /* Player weapon */ if (player_ent->valid) { struct entity *e = entity_alloc(player_ent); @@ -395,15 +414,6 @@ INTERNAL void spawn_test_entities(void) - - - - - - - - - /* ========================== * * TESTING CONTACT CONSTRAINT * ========================== */ @@ -481,14 +491,51 @@ INTERNAL void create_contacts(void) if (collider_res.num_points > 0) { if (!entity_is_valid_and_active(constraint_ent)) { - constraint_ent = entity_alloc(root); - constraint_ent->contact_constraint_data.e1 = e1->handle; - constraint_ent->contact_constraint_data.e0 = e0->handle; - /* TODO: Should we recalculate normal as more contact points are added? */ - entity_enable_prop(constraint_ent, ENTITY_PROP_CONTACT_CONSTRAINT); - activate_now(constraint_ent); - if (!entry) { - contact_lookup_set(&G.contact_lookup, lookup_hash, constraint_ent->handle); + /* Create hit event */ + { + struct entity *event = entity_alloc(root); + entity_enable_prop(event, ENTITY_PROP_HIT_EVENT); + event->hit_event.e0 = e0->handle; + event->hit_event.e1 = e1->handle; + event->hit_event.normal = collider_res.normal; + entity_enable_prop(event, ENTITY_PROP_RELEASE_AT_END_OF_FRAME); + entity_enable_prop(event, ENTITY_PROP_ACTIVE); + + /* Calculate point */ + struct v2 point = collider_res.points[0].point; + if (collider_res.num_points > 1) { + point = v2_add(point, v2_mul(v2_sub(collider_res.points[1].point, point), 0.5f)); + } + event->hit_event.point = point; + + /* Calculate relative velocity */ + struct v2 vrel; + { + struct v2 v0 = e0->linear_velocity; + struct v2 v1 = e1->linear_velocity; + f32 w0 = e0->angular_velocity; + f32 w1 = e1->angular_velocity; + struct v2 vcp0 = v2_sub(point, e0_xf.og); + struct v2 vcp1 = v2_sub(point, e1_xf.og); + struct v2 vel0 = v2_add(v0, v2_perp_mul(vcp0, w0)); + struct v2 vel1 = v2_add(v1, v2_perp_mul(vcp1, w1)); + vrel = v2_sub(vel0, vel1); + } + event->hit_event.vrel = vrel; + } + + /* Create constraint */ + { + constraint_ent = entity_alloc(root); + constraint_ent->contact_constraint_data.e1 = e1->handle; + constraint_ent->contact_constraint_data.e0 = e0->handle; + constraint_ent->contact_constraint_data.skip_solve = entity_has_prop(e0, ENTITY_PROP_SENSOR) || entity_has_prop(e1, ENTITY_PROP_SENSOR); + /* TODO: Should we recalculate normal as more contact points are added? */ + entity_enable_prop(constraint_ent, ENTITY_PROP_CONTACT_CONSTRAINT); + activate_now(constraint_ent); + if (!entry) { + contact_lookup_set(&G.contact_lookup, lookup_hash, constraint_ent->handle); + } } } struct contact_constraint *constraint = &constraint_ent->contact_constraint_data; @@ -663,7 +710,7 @@ INTERNAL void warm_start_contacts(void) u32 num_points = constraint->num_points; struct entity *e0 = entity_from_handle(store, constraint->e0); struct entity *e1 = entity_from_handle(store, constraint->e1); - if (num_points > 0 && entity_is_valid_and_active(e0) && entity_is_valid_and_active(e1)) { + if (num_points > 0 && entity_is_valid_and_active(e0) && entity_is_valid_and_active(e1) && !constraint->skip_solve) { struct xform e0_xf = entity_get_xform(e0); struct xform e1_xf = entity_get_xform(e1); @@ -722,7 +769,7 @@ INTERNAL void solve_contacts(f32 dt, b32 apply_bias) f32 w1 = e1->angular_velocity; u32 num_points = constraint->num_points; - if (num_points > 0 && entity_is_valid_and_active(e0) && entity_is_valid_and_active(e1)) { + if (num_points > 0 && entity_is_valid_and_active(e0) && entity_is_valid_and_active(e1) && !constraint->skip_solve) { struct xform e0_xf = entity_get_xform(e0); struct xform e1_xf = entity_get_xform(e1); @@ -1758,6 +1805,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) bullet->inertia_unscaled = 0.00001f; entity_enable_prop(bullet, ENTITY_PROP_BULLET); + entity_enable_prop(bullet, ENTITY_PROP_SENSOR); } } } @@ -1980,6 +2028,44 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) } #endif + /* ========================== * + * Respond to hit events + * ========================== */ + + 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_HIT_EVENT)) continue; + + struct hit_event *event = &ent->hit_event; + + struct entity *e0 = entity_from_handle(store, event->e0); + struct entity *e1 = entity_from_handle(store, event->e1); + + if (entity_is_valid_and_active(e0) && entity_is_valid_and_active(e1)) { + /* Bullet hit entity */ + if (entity_has_prop(e0, ENTITY_PROP_BULLET) || entity_has_prop(e1, ENTITY_PROP_BULLET)) { + struct entity *bullet = entity_has_prop(e0, ENTITY_PROP_BULLET) ? e0 : e1; + struct entity *target = e0 == bullet ? e1 : e0; + + (UNUSED)bullet; + (UNUSED)target; + entity_enable_prop(bullet, ENTITY_PROP_RELEASE_AT_END_OF_FRAME); + + + + /* Create test blood */ + /* TODO: Remove this */ + { + struct xform xf = XFORM_TRS(.t = event->point); + struct entity *decal = entity_alloc(root); + decal->sprite = sprite_tag_from_path(STR("res/graphics/blood.ase")); + entity_set_xform(decal, xf); + } + } + } + } + /* ========================== * * Initialize bullet kinematics from sources * ========================== */