physics stuff

This commit is contained in:
2026-07-17 19:07:32 -05:00
parent 0bc80d5df3
commit 5f08337726
38 changed files with 945 additions and 634 deletions
+97 -9
View File
@@ -61,7 +61,7 @@ static void test_physicsWorldStepStraightLineNoObstacles(void **state) {
const uint32_t steps = 10;
for(uint32_t i = 0; i < steps; i++) {
physicsWorldStep(&world, &body, DUSK_TIME_STEP);
physicsWorldStep(&world, &body, DUSK_TIME_STEP, NULL, 0);
}
assert_float_equal(body.position[0], 1.0f * steps * DUSK_TIME_STEP, 0.001f);
@@ -89,7 +89,7 @@ static void test_physicsWorldStepBlockedHorizontally(void **state) {
body.velocity[0] = 5.0f;
for(uint32_t i = 0; i < 60; i++) {
physicsWorldStep(&world, &body, DUSK_TIME_STEP);
physicsWorldStep(&world, &body, DUSK_TIME_STEP, NULL, 0);
}
assert_float_equal(body.position[0], 2.0f, 0.0001f);
@@ -97,7 +97,7 @@ static void test_physicsWorldStepBlockedHorizontally(void **state) {
// Further steps must not push it past the wall.
for(uint32_t i = 0; i < 5; i++) {
physicsWorldStep(&world, &body, DUSK_TIME_STEP);
physicsWorldStep(&world, &body, DUSK_TIME_STEP, NULL, 0);
assert_float_equal(body.position[0], 2.0f, 0.0001f);
}
@@ -117,7 +117,7 @@ static void test_physicsWorldStepGravitySettlesOnFloor(void **state) {
physicsBodyInit(&body, position, extents);
for(uint32_t i = 0; i < 200; i++) {
physicsWorldStep(&world, &body, DUSK_TIME_STEP);
physicsWorldStep(&world, &body, DUSK_TIME_STEP, NULL, 0);
assert_true(body.position[2] >= -0.0001f);
}
@@ -142,7 +142,7 @@ static void test_physicsWorldStepFallsThroughHole(void **state) {
for(uint32_t i = 0; i < 50; i++) {
const float_t previousZ = body.position[2];
physicsWorldStep(&world, &body, DUSK_TIME_STEP);
physicsWorldStep(&world, &body, DUSK_TIME_STEP, NULL, 0);
assert_true(body.position[2] < previousZ);
assert_false(body.grounded);
}
@@ -163,7 +163,7 @@ static void test_physicsWorldStepTerminalVelocityClamp(void **state) {
physicsBodyInit(&body, position, extents);
for(uint32_t i = 0; i < 300; i++) {
physicsWorldStep(&world, &body, DUSK_TIME_STEP);
physicsWorldStep(&world, &body, DUSK_TIME_STEP, NULL, 0);
assert_true(fabsf(body.velocity[2]) <= world.terminalVelocity + 0.0001f);
}
@@ -186,7 +186,7 @@ static void test_physicsWorldStepBlockedByCeiling(void **state) {
body.velocity[2] = 1.0f;
for(uint32_t i = 0; i < 200; i++) {
physicsWorldStep(&world, &body, DUSK_TIME_STEP);
physicsWorldStep(&world, &body, DUSK_TIME_STEP, NULL, 0);
}
assert_float_equal(body.position[2], 1.0f, 0.0001f);
@@ -215,7 +215,7 @@ static void test_physicsWorldStepMultiColumnFootprint(void **state) {
body.velocity[0] = 5.0f;
for(uint32_t i = 0; i < 60; i++) {
physicsWorldStep(&world, &body, DUSK_TIME_STEP);
physicsWorldStep(&world, &body, DUSK_TIME_STEP, NULL, 0);
}
assert_float_equal(body.position[0], 1.0f, 0.0001f);
@@ -242,7 +242,7 @@ static void test_physicsWorldStepRampTreatedAsFlatGround(void **state) {
body.velocity[0] = 5.0f;
for(uint32_t i = 0; i < 60; i++) {
physicsWorldStep(&world, &body, DUSK_TIME_STEP);
physicsWorldStep(&world, &body, DUSK_TIME_STEP, NULL, 0);
assert_float_equal(body.position[2], 0.0f, 0.0001f);
}
@@ -252,6 +252,91 @@ static void test_physicsWorldStepRampTreatedAsFlatGround(void **state) {
assert_int_equal(memoryGetAllocatedCount(), 0);
}
static void test_physicsWorldStepBlockedByOtherBody(void **state) {
testMapReset();
for(worldunit_t x = 0; x < 10; x++) {
testMapSetTile(x, 0, 0, TILE_SHAPE_GROUND);
}
physicsworld_t world;
physicsWorldInit(&world, 0.0f, 40.0f);
const vec3 extents = { 1.0f, 1.0f, 1.0f };
physicsbody_t other;
physicsBodyInit(&other, (vec3){ 5.0f, 0.0f, 0.0f }, extents);
physicsbody_t body;
physicsBodyInit(&body, (vec3){ 0.0f, 0.0f, 0.0f }, extents);
body.velocity[0] = 5.0f;
physicsbody_t *others[] = { &other };
for(uint32_t i = 0; i < 60; i++) {
physicsWorldStep(&world, &body, DUSK_TIME_STEP, others, 1);
}
// Other occupies [5,6) - body (1 unit wide) should stop exactly
// touching it, at x=4.
assert_float_equal(body.position[0], 4.0f, 0.0001f);
assert_float_equal(body.velocity[0], 0.0f, 0.0001f);
assert_float_equal(other.position[0], 5.0f, 0.0001f);
assert_int_equal(memoryGetAllocatedCount(), 0);
}
static void test_physicsWorldStepBlockedByNearestOfMultipleBodies(
void **state
) {
testMapReset();
for(worldunit_t x = 0; x < 20; x++) {
testMapSetTile(x, 0, 0, TILE_SHAPE_GROUND);
}
physicsworld_t world;
physicsWorldInit(&world, 0.0f, 40.0f);
const vec3 extents = { 1.0f, 1.0f, 1.0f };
physicsbody_t nearOther;
physicsBodyInit(&nearOther, (vec3){ 5.0f, 0.0f, 0.0f }, extents);
physicsbody_t farOther;
physicsBodyInit(&farOther, (vec3){ 15.0f, 0.0f, 0.0f }, extents);
physicsbody_t body;
physicsBodyInit(&body, (vec3){ 0.0f, 0.0f, 0.0f }, extents);
body.velocity[0] = 5.0f;
physicsbody_t *others[] = { &farOther, &nearOther };
for(uint32_t i = 0; i < 60; i++) {
physicsWorldStep(&world, &body, DUSK_TIME_STEP, others, 2);
}
assert_float_equal(body.position[0], 4.0f, 0.0001f);
assert_float_equal(body.velocity[0], 0.0f, 0.0001f);
assert_int_equal(memoryGetAllocatedCount(), 0);
}
static void test_physicsWorldResolveBodyOverlapIgnoresSelfAndNull(
void **state
) {
const vec3 extents = { 1.0f, 1.0f, 1.0f };
physicsbody_t body;
physicsBodyInit(&body, (vec3){ 0.0f, 0.0f, 0.0f }, extents);
body.velocity[0] = 1.0f;
physicsbody_t *others[] = { &body, NULL };
physicsWorldResolveBodyOverlap(&body, 0, others, 2);
assert_float_equal(body.position[0], 0.0f, 0.0001f);
assert_float_equal(body.velocity[0], 1.0f, 0.0001f);
assert_int_equal(memoryGetAllocatedCount(), 0);
}
int main(void) {
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_physicsWorldStepStraightLineNoObstacles),
@@ -262,6 +347,9 @@ int main(void) {
cmocka_unit_test(test_physicsWorldStepBlockedByCeiling),
cmocka_unit_test(test_physicsWorldStepMultiColumnFootprint),
cmocka_unit_test(test_physicsWorldStepRampTreatedAsFlatGround),
cmocka_unit_test(test_physicsWorldStepBlockedByOtherBody),
cmocka_unit_test(test_physicsWorldStepBlockedByNearestOfMultipleBodies),
cmocka_unit_test(test_physicsWorldResolveBodyOverlapIgnoresSelfAndNull),
};
return cmocka_run_group_tests(tests, NULL, NULL);