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

View File

@ -0,0 +1,36 @@
#include "GravityManager.h"
#include <algorithm>
#include <iostream>
GravityManager::GravityManager() {
levelMultipliers.fill(1.0);
}
void GravityManager::setGlobalMultiplier(double m) {
globalMultiplier = std::clamp(m, 0.01, 100.0);
}
double GravityManager::getGlobalMultiplier() const { return globalMultiplier; }
void GravityManager::setLevelMultiplier(int level, double m) {
if (level < 0) return;
int idx = level >= 29 ? 29 : level;
levelMultipliers[idx] = std::clamp(m, 0.01, 100.0);
}
double GravityManager::getLevelMultiplier(int level) const {
int idx = level < 0 ? 0 : (level >= 29 ? 29 : level);
return levelMultipliers[idx];
}
double GravityManager::getMsForLevel(int level) const {
int idx = level < 0 ? 0 : (level >= 29 ? 29 : level);
double frames = static_cast<double>(FRAMES_TABLE[idx]) * levelMultipliers[idx];
double result = frames * FRAME_MS * globalMultiplier;
return std::max(1.0, result);
}
double GravityManager::getFpsForLevel(int level) const {
double ms = getMsForLevel(level);
return 1000.0 / ms;
}

31
src/core/GravityManager.h Normal file
View File

@ -0,0 +1,31 @@
#pragma once
#include <array>
class GravityManager {
public:
GravityManager();
// Global multiplier applied to all levels
void setGlobalMultiplier(double m);
double getGlobalMultiplier() const;
// Per-level multiplier (29 = 29+)
void setLevelMultiplier(int level, double m);
double getLevelMultiplier(int level) const;
// Compute ms per cell and fps for a given level
double getMsForLevel(int level) const;
double getFpsForLevel(int level) const;
private:
static constexpr double NES_FPS = 60.0988;
static constexpr double FRAME_MS = 1000.0 / NES_FPS;
static 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
};
double globalMultiplier{1.0};
std::array<double,30> levelMultipliers{}; // default 1.0
};

46
src/core/StateManager.cpp Normal file
View File

@ -0,0 +1,46 @@
#include "StateManager.h"
StateManager::StateManager(AppState initial)
: currentState(initial)
{
}
void StateManager::registerHandler(AppState s, EventHandler h) {
handlers[static_cast<int>(s)].push_back(std::move(h));
}
void StateManager::registerOnEnter(AppState s, Hook h) {
onEnter[static_cast<int>(s)].push_back(std::move(h));
}
void StateManager::registerOnExit(AppState s, Hook h) {
onExit[static_cast<int>(s)].push_back(std::move(h));
}
// Overload accepting a no-arg function as handler (wraps it into an EventHandler)
void StateManager::registerHandler(AppState s, std::function<void()> h) {
EventHandler wrapper = [h = std::move(h)](const SDL_Event&) { h(); };
registerHandler(s, std::move(wrapper));
}
void StateManager::setState(AppState s) {
if (s == currentState) return;
// call exit hooks for current
auto it = onExit.find(static_cast<int>(currentState));
if (it != onExit.end()) {
for (auto &h : it->second) h();
}
currentState = s;
auto it2 = onEnter.find(static_cast<int>(currentState));
if (it2 != onEnter.end()) {
for (auto &h : it2->second) h();
}
}
AppState StateManager::getState() const { return currentState; }
void StateManager::handleEvent(const SDL_Event& e) {
auto it = handlers.find(static_cast<int>(currentState));
if (it == handlers.end()) return;
for (auto &h : it->second) h(e);
}

41
src/core/StateManager.h Normal file
View File

@ -0,0 +1,41 @@
#pragma once
#include <functional>
#include <unordered_map>
#include <vector>
#include <SDL3/SDL.h>
// Application states used across the app
enum class AppState {
Loading,
Menu,
Playing,
LevelSelect,
GameOver
};
// State manager used by main to route events and lifecycle hooks
class StateManager {
public:
using EventHandler = std::function<void(const SDL_Event&)>;
using Hook = std::function<void()>;
StateManager(AppState initial);
void registerHandler(AppState s, EventHandler h);
void registerOnEnter(AppState s, Hook h);
void registerOnExit(AppState s, Hook h);
void registerHandler(AppState s, std::function<void()> h); // overload used in some places
void setState(AppState s);
AppState getState() const;
void handleEvent(const SDL_Event& e);
private:
AppState currentState;
std::unordered_map<int, std::vector<EventHandler>> handlers;
std::unordered_map<int, std::vector<Hook>> onEnter;
std::unordered_map<int, std::vector<Hook>> onExit;
};