accumulate forces and impulses in one pass
This commit is contained in:
parent
0d33c5746f
commit
687ebb4eb9
@ -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;
|
||||
|
||||
55
src/game.c
55
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,19 +192,9 @@ 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
|
||||
* ========================== */
|
||||
|
||||
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;
|
||||
activate_now(e);
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
@ -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);
|
||||
entity_enable_prop(child, ENTITY_PROP_RELEASE);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user