fixed timer functions
This commit is contained in:
@ -30,6 +30,9 @@ namespace Config {
|
||||
constexpr double ARR_RATE = 40.0; // Auto Repeat Rate in ms
|
||||
constexpr float LEVEL_FADE_DURATION = 3500.0f; // Level background fade time in ms
|
||||
constexpr int MAX_LEVELS = 20; // Maximum selectable starting level
|
||||
|
||||
// Gravity speed multiplier: 1.0 = normal, 2.0 = 2x slower, 0.5 = 2x faster
|
||||
constexpr double GRAVITY_SPEED_MULTIPLIER = 1;
|
||||
}
|
||||
|
||||
// UI Layout constants
|
||||
|
||||
@ -512,6 +512,11 @@ bool ApplicationManager::initializeGame() {
|
||||
m_game = std::make_unique<Game>(m_startLevelSelection);
|
||||
// Wire up sound callbacks as main.cpp did
|
||||
if (m_game) {
|
||||
// Apply global gravity speed multiplier from config
|
||||
m_game->setGravityGlobalMultiplier(Config::Gameplay::GRAVITY_SPEED_MULTIPLIER);
|
||||
// Reset to recalculate gravity with the new multiplier
|
||||
m_game->reset(m_startLevelSelection);
|
||||
|
||||
m_game->setSoundCallback([&](int linesCleared){
|
||||
SoundEffectManager::instance().playSound("clear_line", 1.0f);
|
||||
// voice lines handled via asset manager loaded sounds
|
||||
|
||||
@ -56,11 +56,53 @@ void Game::reset(int startLevel_) {
|
||||
_score = 0; _lines = 0; _level = startLevel_; startLevel = startLevel_;
|
||||
// Initialize gravity using NES timing table (ms per cell by level)
|
||||
gravityMs = gravityMsForLevel(_level, gravityGlobalMultiplier);
|
||||
fallAcc = 0; _elapsedSec = 0; gameOver=false; paused=false;
|
||||
fallAcc = 0; gameOver=false; paused=false;
|
||||
_startTime = SDL_GetPerformanceCounter();
|
||||
_pausedTime = 0;
|
||||
_lastPauseStart = 0;
|
||||
hold = Piece{}; hold.type = PIECE_COUNT; canHold=true;
|
||||
refillBag(); spawn();
|
||||
}
|
||||
|
||||
double Game::elapsed() const {
|
||||
if (!_startTime) return 0.0;
|
||||
|
||||
Uint64 currentTime = SDL_GetPerformanceCounter();
|
||||
Uint64 totalPausedTime = _pausedTime;
|
||||
|
||||
// If currently paused, add time since pause started
|
||||
if (paused && _lastPauseStart > 0) {
|
||||
totalPausedTime += (currentTime - _lastPauseStart);
|
||||
}
|
||||
|
||||
Uint64 activeTime = currentTime - _startTime - totalPausedTime;
|
||||
double seconds = (double)activeTime / (double)SDL_GetPerformanceFrequency();
|
||||
return seconds;
|
||||
}
|
||||
|
||||
void Game::updateElapsedTime() {
|
||||
// This method is now just for API compatibility
|
||||
// Actual elapsed time is calculated on-demand in elapsed()
|
||||
}
|
||||
|
||||
void Game::setPaused(bool p) {
|
||||
if (p == paused) return; // No change
|
||||
|
||||
if (p) {
|
||||
// Pausing - record when pause started
|
||||
_lastPauseStart = SDL_GetPerformanceCounter();
|
||||
} else {
|
||||
// Unpausing - add elapsed pause time to total
|
||||
if (_lastPauseStart > 0) {
|
||||
Uint64 currentTime = SDL_GetPerformanceCounter();
|
||||
_pausedTime += (currentTime - _lastPauseStart);
|
||||
_lastPauseStart = 0;
|
||||
}
|
||||
}
|
||||
|
||||
paused = p;
|
||||
}
|
||||
|
||||
void Game::refillBag() {
|
||||
bag.clear();
|
||||
for (int i=0;i<PIECE_COUNT;++i) bag.push_back(static_cast<PieceType>(i));
|
||||
@ -241,13 +283,15 @@ bool Game::tryMoveDown() {
|
||||
void Game::tickGravity(double frameMs) {
|
||||
if (paused) return; // Don't tick gravity when paused
|
||||
|
||||
// Soft drop: 20x faster for rapid continuous dropping
|
||||
double effectiveGravityMs = softDropping ? (gravityMs / 5.0) : gravityMs;
|
||||
|
||||
fallAcc += frameMs;
|
||||
|
||||
while (fallAcc >= gravityMs) {
|
||||
while (fallAcc >= effectiveGravityMs) {
|
||||
// Attempt to move down by one row
|
||||
if (tryMoveDown()) {
|
||||
// Award soft drop points only if player is actively holding Down
|
||||
// JS: POINTS.SOFT_DROP = 1 per cell for soft drop
|
||||
if (softDropping) {
|
||||
_score += 1;
|
||||
}
|
||||
@ -256,13 +300,14 @@ void Game::tickGravity(double frameMs) {
|
||||
lockPiece();
|
||||
if (gameOver) break;
|
||||
}
|
||||
fallAcc -= gravityMs;
|
||||
fallAcc -= effectiveGravityMs;
|
||||
}
|
||||
}
|
||||
|
||||
void Game::softDropBoost(double frameMs) {
|
||||
// Reduce soft drop speed multiplier from 10.0 to 3.0 to make it less aggressive
|
||||
if (!paused) fallAcc += frameMs * 3.0;
|
||||
// This method is now deprecated - soft drop is handled in tickGravity
|
||||
// Kept for API compatibility but does nothing
|
||||
(void)frameMs;
|
||||
}
|
||||
|
||||
void Game::hardDrop() {
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <SDL3/SDL.h>
|
||||
#include "../../core/GravityManager.h"
|
||||
|
||||
enum PieceType { I, O, T, S, Z, J, L, PIECE_COUNT };
|
||||
@ -40,13 +41,14 @@ public:
|
||||
bool canHoldPiece() const { return canHold; }
|
||||
bool isGameOver() const { return gameOver; }
|
||||
bool isPaused() const { return paused; }
|
||||
void setPaused(bool p) { paused = p; }
|
||||
void setPaused(bool p);
|
||||
int score() const { return _score; }
|
||||
int lines() const { return _lines; }
|
||||
int level() const { return _level; }
|
||||
int startLevelBase() const { return startLevel; }
|
||||
double elapsed() const { return _elapsedSec; }
|
||||
void addElapsed(double frameMs) { if (!paused) _elapsedSec += frameMs/1000.0; }
|
||||
double elapsed() const; // Now calculated from start time
|
||||
void updateElapsedTime(); // Update elapsed time from system clock
|
||||
bool isSoftDropping() const { return softDropping; }
|
||||
|
||||
// Block statistics
|
||||
const std::array<int, PIECE_COUNT>& getBlockCounts() const { return blockCounts; }
|
||||
@ -69,6 +71,7 @@ public:
|
||||
void setGravityGlobalMultiplier(double m) { gravityGlobalMultiplier = m; }
|
||||
double getGravityGlobalMultiplier() const;
|
||||
double getGravityMs() const;
|
||||
double getFallAccumulator() const { return fallAcc; } // Debug: time accumulated toward next drop
|
||||
void setLevelGravityMultiplier(int level, double m);
|
||||
|
||||
private:
|
||||
@ -85,7 +88,9 @@ private:
|
||||
int _level{1};
|
||||
double gravityMs{800.0};
|
||||
double fallAcc{0.0};
|
||||
double _elapsedSec{0.0};
|
||||
Uint64 _startTime{0}; // Performance counter at game start
|
||||
Uint64 _pausedTime{0}; // Time spent paused (in performance counter ticks)
|
||||
Uint64 _lastPauseStart{0}; // When the current pause started
|
||||
bool gameOver{false};
|
||||
int startLevel{0};
|
||||
bool softDropping{false}; // true while player holds Down key
|
||||
|
||||
@ -412,6 +412,25 @@ void GameRenderer::renderPlayingState(
|
||||
snprintf(timeStr, sizeof(timeStr), "%02d:%02d", mins, secs);
|
||||
pixelFont->draw(renderer, scoreX, baseY + 290, timeStr, 0.9f, {255, 255, 255, 255});
|
||||
|
||||
// Debug: Gravity timing info
|
||||
pixelFont->draw(renderer, scoreX, baseY + 330, "GRAVITY", 0.8f, {150, 150, 150, 255});
|
||||
double gravityMs = game->getGravityMs();
|
||||
double fallAcc = game->getFallAccumulator();
|
||||
|
||||
// Calculate effective gravity (accounting for soft drop)
|
||||
bool isSoftDrop = game->isSoftDropping();
|
||||
double effectiveGravityMs = isSoftDrop ? (gravityMs / 2.0) : gravityMs;
|
||||
double timeUntilDrop = std::max(0.0, effectiveGravityMs - fallAcc);
|
||||
|
||||
char gravityStr[32];
|
||||
snprintf(gravityStr, sizeof(gravityStr), "%.0f ms%s", gravityMs, isSoftDrop ? " (SD)" : "");
|
||||
pixelFont->draw(renderer, scoreX, baseY + 350, gravityStr, 0.7f, {180, 180, 180, 255});
|
||||
|
||||
char dropStr[32];
|
||||
snprintf(dropStr, sizeof(dropStr), "Drop: %.0f", timeUntilDrop);
|
||||
SDL_Color dropColor = isSoftDrop ? SDL_Color{255, 200, 100, 255} : SDL_Color{100, 255, 100, 255};
|
||||
pixelFont->draw(renderer, scoreX, baseY + 370, dropStr, 0.7f, dropColor);
|
||||
|
||||
// Gravity HUD
|
||||
char gms[64];
|
||||
double gms_val = game->getGravityMs();
|
||||
|
||||
15
src/main.cpp
15
src/main.cpp
@ -33,6 +33,7 @@
|
||||
#include "audio/MenuWrappers.h"
|
||||
#include "utils/ImagePathResolver.h"
|
||||
#include "graphics/renderers/GameRenderer.h"
|
||||
#include "core/Config.h"
|
||||
|
||||
// Debug logging removed: no-op in this build (previously LOG_DEBUG)
|
||||
|
||||
@ -629,6 +630,9 @@ int main(int, char **)
|
||||
}
|
||||
|
||||
Game game(startLevelSelection);
|
||||
// Apply global gravity speed multiplier from config
|
||||
game.setGravityGlobalMultiplier(Config::Gameplay::GRAVITY_SPEED_MULTIPLIER);
|
||||
game.reset(startLevelSelection);
|
||||
|
||||
// Initialize sound effects system
|
||||
SoundEffectManager::instance().init();
|
||||
@ -713,7 +717,7 @@ int main(int, char **)
|
||||
const double DAS = 170.0, ARR = 40.0;
|
||||
SDL_Rect logicalVP{0, 0, LOGICAL_W, LOGICAL_H};
|
||||
float logicalScale = 1.f;
|
||||
Uint64 lastMs = SDL_GetTicks();
|
||||
Uint64 lastMs = SDL_GetPerformanceCounter();
|
||||
bool musicStarted = false;
|
||||
bool musicLoaded = false;
|
||||
int currentTrackLoading = 0;
|
||||
@ -1084,9 +1088,12 @@ int main(int, char **)
|
||||
}
|
||||
|
||||
// --- Timing ---
|
||||
Uint64 now = SDL_GetTicks();
|
||||
double frameMs = double(now - lastMs);
|
||||
Uint64 now = SDL_GetPerformanceCounter();
|
||||
double frameMs = double(now - lastMs) * 1000.0 / double(SDL_GetPerformanceFrequency());
|
||||
lastMs = now;
|
||||
|
||||
// Cap frame time to avoid spiral of death (max 100ms)
|
||||
if (frameMs > 100.0) frameMs = 100.0;
|
||||
const bool *ks = SDL_GetKeyboardState(nullptr);
|
||||
bool left = state == AppState::Playing && ks[SDL_SCANCODE_LEFT];
|
||||
bool right = state == AppState::Playing && ks[SDL_SCANCODE_RIGHT];
|
||||
@ -1132,7 +1139,7 @@ int main(int, char **)
|
||||
{
|
||||
if (!game.isPaused()) {
|
||||
game.tickGravity(frameMs);
|
||||
game.addElapsed(frameMs);
|
||||
game.updateElapsedTime();
|
||||
|
||||
// Update line effect and clear lines when animation completes
|
||||
if (lineEffect.isActive()) {
|
||||
|
||||
@ -128,16 +128,10 @@ void PlayingState::handleEvent(const SDL_Event& e) {
|
||||
void PlayingState::update(double frameMs) {
|
||||
if (!ctx.game) return;
|
||||
|
||||
static bool debugPrinted = false;
|
||||
if (!debugPrinted) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "[PLAYING] Starting updates, frameMs=%.2f, paused=%d", frameMs, ctx.game->isPaused());
|
||||
debugPrinted = true;
|
||||
}
|
||||
|
||||
// forward per-frame gameplay updates (gravity, elapsed)
|
||||
// forward per-frame gameplay updates (gravity, line effects)
|
||||
if (!ctx.game->isPaused()) {
|
||||
ctx.game->tickGravity(frameMs);
|
||||
ctx.game->addElapsed(frameMs);
|
||||
ctx.game->updateElapsedTime();
|
||||
|
||||
if (ctx.lineEffect && ctx.lineEffect->isActive()) {
|
||||
if (ctx.lineEffect->update(frameMs / 1000.0f)) {
|
||||
|
||||
Reference in New Issue
Block a user