#include #include #include #include "collider.hpp" #include "dinkyecs.hpp" using DinkyECS::Entity; using namespace fmt; FoundList require_found(const SpatialHashTable& collider, Point at, bool diag, size_t expect_size) { println("TEST require_found at={},{}", at.x, at.y); auto [found, nearby] = collider.neighbors(at, diag); REQUIRE(found == true); REQUIRE(nearby.size() == expect_size); return nearby; } TEST_CASE("confirm basic collision operations", "[collision]") { DinkyECS::World world; Entity player = world.entity(); Entity enemy = world.entity(); SpatialHashTable collider; collider.insert({11,11}, player); collider.insert({21,21}, enemy); { // not found auto [found, nearby] = collider.neighbors({1,1}); REQUIRE(!found); REQUIRE(nearby.empty()); } // found FoundList nearby = require_found(collider, {10,10}, true, 1); REQUIRE(nearby[0] == player); { // removed collider.remove({11,11}); auto [found, nearby] = collider.neighbors({10,10}, true); REQUIRE(!found); REQUIRE(nearby.empty()); } collider.insert({11,11}, player); // setup for the move test { // moving, not found collider.move({11,11}, {12, 12}, player); auto [found, nearby] = collider.neighbors({10,10}, true); REQUIRE(!found); REQUIRE(nearby.empty()); } nearby = require_found(collider, {11,11}, true, 1); REQUIRE(nearby[0] == player); // confirm occupied works REQUIRE(collider.occupied({12,12})); REQUIRE(collider.occupied({21,21})); REQUIRE(!collider.occupied({1,10})); } TEST_CASE("confirm multiple entities moving", "[collision]") { DinkyECS::World world; Entity player = world.entity(); Entity e1 = world.entity(); Entity e2 = world.entity(); Entity e3 = world.entity(); SpatialHashTable collider; collider.insert({11,11}, player); collider.insert({10,10}, e2); collider.insert({11,10}, e3); collider.insert({21,21}, e1); FoundList nearby = require_found(collider, {11,11}, false, 1); REQUIRE(nearby[0] == e3); nearby = require_found(collider, {11,11}, true, 2); REQUIRE(nearby[0] == e3); REQUIRE(nearby[1] == e2); collider.move({11,11}, {20,20}, player); nearby = require_found(collider, {20,20}, true, 1); REQUIRE(nearby[0] == e1); } TEST_CASE("test edge cases that might crash", "[collision]") { DinkyECS::World world; Entity player = world.entity(); Entity enemy = world.entity(); SpatialHashTable collider; collider.insert({0,0}, player); Point enemy_at = {1, 0}; collider.insert(enemy_at, enemy); FoundList nearby = require_found(collider, {0,0}, true, 1); collider.move({1,0}, {1,1}, enemy); nearby = require_found(collider, {0,0}, true, 1); REQUIRE(nearby[0] == enemy); collider.move({1,1}, {0,1}, enemy); nearby = require_found(collider, {0,0}, true, 1); REQUIRE(nearby[0] == enemy); } TEST_CASE("check all diagonal works", "[collision]") { DinkyECS::World world; Entity player = world.entity(); Entity enemy = world.entity(); SpatialHashTable collider; Point player_at = {1,1}; collider.insert(player_at, player); Point enemy_at = {1, 0}; collider.insert(enemy_at, enemy); for(size_t x = 0; x <= 2; x++) { for(size_t y = 0; y <= 2; y++) { if(enemy_at.x == player_at.x && enemy_at.y == player_at.y) continue; // skip player spot FoundList nearby = require_found(collider, player_at, true, 1); REQUIRE(nearby[0] == enemy); // move the enemy to a new spot around the player Point move_to = {enemy_at.x + x, enemy_at.y + y}; collider.move(enemy_at, move_to, enemy); enemy_at = move_to; } } }