diff --git a/src/sim_ent.h b/src/sim_ent.h index 5f9399d8..4a23041c 100644 --- a/src/sim_ent.h +++ b/src/sim_ent.h @@ -295,14 +295,15 @@ struct sim_ent { struct v2 bullet_src_dir; f32 bullet_impulse; f32 bullet_knockback; + f32 bullet_impact_explosion_strength; f32 bullet_impact_explosion_radius; b32 bullet_has_hit; /* ====================================================================== */ /* Explosion */ + f32 explosion_strength; f32 explosion_radius; - u64 explosion_tick; /* ====================================================================== */ /* Tracer */ diff --git a/src/sim_step.c b/src/sim_step.c index bdabb225..75fc053c 100644 --- a/src/sim_step.c +++ b/src/sim_step.c @@ -151,7 +151,7 @@ INTERNAL struct sim_ent *spawn_test_camera(struct sim_snapshot *world, struct si return camera_ent; } -INTERNAL struct sim_ent *spawn_test_explosion(struct sim_snapshot *world, struct v2 pos, f32 radius) +INTERNAL struct sim_ent *spawn_test_explosion(struct sim_snapshot *world, struct v2 pos, f32 strength, f32 radius) { struct sim_ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID); @@ -159,6 +159,7 @@ INTERNAL struct sim_ent *spawn_test_explosion(struct sim_snapshot *world, struct sim_ent_set_xform(ent, XFORM_POS(pos)); sim_ent_enable_prop(ent, SEPROP_EXPLOSION); + ent->explosion_strength = strength; ent->explosion_radius = radius; sim_ent_enable_prop(ent, SEPROP_SENSOR); @@ -323,7 +324,7 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx) /* Create explosion */ if (bullet->bullet_impact_explosion_radius > 0) { - spawn_test_explosion(world, point, bullet->bullet_impact_explosion_radius); + spawn_test_explosion(world, point, bullet->bullet_impact_explosion_strength, bullet->bullet_impact_explosion_radius); } /* Update bullet */ @@ -333,17 +334,12 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx) } /* Explosion blast collision */ - if (sim_ent_has_prop(e0, SEPROP_EXPLOSION) && (e0->explosion_tick == world->tick || e0->explosion_tick == 0)) { + if (sim_ent_has_prop(e0, SEPROP_EXPLOSION)) { struct sim_ent *exp = e0; struct sim_ent *victim = e1; - exp->explosion_tick = world->tick; - //sim_ent_disable_prop(exp, SEPROP_SENSOR); - struct xform xf = sim_ent_get_xform(exp); - f32 radius = exp->explosion_radius; - struct collider_shape origin_collider = ZI; origin_collider.count = 1; @@ -357,12 +353,14 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx) } else { distance = v2_len(dir); } + /* TODO: Blast obstruction */ - if (distance <= radius) { - /* TODO: Exponential decay */ - f32 strength = 100; - f32 ratio = (radius - distance) / radius; - struct v2 impulse = v2_with_len(dir, strength * ratio); + f32 radius = exp->explosion_radius; + f32 strength_center = exp->explosion_strength; + if (distance < radius) { + const f32 falloff_curve = 3; /* Cubic falloff */ + f32 strength_factor = math_pow(1 - distance/radius, falloff_curve); + struct v2 impulse = v2_with_len(dir, strength_center * strength_factor); sim_ent_apply_linear_impulse(victim, impulse, closest_points.p1); } } @@ -613,7 +611,7 @@ void sim_step(struct sim_step_ctx *ctx) if (flags & SIM_CONTROL_FLAG_EXPLODE_TEST) { if (!(old_control.flags & SIM_CONTROL_FLAG_EXPLODE_TEST)) { logf_info("Explosion (test)"); - spawn_test_explosion(world, player->player_cursor_pos, 1); + spawn_test_explosion(world, player->player_cursor_pos, 100, 2); } } } @@ -955,7 +953,7 @@ void sim_step(struct sim_step_ctx *ctx) bullet->bullet_src_dir = rel_dir; //bullet->bullet_impulse = 0.75f; bullet->bullet_impulse = 2.0f; - //bullet->bullet_knockback = 10; + bullet->bullet_knockback = 10; bullet->mass_unscaled = 0.04f; bullet->inertia_unscaled = 0.00001f; bullet->layer = SIM_LAYER_BULLETS; @@ -1005,7 +1003,8 @@ void sim_step(struct sim_step_ctx *ctx) //bullet->bullet_impulse = 0.75f; bullet->bullet_impulse = 0.75; bullet->bullet_knockback = 10; - bullet->bullet_impact_explosion_radius = 1.0; + bullet->bullet_impact_explosion_strength = 200; + bullet->bullet_impact_explosion_radius = 4.0; bullet->mass_unscaled = 0.04f; bullet->inertia_unscaled = 0.00001f; bullet->layer = SIM_LAYER_BULLETS; @@ -1258,6 +1257,19 @@ void sim_step(struct sim_step_ctx *ctx) phys_step(&phys, sim_dt); } + /* ========================== * + * Update explosions + * ========================== */ + + for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { + struct sim_ent *ent = &world->ents[ent_index]; + if (!sim_ent_should_simulate(ent)) continue; + if (!sim_ent_has_prop(ent, SEPROP_EXPLOSION)) continue; + + /* Explosion doesn't need to generate any more collisions after initial physics step */ + //sim_ent_disable_prop(ent, SEPROP_SENSOR); + } + /* ========================== * * Update tracers * ========================== */