Updated game structure
Some checks failed
Build and Package Tetris / build-windows (push) Has been cancelled
Build and Package Tetris / build-linux (push) Has been cancelled

This commit is contained in:
2025-08-16 12:10:19 +02:00
parent 71648fbaeb
commit 2afaea7fd3
36 changed files with 665 additions and 382 deletions

82
tests/GravityTests.cpp Normal file
View File

@ -0,0 +1,82 @@
#include <catch2/catch_test_macros.hpp>
#include <catch2/catch_approx.hpp>
#include <iostream>
#include "core/GravityManager.h"
TEST_CASE("GravityManager basic ms calculation", "[gravity]") {
GravityManager g;
g.setGlobalMultiplier(1.0);
double ms0 = g.getMsForLevel(0);
REQUIRE(ms0 > 0);
double ms29 = g.getMsForLevel(29);
REQUIRE(ms29 >= 1.0);
}
// Additional tests
TEST_CASE("frames_to_ms_exact", "[gravity][exact]") {
// Reuse the reference constants (must match GravityManager implementation)
constexpr double NES_FPS = 60.0988;
constexpr double FRAME_MS = 1000.0 / NES_FPS;
constexpr int FRAMES_TABLE[30] = {
48, 43, 38, 33, 28, 23, 18, 13, 8, 6,
5, 5, 5, 4, 4, 4, 3, 3, 3, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 1
};
GravityManager g;
g.setGlobalMultiplier(1.0);
for (int lvl = 0; lvl <= 29; ++lvl) {
double expected = static_cast<double>(FRAMES_TABLE[lvl]) * FRAME_MS * 1.0;
double actual = g.getMsForLevel(lvl);
// GravityManager clamps to minimum 1.0ms; expected for these levels is >> 1.0 except possibly level 29
if (expected < 1.0) expected = 1.0;
if (!(actual == Catch::Approx(expected).epsilon(1e-6))) {
std::cerr << "DEBUG: lvl=" << lvl << ", levelMultiplier=" << g.getLevelMultiplier(lvl)
<< ", FRAMES_TABLE[lvl]=" << FRAMES_TABLE[lvl]
<< ", actual=" << actual << ", expected=" << expected << std::endl;
}
REQUIRE(actual == Catch::Approx(expected).epsilon(1e-6));
REQUIRE(g.getFpsForLevel(lvl) == Catch::Approx(1000.0 / actual).epsilon(1e-6));
}
}
TEST_CASE("multiplier_effects", "[gravity][multiplier]") {
GravityManager g;
g.setGlobalMultiplier(1.0);
double base = g.getMsForLevel(5); // level 5 baseline
g.setLevelMultiplier(5, 2.0);
double doubled = g.getMsForLevel(5);
REQUIRE(doubled == Catch::Approx(base * 2.0).epsilon(1e-6));
// global multiplier scales all levels
g.setGlobalMultiplier(0.5);
double afterGlobal = g.getMsForLevel(5);
REQUIRE(afterGlobal == Catch::Approx(doubled * 0.5).epsilon(1e-6));
}
TEST_CASE("clamping_and_edges", "[gravity][clamp]") {
GravityManager g;
// global multiplier clamped to [0.01,100.0]
g.setGlobalMultiplier(0.0001);
REQUIRE(g.getGlobalMultiplier() == Catch::Approx(0.01).epsilon(1e-12));
g.setGlobalMultiplier(500.0);
REQUIRE(g.getGlobalMultiplier() == Catch::Approx(100.0).epsilon(1e-12));
// per-level multiplier clamps
g.setLevelMultiplier(100, 200.0);
REQUIRE(g.getLevelMultiplier(100) == Catch::Approx(100.0).epsilon(1e-12));
// negative level queries map to level 0
REQUIRE(g.getLevelMultiplier(-5) == Catch::Approx(g.getLevelMultiplier(0)).epsilon(1e-12));
}
TEST_CASE("min_ms_enforced", "[gravity][min]") {
GravityManager g;
// Force very small multipliers then ensure minimum 1.0ms enforced
g.setLevelMultiplier(29, 0.01);
g.setGlobalMultiplier(0.01);
double ms29 = g.getMsForLevel(29);
REQUIRE(ms29 >= 1.0);
REQUIRE(ms29 == Catch::Approx(1.0).epsilon(1e-12));
}