start explosion work
This commit is contained in:
parent
2c0b2fcc36
commit
855fa051d0
@ -37,10 +37,10 @@
|
||||
|
||||
/* 64^2 = 4096 bins */
|
||||
#define SPACE_CELL_BINS_SQRT (64)
|
||||
#define SPACE_CELL_SIZE (1.0f)
|
||||
#define SPACE_CELL_SIZE (4)
|
||||
|
||||
#define SIM_TILES_PER_UNIT_SQRT (2)
|
||||
#define SIM_TILES_PER_CHUNK_SQRT (16)
|
||||
#define SIM_TILES_PER_CHUNK_SQRT (1)
|
||||
|
||||
#define SIM_TICKS_PER_SECOND 50
|
||||
//#define SIM_TIMESCALE 1
|
||||
|
||||
@ -1045,13 +1045,13 @@ f32 phys_determine_earliest_toi_for_bullets(struct phys_step_ctx *ctx, f32 step_
|
||||
|
||||
void phys_update_aabbs(struct phys_step_ctx *ctx)
|
||||
{
|
||||
__prof;
|
||||
struct sim_snapshot *ss = ctx->sim_step_ctx->world;
|
||||
struct space *space = ctx->sim_step_ctx->accel->space;
|
||||
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||
struct sim_ent *ent = &ss->ents[sim_ent_index];
|
||||
if (!sim_ent_is_valid_and_active(ent)) continue;
|
||||
if (ent->local_collider.count <= 0) continue;
|
||||
|
||||
if (ent->local_collider.count > 0) {
|
||||
struct xform xf = sim_ent_get_xform(ent);
|
||||
struct space_entry *space_entry = space_entry_from_handle(space, ent->space_handle);
|
||||
if (!space_entry->valid) {
|
||||
@ -1061,6 +1061,7 @@ void phys_update_aabbs(struct phys_step_ctx *ctx)
|
||||
struct aabb aabb = collider_aabb_from_collider(&ent->local_collider, xf);
|
||||
space_entry_update_aabb(space_entry, aabb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
|
||||
@ -141,6 +141,7 @@ enum sim_control_flag {
|
||||
SIM_CONTROL_FLAG_CLEAR_ALL = 1 << 2,
|
||||
SIM_CONTROL_FLAG_SPAWN_TEST = 1 << 3,
|
||||
SIM_CONTROL_FLAG_TILE_TEST = 1 << 4,
|
||||
SIM_CONTROL_FLAG_EXPLODE_TEST = 1 << 5,
|
||||
};
|
||||
|
||||
struct sim_control {
|
||||
|
||||
@ -47,6 +47,9 @@ enum sim_ent_prop {
|
||||
SEPROP_TRIGGERED_THIS_TICK,
|
||||
SEPROP_TRIGGER_NEXT_TICK,
|
||||
|
||||
SEPROP_EXPLOSION,
|
||||
SEPROP_EXPLOSION_STARTED,
|
||||
|
||||
SEPROP_BULLET,
|
||||
SEPROP_TRACER,
|
||||
|
||||
@ -293,8 +296,14 @@ struct sim_ent {
|
||||
struct v2 bullet_src_dir;
|
||||
f32 bullet_impulse;
|
||||
f32 bullet_knockback;
|
||||
f32 bullet_impact_explosion_radius;
|
||||
b32 bullet_has_hit;
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Explosion */
|
||||
|
||||
f32 explosion_radius;
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Tracer */
|
||||
|
||||
|
||||
139
src/sim_step.c
139
src/sim_step.c
@ -23,7 +23,7 @@
|
||||
struct sim_accel sim_accel_alloc(void)
|
||||
{
|
||||
struct sim_accel accel = ZI;
|
||||
accel.space = space_alloc(1, 256);
|
||||
accel.space = space_alloc(SPACE_CELL_SIZE, SPACE_CELL_BINS_SQRT);
|
||||
return accel;
|
||||
}
|
||||
|
||||
@ -94,8 +94,10 @@ INTERNAL struct sim_ent *spawn_test_employee(struct sim_step_ctx *ctx)
|
||||
|
||||
sim_ent_set_xform(e, xf);
|
||||
|
||||
#if 0
|
||||
e->linear_ground_friction = 250;
|
||||
e->angular_ground_friction = 200;
|
||||
#endif
|
||||
|
||||
e->friction = 0;
|
||||
|
||||
@ -187,7 +189,9 @@ INTERNAL void spawn_test_entities(struct sim_step_ctx *ctx, struct v2 offset)
|
||||
/* Enemy */
|
||||
if (ctx->is_master) {
|
||||
struct sim_ent *e = spawn_test_employee(ctx);
|
||||
(UNUSED)e;
|
||||
struct xform xf = sim_ent_get_xform(e);
|
||||
xf.og = offset;
|
||||
sim_ent_set_xform(e, xf);
|
||||
}
|
||||
|
||||
/* Big box */
|
||||
@ -253,32 +257,22 @@ INTERNAL void test_clear_level(struct sim_step_ctx *ctx)
|
||||
* Respond to physics collisions
|
||||
* ========================== */
|
||||
|
||||
INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, collision_data_array, step_ctx)
|
||||
INTERNAL void on_collision(struct sim_ent *e0, struct sim_ent *e1, struct phys_collision_data *data, struct sim_step_ctx *step_ctx)
|
||||
{
|
||||
|
||||
struct sim_snapshot *world = step_ctx->world;
|
||||
struct sim_ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID);
|
||||
|
||||
for (u64 i = 0; i < collision_data_array.count; ++i) {
|
||||
struct phys_collision_data *data = &collision_data_array.a[i];
|
||||
|
||||
struct phys_contact_constraint *constraint = data->constraint;
|
||||
struct sim_ent *e0 = sim_ent_from_id(world, data->e0);
|
||||
struct sim_ent *e1 = sim_ent_from_id(world, data->e1);
|
||||
|
||||
if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) {
|
||||
/* Bullet hit entity */
|
||||
if (sim_ent_has_prop(e0, SEPROP_BULLET) || sim_ent_has_prop(e1, SEPROP_BULLET)) {
|
||||
|
||||
/* Bullet impact */
|
||||
if (sim_ent_has_prop(e0, SEPROP_BULLET)) {
|
||||
struct v2 normal = data->normal; /* Impact normal */
|
||||
struct v2 vrel = v2_neg(data->vrel); /* Impact velocity */
|
||||
|
||||
struct sim_ent *target = e0;
|
||||
struct sim_ent *bullet = e1;
|
||||
if (sim_ent_has_prop(e0, SEPROP_BULLET)) {
|
||||
target = e1;
|
||||
bullet = e0;
|
||||
normal = v2_neg(normal);
|
||||
vrel = v2_neg(vrel);
|
||||
}
|
||||
struct sim_ent *bullet = e0;
|
||||
struct sim_ent *target = e1;
|
||||
struct sim_ent *src = sim_ent_from_id(world, bullet->bullet_src);
|
||||
|
||||
if (bullet->bullet_has_hit || sim_ent_id_eq(src->top, target->top)) {
|
||||
@ -302,10 +296,6 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, collision_data_array, st
|
||||
struct v2 knockback = v2_mul(v2_norm(vrel), bullet->bullet_knockback);
|
||||
sim_ent_apply_linear_impulse(target, knockback, point);
|
||||
|
||||
/* Explode */
|
||||
//if (sim_ent_has_prop(bullet, SEPROP_EXPLODE_ON_IMPACT)) {
|
||||
//}
|
||||
|
||||
/* Create test blood */
|
||||
/* TODO: Remove this */
|
||||
{
|
||||
@ -331,12 +321,37 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, collision_data_array, st
|
||||
decal->angular_damping = 5.0f;
|
||||
}
|
||||
|
||||
/* Create explosion */
|
||||
if (bullet->bullet_impact_explosion_radius > 0) {
|
||||
struct sim_ent *exp = sim_ent_alloc_sync_src(root);
|
||||
sim_ent_set_xform(exp, XFORM_POS(point));
|
||||
|
||||
sim_ent_enable_prop(exp, SEPROP_SENSOR);
|
||||
sim_ent_enable_prop(exp, SEPROP_EXPLOSION);
|
||||
exp->explosion_radius = bullet->bullet_impact_explosion_radius;
|
||||
}
|
||||
|
||||
/* Update bullet */
|
||||
bullet->bullet_has_hit = true;
|
||||
//sim_ent_enable_prop(bullet, SEPROP_RELEASE);
|
||||
sim_ent_enable_prop(bullet, SEPROP_RELEASE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(pre_solve_callback, collision_data_array, step_ctx)
|
||||
{
|
||||
struct sim_snapshot *world = step_ctx->world;
|
||||
for (u64 i = 0; i < collision_data_array.count; ++i) {
|
||||
struct phys_collision_data *data = &collision_data_array.a[i];
|
||||
struct sim_ent *e0 = sim_ent_from_id(world, data->e0);
|
||||
struct sim_ent *e1 = sim_ent_from_id(world, data->e1);
|
||||
if (sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1)) {
|
||||
on_collision(e0, e1, data, step_ctx);
|
||||
if (sim_ent_is_valid_and_active(e1) && sim_ent_is_valid_and_active(e0)) {
|
||||
on_collision(e1, e0, data, step_ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -558,12 +573,25 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
if (!(old_control.flags & SIM_CONTROL_FLAG_SPAWN_TEST)) {
|
||||
logf_info("Spawning (test)");
|
||||
u32 count = 1;
|
||||
f32 spread = 1;
|
||||
f32 spread = 0;
|
||||
for (u32 j = 0; j < count; ++j) {
|
||||
spawn_test_entities(ctx, V2(0, (((f32)j / (f32)count) - 0.5) * spread));
|
||||
struct v2 pos = player->player_cursor_pos;
|
||||
pos.y += (((f32)j / (f32)count) - 0.5) * spread;
|
||||
spawn_test_entities(ctx, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flags & SIM_CONTROL_FLAG_EXPLODE_TEST) {
|
||||
if (!(old_control.flags & SIM_CONTROL_FLAG_EXPLODE_TEST)) {
|
||||
logf_info("Explosion (test)");
|
||||
struct sim_ent *exp = sim_ent_alloc_sync_src(root);
|
||||
sim_ent_set_xform(exp, XFORM_POS(player->player_cursor_pos));
|
||||
|
||||
sim_ent_enable_prop(exp, SEPROP_EXPLOSION);
|
||||
exp->explosion_radius = 50;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & SIM_CONTROL_FLAG_TILE_TEST) {
|
||||
#if 0
|
||||
if (is_master) {
|
||||
@ -901,7 +929,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;
|
||||
@ -951,6 +979,7 @@ 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->mass_unscaled = 0.04f;
|
||||
bullet->inertia_unscaled = 0.00001f;
|
||||
bullet->layer = SIM_LAYER_BULLETS;
|
||||
@ -1199,10 +1228,64 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
{
|
||||
struct phys_step_ctx phys = ZI;
|
||||
phys.sim_step_ctx = ctx;
|
||||
phys.pre_solve_callback = on_collision;
|
||||
phys.pre_solve_callback = pre_solve_callback;
|
||||
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)) {
|
||||
struct xform xf = sim_ent_get_xform(ent);
|
||||
if (!sim_ent_has_prop(ent, SEPROP_EXPLOSION_STARTED)) {
|
||||
f32 radius = ent->explosion_radius;
|
||||
sim_ent_enable_prop(ent, SEPROP_EXPLOSION_STARTED);
|
||||
|
||||
struct collider_shape origin_collider = ZI;
|
||||
origin_collider.count = 1;
|
||||
|
||||
struct aabb aabb = ZI;
|
||||
{
|
||||
struct collider_shape radius_collider = ZI;
|
||||
radius_collider.radius = radius;
|
||||
radius_collider.count = 1;
|
||||
ent->local_collider = radius_collider;
|
||||
aabb = collider_aabb_from_collider(&radius_collider, xf);
|
||||
}
|
||||
|
||||
/* Find ents in blast range */
|
||||
struct space_iter iter = space_iter_begin_aabb(ctx->accel->space, aabb);
|
||||
struct space_entry *space_entry;
|
||||
while ((space_entry = space_iter_next(&iter))) {
|
||||
struct sim_ent *victim = sim_ent_from_id(world, space_entry->ent);
|
||||
if (sim_ent_should_simulate(victim) && sim_ent_has_prop(victim, SEPROP_PHYSICAL_DYNAMIC) && !sim_ent_id_eq(ent->id, victim->id)) {
|
||||
struct xform victim_xf = sim_ent_get_xform(victim);
|
||||
struct collider_closest_points_result closest_points = collider_closest_points(&origin_collider, &victim->local_collider, xf, victim_xf);
|
||||
struct v2 dir = v2_sub(closest_points.p1, closest_points.p0);
|
||||
f32 distance = v2_len(dir);
|
||||
/* TODO: Blast obstruction */
|
||||
if (distance <= radius) {
|
||||
/* TODO: Exponential decay */
|
||||
//f32 ratio = (radius - distance) / radius;
|
||||
//f32 strength = 100;
|
||||
//struct v2 impulse = v2_with_len(dir, strength * ratio);
|
||||
struct v2 impulse = V2(-100, 0);
|
||||
|
||||
//sim_ent_apply_linear_impulse(victim, impulse, closest_points.p1);
|
||||
sim_ent_apply_linear_impulse_to_center(victim, impulse);
|
||||
}
|
||||
}
|
||||
}
|
||||
space_iter_end(iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Update tracers
|
||||
* ========================== */
|
||||
|
||||
@ -145,6 +145,7 @@ GLOBAL READONLY enum user_bind_kind g_binds[SYS_BTN_COUNT] = {
|
||||
[SYS_BTN_M4] = USER_BIND_KIND_TILE_TEST,
|
||||
|
||||
[SYS_BTN_M2] = USER_BIND_KIND_DEBUG_DRAG,
|
||||
[SYS_BTN_F] = USER_BIND_KIND_DEBUG_EXPLODE,
|
||||
[SYS_BTN_C] = USER_BIND_KIND_DEBUG_CLEAR,
|
||||
[SYS_BTN_V] = USER_BIND_KIND_DEBUG_SPAWN,
|
||||
[SYS_BTN_N] = USER_BIND_KIND_DEBUG_STEP,
|
||||
@ -1590,9 +1591,10 @@ INTERNAL void user_update(void)
|
||||
struct bind_state drag_state = G.bind_states[USER_BIND_KIND_DEBUG_DRAG];
|
||||
struct bind_state clear_state = G.bind_states[USER_BIND_KIND_DEBUG_CLEAR];
|
||||
struct bind_state spawn_state = G.bind_states[USER_BIND_KIND_DEBUG_SPAWN];
|
||||
struct bind_state tile_state = G.bind_states[USER_BIND_KIND_TILE_TEST];
|
||||
struct bind_state pause_state = G.bind_states[USER_BIND_KIND_DEBUG_PAUSE];
|
||||
struct bind_state step_state = G.bind_states[USER_BIND_KIND_DEBUG_STEP];
|
||||
struct bind_state tile_state = G.bind_states[USER_BIND_KIND_TILE_TEST];
|
||||
struct bind_state explode_state = G.bind_states[USER_BIND_KIND_DEBUG_EXPLODE];
|
||||
|
||||
if (fire_state.num_presses || fire_state.is_held) {
|
||||
control.flags |= SIM_CONTROL_FLAG_FIRE;
|
||||
@ -1609,6 +1611,9 @@ INTERNAL void user_update(void)
|
||||
if (tile_state.num_presses) {
|
||||
control.flags |= SIM_CONTROL_FLAG_TILE_TEST;
|
||||
}
|
||||
if (explode_state.num_presses) {
|
||||
control.flags |= SIM_CONTROL_FLAG_EXPLODE_TEST;
|
||||
}
|
||||
|
||||
if (pause_state.num_presses) {
|
||||
atomic_i32_eval_xor(&G.user_paused, 1);
|
||||
|
||||
@ -36,6 +36,7 @@ enum user_bind_kind {
|
||||
USER_BIND_KIND_DEBUG_PAUSE,
|
||||
USER_BIND_KIND_DEBUG_STEP,
|
||||
USER_BIND_KIND_DEBUG_DRAG,
|
||||
USER_BIND_KIND_DEBUG_EXPLODE,
|
||||
USER_BIND_KIND_FULLSCREEN,
|
||||
USER_BIND_KIND_ZOOM_IN,
|
||||
USER_BIND_KIND_ZOOM_OUT,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user