Updated game structure
This commit is contained in:
36
src/core/GravityManager.cpp
Normal file
36
src/core/GravityManager.cpp
Normal 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
31
src/core/GravityManager.h
Normal 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
46
src/core/StateManager.cpp
Normal 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
41
src/core/StateManager.h
Normal 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;
|
||||
};
|
||||
Reference in New Issue
Block a user