diff --git a/src/entity.h b/src/entity.h index 6a98ee4f..1ab5b567 100644 --- a/src/entity.h +++ b/src/entity.h @@ -110,15 +110,8 @@ struct entity { /* ====================================================================== */ /* Impulse */ - /* ENTITY_PROP_IMPULSE */ - - /* Applies impulse velocity to parent entity */ - struct v2 impulse; - - /* ====================================================================== */ - /* Impulse */ - /* ENTITY_PROP_FORCE */ + /* ENTITY_PROP_IMPULSE */ /* Applies force to parent entity */ struct v2 force; diff --git a/src/game.c b/src/game.c index cddd3311..bf1dc80c 100644 --- a/src/game.c +++ b/src/game.c @@ -96,6 +96,18 @@ INTERNAL struct game_cmd_array pop_cmds(struct arena *arena) return array; } +/* ========================== * + * Activate + * ========================== */ + +INTERNAL void activate_now(struct entity *ent) +{ + entity_enable_prop(ent, ENTITY_PROP_ACTIVE); + ent->activation_tick = G.tick.tick_id; + ent->verlet_xform = entity_get_xform(ent); + ++ent->continuity_gen; +} + /* ========================== * * Test * ========================== */ @@ -180,21 +192,11 @@ INTERNAL void spawn_test_entities(void) f32 width = (f32)DEFAULT_CAMERA_WIDTH; f32 height = (f32)DEFAULT_CAMERA_HEIGHT; e->camera_quad_xform = XFORM_TRS(.s = V2(width, height)); + + activate_now(e); } } -/* ========================== * - * Activate - * ========================== */ - -INTERNAL void activate_now(struct entity *ent) -{ - entity_enable_prop(ent, ENTITY_PROP_ACTIVE); - ent->activation_tick = G.tick.tick_id; - ent->verlet_xform = entity_get_xform(ent); - ++ent->continuity_gen; -} - /* ========================== * * Update * ========================== */ @@ -566,7 +568,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) /* Ground friction */ if (!v2_eq(velocity, V2(0, 0))) { /* FIXME: Incorrect behavior at low FPS & low entity density */ - const f32 clamp_epsilon = 0.025; + const f32 clamp_epsilon = 0.001; f32 velocity_len = v2_len(velocity); if (velocity_len >= clamp_epsilon) { f32 force_len = -velocity_len * ent->ground_friction; @@ -576,9 +578,10 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) activate_now(force); } else { /* If velocity is below clamp_epsilon, stop entity movement. */ + f32 mass = ent->mass_unscaled * xform_get_determinant(xf); struct entity *impulse = entity_alloc(ent); entity_enable_prop(impulse, ENTITY_PROP_IMPULSE); - impulse->impulse = v2_neg(velocity); + impulse->force = v2_mul(v2_neg(velocity), mass); activate_now(impulse); } } @@ -599,22 +602,20 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) struct v2 acceleration = V2(0, 0); - /* Apply impulses */ + /* Apply forces and impulses */ for (struct entity *child = entity_from_handle(store, ent->first); child->valid; child = entity_from_handle(store, child->next)) { - if (entity_has_prop(child, ENTITY_PROP_IMPULSE)) { - struct v2 impulse_acceleration = v2_div(child->impulse, mass); - acceleration = v2_add(acceleration, impulse_acceleration); + b32 is_force = entity_has_prop(child, ENTITY_PROP_FORCE); + b32 is_impulse = entity_has_prop(child, ENTITY_PROP_IMPULSE); + if (is_force || is_impulse) { + struct v2 force_accel = v2_div(child->force, mass); + if (!is_impulse) { + force_accel = v2_mul(force_accel, dt); + } + acceleration = v2_add(acceleration, force_accel); entity_enable_prop(child, ENTITY_PROP_RELEASE); } - } - /* Apply forces */ - for (struct entity *child = entity_from_handle(store, ent->first); child->valid; child = entity_from_handle(store, child->next)) { - if (entity_has_prop(child, ENTITY_PROP_FORCE)) { - struct v2 force_acceleration = v2_mul(v2_div(child->force, mass), dt); - acceleration = v2_add(acceleration, force_acceleration); - entity_enable_prop(child, ENTITY_PROP_RELEASE); - } + } /* Verlet integration */ @@ -717,7 +718,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) /* Create impulse */ struct entity *impulse = entity_alloc(ent); - impulse->impulse = velocity; + impulse->force = velocity; entity_enable_prop(impulse, ENTITY_PROP_IMPULSE); } }