diff --git a/FreeSans.ttf b/FreeSans.ttf deleted file mode 100644 index 9db9585..0000000 Binary files a/FreeSans.ttf and /dev/null differ diff --git a/settings.ini b/settings.ini index ea793f9..9724bbf 100644 --- a/settings.ini +++ b/settings.ini @@ -5,7 +5,7 @@ Fullscreen=1 [Audio] -Music=1 +Music=0 Sound=1 [Player] diff --git a/src/gameplay/core/Game.cpp b/src/gameplay/core/Game.cpp index 9360ba9..2196648 100644 --- a/src/gameplay/core/Game.cpp +++ b/src/gameplay/core/Game.cpp @@ -103,6 +103,24 @@ void Game::setPaused(bool p) { paused = p; } +void Game::setSoftDropping(bool on) { + if (softDropping == on) { + return; + } + + double oldStep = softDropping ? (gravityMs / 5.0) : gravityMs; + softDropping = on; + double newStep = softDropping ? (gravityMs / 5.0) : gravityMs; + + if (oldStep <= 0.0 || newStep <= 0.0) { + return; + } + + double progress = fallAcc / oldStep; + progress = std::clamp(progress, 0.0, 1.0); + fallAcc = progress * newStep; +} + void Game::refillBag() { bag.clear(); for (int i=0;i(i)); diff --git a/src/gameplay/core/Game.h b/src/gameplay/core/Game.h index 07a8aeb..48de705 100644 --- a/src/gameplay/core/Game.h +++ b/src/gameplay/core/Game.h @@ -28,7 +28,7 @@ public: void tickGravity(double frameMs); // advance gravity accumulator & drop void softDropBoost(double frameMs); // accelerate fall while held void hardDrop(); // instant drop & lock - void setSoftDropping(bool on) { softDropping = on; } // mark if player holds Down + void setSoftDropping(bool on); // mark if player holds Down void move(int dx); // horizontal move void rotate(int dir); // +1 cw, -1 ccw (simple wall-kick) void holdCurrent(); // swap with hold (once per spawn) diff --git a/src/graphics/renderers/GameRenderer.cpp b/src/graphics/renderers/GameRenderer.cpp index 5cb8de6..50e67c8 100644 --- a/src/graphics/renderers/GameRenderer.cpp +++ b/src/graphics/renderers/GameRenderer.cpp @@ -47,14 +47,14 @@ void GameRenderer::drawBlockTexture(SDL_Renderer* renderer, SDL_Texture* blocksT SDL_RenderTexture(renderer, blocksTex, &srcRect, &dstRect); } -void GameRenderer::drawPiece(SDL_Renderer* renderer, SDL_Texture* blocksTex, const Game::Piece& piece, float ox, float oy, float tileSize, bool isGhost) { +void GameRenderer::drawPiece(SDL_Renderer* renderer, SDL_Texture* blocksTex, const Game::Piece& piece, float ox, float oy, float tileSize, bool isGhost, float pixelOffsetY) { if (piece.type >= PIECE_COUNT) return; for (int cy = 0; cy < 4; ++cy) { for (int cx = 0; cx < 4; ++cx) { if (Game::cellFilled(piece, cx, cy)) { float px = ox + (piece.x + cx) * tileSize; - float py = oy + (piece.y + cy) * tileSize; + float py = oy + (piece.y + cy) * tileSize + pixelOffsetY; if (isGhost) { SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); @@ -239,6 +239,59 @@ void GameRenderer::renderPlayingState( bool allowActivePieceRender = true; + auto computeFallOffset = [&]() -> float { + if (game->isPaused()) { + return 0.0f; + } + double gravityMs = game->getGravityMs(); + if (gravityMs <= 0.0) { + return 0.0f; + } + double effectiveMs = game->isSoftDropping() ? std::max(5.0, gravityMs / 5.0) : gravityMs; + double accumulator = std::clamp(game->getFallAccumulator(), 0.0, effectiveMs); + if (effectiveMs <= 0.0) { + return 0.0f; + } + float progress = static_cast(accumulator / effectiveMs); + progress = std::clamp(progress, 0.0f, 1.0f); + return progress * finalBlockSize; + }; + + float activePieceOffset = (!game->isPaused()) ? computeFallOffset() : 0.0f; + if (activePieceOffset > 0.0f) { + const auto& boardRef = game->boardRef(); + const Game::Piece& piece = game->current(); + float maxAllowed = finalBlockSize; + for (int cy = 0; cy < 4; ++cy) { + for (int cx = 0; cx < 4; ++cx) { + if (!Game::cellFilled(piece, cx, cy)) { + continue; + } + int gx = piece.x + cx; + int gy = piece.y + cy; + if (gx < 0 || gx >= Game::COLS) { + continue; + } + int testY = gy + 1; + int emptyRows = 0; + if (testY < 0) { + emptyRows -= testY; // number of rows until we reach row 0 + testY = 0; + } + while (testY >= 0 && testY < Game::ROWS) { + if (boardRef[testY * Game::COLS + gx] != 0) { + break; + } + ++emptyRows; + ++testY; + } + float cellLimit = (emptyRows > 0) ? finalBlockSize : 0.0f; + maxAllowed = std::min(maxAllowed, cellLimit); + } + } + activePieceOffset = std::min(activePieceOffset, maxAllowed); + } + // Draw ghost piece (where current piece will land) if (allowActivePieceRender) { Game::Piece ghostPiece = game->current(); @@ -274,7 +327,7 @@ void GameRenderer::renderPlayingState( // Draw the falling piece if (allowActivePieceRender) { - drawPiece(renderer, blocksTex, game->current(), gridX, gridY, finalBlockSize, false); + drawPiece(renderer, blocksTex, game->current(), gridX, gridY, finalBlockSize, false, activePieceOffset); } // Draw line clearing effects diff --git a/src/graphics/renderers/GameRenderer.h b/src/graphics/renderers/GameRenderer.h index cd24d19..77e55a2 100644 --- a/src/graphics/renderers/GameRenderer.h +++ b/src/graphics/renderers/GameRenderer.h @@ -50,7 +50,7 @@ public: private: // Helper functions for drawing game elements static void drawBlockTexture(SDL_Renderer* renderer, SDL_Texture* blocksTex, float x, float y, float size, int blockType); - static void drawPiece(SDL_Renderer* renderer, SDL_Texture* blocksTex, const Game::Piece& piece, float ox, float oy, float tileSize, bool isGhost = false); + static void drawPiece(SDL_Renderer* renderer, SDL_Texture* blocksTex, const Game::Piece& piece, float ox, float oy, float tileSize, bool isGhost = false, float pixelOffsetY = 0.0f); static void drawSmallPiece(SDL_Renderer* renderer, SDL_Texture* blocksTex, PieceType pieceType, float x, float y, float tileSize); // Helper function for drawing rectangles