From 2d44c101c270fd1277f339bc2fe0e06b67c7d669 Mon Sep 17 00:00:00 2001 From: LazyJazz Date: Sat, 30 Dec 2023 19:44:31 +0800 Subject: [PATCH] Test ready --- CMakeLists.txt | 2 + src/GameBall/CMakeLists.txt | 9 ++- src/GameBall/core/game_ball.cpp | 6 +- src/GameBall/logic/player.cpp | 2 +- src/GameBall/logic/player.h | 2 +- src/GameBall/logic/units/regular_ball.cpp | 20 ++++- src/GameBall/logic/units/regular_ball.h | 5 ++ src/GameBall/logic/world.cpp | 2 +- src/GameBall/logic/world.h | 4 +- src/GameBall/main.cpp | 17 +++- src/GameX/physics/world.cpp | 5 -- test/CMakeLists.txt | 2 +- test/regular_ball_test.cpp | 95 +++++++++++++++++++++++ test/rotation_matrix.cpp | 6 -- 14 files changed, 151 insertions(+), 26 deletions(-) create mode 100644 test/regular_ball_test.cpp delete mode 100644 test/rotation_matrix.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 82519ea..1130a8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,8 @@ project(GameX) set(CMAKE_CXX_STANDARD 17) +find_package(absl CONFIG REQUIRED) + add_subdirectory(external/grassland) set(GAMEX_ASSETS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/assets) diff --git a/src/GameBall/CMakeLists.txt b/src/GameBall/CMakeLists.txt index 1a9b6c7..b3dd846 100644 --- a/src/GameBall/CMakeLists.txt +++ b/src/GameBall/CMakeLists.txt @@ -1,4 +1,11 @@ file(GLOB_RECURSE SOURCES *.cpp *.h) add_executable(GameBall ${SOURCES}) -target_link_libraries(GameBall PRIVATE GameX) +target_link_libraries(GameBall PRIVATE GameX absl::flags absl::flags_parse) + +# Delete main.cpp from sources +list(REMOVE_ITEM SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp) + +# Create a library for the tests +add_library(GameBallLib ${SOURCES}) +target_link_libraries(GameBallLib PRIVATE GameX) diff --git a/src/GameBall/core/game_ball.cpp b/src/GameBall/core/game_ball.cpp index 9be0ae2..a47b79e 100644 --- a/src/GameBall/core/game_ball.cpp +++ b/src/GameBall/core/game_ball.cpp @@ -45,10 +45,6 @@ void GameBall::OnInit() { glm::vec3{0.0f, -10.0f, 0.0f}, std::numeric_limits::infinity(), false, 20.0f); - primary_unit->SetMotion(glm::vec3{0.0f, 1.0f, 0.0f}, - glm::vec3{0.0f, 10.0f, 0.0f}, glm::mat3{1.0f}, - glm::vec3{0.0f, 0.0f, 1.0f}); - primary_player_id_ = primary_player->PlayerId(); primary_player->SetPrimaryUnit(primary_unit->UnitId()); @@ -103,7 +99,7 @@ void GameBall::OnUpdate() { if (primary_unit) { primary_player_primary_unit_object_id_ = primary_unit->ObjectId(); } - primary_player->SetPlayerInput(player_input); + primary_player->SetInput(player_input); } } diff --git a/src/GameBall/logic/player.cpp b/src/GameBall/logic/player.cpp index c4c558b..6668885 100644 --- a/src/GameBall/logic/player.cpp +++ b/src/GameBall/logic/player.cpp @@ -24,7 +24,7 @@ void Player::SetPrimaryUnit(uint64_t unit_id) { primary_unit_id_ = unit_id; } -void Player::SetPlayerInput(const PlayerInput &input) { +void Player::SetInput(const PlayerInput &input) { input_ = input; } diff --git a/src/GameBall/logic/player.h b/src/GameBall/logic/player.h index 155b685..ef33e2e 100644 --- a/src/GameBall/logic/player.h +++ b/src/GameBall/logic/player.h @@ -14,7 +14,7 @@ class Player { void SetPrimaryUnit(uint64_t unit_id); - void SetPlayerInput(const PlayerInput &input); + void SetInput(const PlayerInput &input); [[nodiscard]] PlayerInput GetPlayerInput() const; diff --git a/src/GameBall/logic/units/regular_ball.cpp b/src/GameBall/logic/units/regular_ball.cpp index 333a0b3..341c366 100644 --- a/src/GameBall/logic/units/regular_ball.cpp +++ b/src/GameBall/logic/units/regular_ball.cpp @@ -65,10 +65,10 @@ void RegularBall::UpdateTick() { moving_direction += right; } if (input.move_left) { - sphere.angular_velocity -= forward; + moving_direction -= forward; } if (input.move_right) { - sphere.angular_velocity += forward; + moving_direction += forward; } if (glm::length(moving_direction) > 0.0f) { @@ -127,4 +127,20 @@ void RegularBall::SetMotion(const glm::vec3 &position, augular_momentum_ = angular_momentum; } +glm::vec3 RegularBall::Position() const { + return position_; +} + +glm::vec3 RegularBall::Velocity() const { + return velocity_; +} + +glm::mat3 RegularBall::Orientation() const { + return orientation_; +} + +glm::vec3 RegularBall::AngularMomentum() const { + return augular_momentum_; +} + } // namespace GameBall::Logic::Units diff --git a/src/GameBall/logic/units/regular_ball.h b/src/GameBall/logic/units/regular_ball.h index 3653f9e..4aebf2b 100644 --- a/src/GameBall/logic/units/regular_ball.h +++ b/src/GameBall/logic/units/regular_ball.h @@ -26,6 +26,11 @@ class RegularBall : public Unit { const glm::mat3 &orientation = glm::mat3{1.0f}, const glm::vec3 &angular_momentum = glm::vec3{0.0f}); + glm::vec3 Position() const; + glm::vec3 Velocity() const; + glm::mat3 Orientation() const; + glm::vec3 AngularMomentum() const; + private: float radius_{1.0f}; float mass_{1.0f}; diff --git a/src/GameBall/logic/world.cpp b/src/GameBall/logic/world.cpp index 0e6f368..b1b9f84 100644 --- a/src/GameBall/logic/world.cpp +++ b/src/GameBall/logic/world.cpp @@ -75,7 +75,7 @@ void World::UnregisterPlayer(uint64_t player_id) { } void World::UpdateTick() { - LAND_INFO("Update Tick... {}", world_version_); + // LAND_INFO("Update Tick... {}", world_version_); physics_world_->ApplyGravity(TickDeltaT()); diff --git a/src/GameBall/logic/world.h b/src/GameBall/logic/world.h index 42baf0c..59dadf6 100644 --- a/src/GameBall/logic/world.h +++ b/src/GameBall/logic/world.h @@ -89,12 +89,12 @@ class World { return 1.0f / 64.0f; } + void UpdateTick(); + private: friend ::GameBall::GameBall; friend ::GameBall::Logic::Manager; - void UpdateTick(); - std::unique_ptr physics_world_; uint64_t next_object_id_{1}; std::map object_map_; diff --git a/src/GameBall/main.cpp b/src/GameBall/main.cpp index 7c4ae0e..4d4f217 100644 --- a/src/GameBall/main.cpp +++ b/src/GameBall/main.cpp @@ -1,7 +1,22 @@ #include "GameBall/core/game_ball.h" +#include "absl/flags/flag.h" +#include "absl/flags/parse.h" + +// Use abseil flags to parse command line arguments. + +ABSL_FLAG(bool, fullscreen, false, "Run in fullscreen mode."); + +// Width and Height +ABSL_FLAG(int, width, -1, "Width of the window."); +ABSL_FLAG(int, height, -1, "Height of the window."); + +int main(int argc, char *argv[]) { + absl::ParseCommandLine(argc, argv); -int main() { GameBall::GameSettings settings; + settings.fullscreen = absl::GetFlag(FLAGS_fullscreen); + settings.width = absl::GetFlag(FLAGS_width); + settings.height = absl::GetFlag(FLAGS_height); GameBall::GameBall game(settings); game.Run(); return 0; diff --git a/src/GameX/physics/world.cpp b/src/GameX/physics/world.cpp index 35eabc2..dd7209f 100644 --- a/src/GameX/physics/world.cpp +++ b/src/GameX/physics/world.cpp @@ -42,7 +42,6 @@ Cube &World::GetCube(uint64_t id) { } void World::SolveCollisions() { - LAND_INFO("Solve Collisions..."); std::vector> collision_pairs; for (auto &sphere1 : spheres_) { @@ -54,15 +53,12 @@ void World::SolveCollisions() { if (DetectCollision(sphere1.second, sphere2.second, collision)) { collision_pairs.emplace_back(&sphere1.second, &sphere2.second, collision); - LAND_INFO("Collision: sphere#{} sphere#{}", sphere1.first, - sphere2.first); } } for (auto &cube : cubes_) { Collision collision; if (DetectCollision(sphere1.second, cube.second, collision)) { collision_pairs.emplace_back(&sphere1.second, &cube.second, collision); - LAND_INFO("Collision: sphere#{} cube#{}", sphere1.first, cube.first); } } } @@ -85,7 +81,6 @@ void World::SolveCollisions() { } void World::ApplyGravity(float delta_time) { - LAND_INFO("Apply Gravity..."); for (auto &sphere : spheres_) { sphere.second.velocity += sphere.second.gravity * delta_time; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e06a5fa..9ec0f1d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,7 +5,7 @@ add_executable(GameXTest ${SOURCES}) enable_testing() find_package(GTest CONFIG REQUIRED) -target_link_libraries(GameXTest PRIVATE GTest::gtest GTest::gtest_main ${GAMEX_LIBS}) +target_link_libraries(GameXTest PRIVATE GTest::gtest GTest::gtest_main ${GAMEX_LIBS} GameBallLib) target_include_directories(GameXTest PRIVATE ${COMMON_INCLUDE_DIRS}) add_test(AllTestsInMain GameXTest) diff --git a/test/regular_ball_test.cpp b/test/regular_ball_test.cpp new file mode 100644 index 0000000..a444926 --- /dev/null +++ b/test/regular_ball_test.cpp @@ -0,0 +1,95 @@ +#include + +#include + +#include "GameBall/core/game_ball.h" +#include "GameBall/logic/obstacles/obstacles.h" +#include "GameBall/logic/units/units.h" + +void TestPlayerInput(GameBall::Logic::PlayerInput input, + glm::vec3 expected_position) { + GameBall::Logic::World world; + + uint64_t player_id{}; + uint64_t unit_id{}; + + { + auto player = world.CreatePlayer(); + EXPECT_NE(player, nullptr); + player_id = player->PlayerId(); + + auto unit = world.CreateUnit( + player->PlayerId(), glm::vec3{0.0f, 1.0f, 0.0f}, 1.0f, 1.0f); + unit_id = unit->UnitId(); + player->SetPrimaryUnit(unit->UnitId()); + + EXPECT_NE(unit, nullptr); + + auto obstacle = world.CreateObstacle( + glm::vec3{0.0f, -50.0f, 0.0f}, std::numeric_limits::infinity(), + false, 100.0f); + + EXPECT_NE(obstacle, nullptr); + } + + const auto max_tick = 500; + + for (int i = 0; i < max_tick; ++i) { + auto player = world.GetPlayer(player_id); + EXPECT_NE(player, nullptr); + player->SetInput(input); + world.UpdateTick(); + auto unit = world.GetUnit(unit_id); + EXPECT_NE(unit, nullptr); + auto regular_ball = + dynamic_cast(unit); + EXPECT_NE(regular_ball, nullptr); + + if (glm::length(regular_ball->Position() - expected_position) < 0.2f) { + SUCCEED(); + return; + } + } + + FAIL(); +} + +TEST(RegularBall, Functional) { + std::random_device rd; + std::mt19937 gen(rd()); + for (int i = 0; i < 100; i++) { + GameBall::Logic::PlayerInput input; + float yaw = std::uniform_real_distribution(0.0f, 360.0f)(gen); + glm::vec3 forward = glm::normalize(glm::vec3{ + glm::cos(glm::radians(yaw)), 0.0f, glm::sin(glm::radians(yaw))}); + glm::vec3 right = + glm::normalize(glm::cross(forward, glm::vec3{0.0f, 1.0f, 0.0f})); + input.orientation = forward; + input.move_forward = std::uniform_int_distribution(0, 1)(gen); + input.move_backward = std::uniform_int_distribution(0, 1)(gen); + input.move_left = std::uniform_int_distribution(0, 1)(gen); + input.move_right = std::uniform_int_distribution(0, 1)(gen); + + glm::vec2 combined = glm::vec2{0.0f}; + if (input.move_forward) { + combined += glm::vec2{0.0f, 1.0f}; + } + if (input.move_backward) { + combined += glm::vec2{0.0f, -1.0f}; + } + if (input.move_left) { + combined += glm::vec2{-1.0f, 0.0f}; + } + if (input.move_right) { + combined += glm::vec2{1.0f, 0.0f}; + } + glm::vec3 expected_position = glm::vec3{0.0f, 1.0f, 0.0f}; + if (glm::length(combined) > 0.0f) { + combined = glm::normalize(combined); + expected_position += + glm::vec3{combined.x * right + combined.y * forward} * 20.0f; + } + + TestPlayerInput(input, expected_position); + } +} diff --git a/test/rotation_matrix.cpp b/test/rotation_matrix.cpp deleted file mode 100644 index 07c5204..0000000 --- a/test/rotation_matrix.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "GameX/renderer/renderer.h" -#include "gtest/gtest.h" -#include "random" - -TEST(Camera, RotationMatrixTest) { -}