From 4cedd8df31c19315e85f738e1981ad6fb72a65bb Mon Sep 17 00:00:00 2001 From: DualFroz Date: Thu, 27 Aug 2026 12:30:43 +0200 Subject: [PATCH] test: add tests for AABB collision and rigid-body physics stepping --- tests/testPhysics.cpp | 104 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 tests/testPhysics.cpp diff --git a/tests/testPhysics.cpp b/tests/testPhysics.cpp new file mode 100644 index 0000000..e592f4d --- /dev/null +++ b/tests/testPhysics.cpp @@ -0,0 +1,104 @@ +#include "testHarness.h" +#include "vf/Physics.h" + +using namespace vf; + +namespace { + +World floorWorld() { + World world; + for (int x = 0; x < chunkSize; ++x) + for (int z = 0; z < chunkSize; ++z) + world.setBlock(x, 0, z, Block::Stone); + return world; +} + +Player standingPlayer() { + Player player; + player.position = {8.0f, 5.0f, 8.0f}; + return player; +} + +} // namespace + +VF_TEST(physicsPlayerFallsAndLandsOnFloor) { + World world = floorWorld(); + Player player = standingPlayer(); + PhysicsConfig config; + MoveInput input; + + for (int i = 0; i < 300; ++i) stepPlayer(world, player, input, config, 1.0f / 60.0f); + + CHECK(player.onGround); + CHECK_NEAR(player.position.y, 1.0f, 0.02f); // feet rest on top of the y=0 block + CHECK(!boxOverlapsSolid(world, playerBox(player))); +} + +VF_TEST(physicsWallBlocksHorizontalMovement) { + World world = floorWorld(); + for (int y = 1; y <= 3; ++y) + for (int z = 0; z < chunkSize; ++z) + world.setBlock(10, y, z, Block::Stone); + + Player player = standingPlayer(); + PhysicsConfig config; + MoveInput input; + input.strafe = 1.0f; // yaw 0 -> pushes toward +x + + for (int i = 0; i < 300; ++i) stepPlayer(world, player, input, config, 1.0f / 60.0f); + + CHECK(player.position.x + player.width * 0.5f <= 10.0f + 1e-3f); + CHECK(!boxOverlapsSolid(world, playerBox(player))); +} + +VF_TEST(physicsFlyModeIgnoresGravity) { + World world; // empty, nothing to stand on + Player player; + player.position = {0.0f, 20.0f, 0.0f}; + player.flying = true; + PhysicsConfig config; + MoveInput input; + + for (int i = 0; i < 120; ++i) stepPlayer(world, player, input, config, 1.0f / 60.0f); + + CHECK_NEAR(player.position.y, 20.0f, 1e-3f); // hovers in place +} + +VF_TEST(physicsFlyAscendsWithInput) { + World world; + Player player; + player.position = {0.0f, 20.0f, 0.0f}; + player.flying = true; + PhysicsConfig config; + MoveInput input; + input.up = true; + + stepPlayer(world, player, input, config, 1.0f / 60.0f); + CHECK(player.position.y > 20.0f); +} + +VF_TEST(physicsJumpLeavesGround) { + World world = floorWorld(); + Player player = standingPlayer(); + PhysicsConfig config; + MoveInput settle; + for (int i = 0; i < 300; ++i) stepPlayer(world, player, settle, config, 1.0f / 60.0f); + CHECK(player.onGround); + + float restY = player.position.y; + MoveInput jump; + jump.jump = true; + stepPlayer(world, player, jump, config, 1.0f / 60.0f); + CHECK(!player.onGround); + CHECK(player.position.y > restY); +} + +VF_TEST(physicsCannotSpawnOverlappingResolvesOnStep) { + World world = floorWorld(); + Player player = standingPlayer(); + PhysicsConfig config; + MoveInput input; + for (int i = 0; i < 300; ++i) stepPlayer(world, player, input, config, 1.0f / 60.0f); + CHECK(!world.solidAt(static_cast(player.position.x), + static_cast(player.position.y), 8)); +}