smooth scroll left / right
This commit is contained in:
@ -5,6 +5,7 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
@ -21,6 +22,14 @@ struct ImpactSpark {
|
||||
float size = 0.0f;
|
||||
SDL_Color color{255, 255, 255, 255};
|
||||
};
|
||||
|
||||
struct ActivePieceSmoothState {
|
||||
uint64_t sequence = 0;
|
||||
float visualX = 0.0f;
|
||||
bool initialized = false;
|
||||
};
|
||||
|
||||
ActivePieceSmoothState s_activePieceSmooth;
|
||||
}
|
||||
|
||||
// Color constants (copied from main.cpp)
|
||||
@ -62,13 +71,13 @@ 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, float pixelOffsetY) {
|
||||
void GameRenderer::drawPiece(SDL_Renderer* renderer, SDL_Texture* blocksTex, const Game::Piece& piece, float ox, float oy, float tileSize, bool isGhost, float pixelOffsetX, 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 px = ox + (piece.x + cx) * tileSize + pixelOffsetX;
|
||||
float py = oy + (piece.y + cy) * tileSize + pixelOffsetY;
|
||||
|
||||
if (isGhost) {
|
||||
@ -380,6 +389,28 @@ void GameRenderer::renderPlayingState(
|
||||
bool allowActivePieceRender = true;
|
||||
const bool smoothScrollEnabled = Settings::instance().isSmoothScrollEnabled();
|
||||
|
||||
float activePiecePixelOffsetX = 0.0f;
|
||||
if (allowActivePieceRender) {
|
||||
if (smoothScrollEnabled && !game->isPaused()) {
|
||||
const uint64_t pieceSeq = game->getCurrentPieceSequence();
|
||||
if (!s_activePieceSmooth.initialized || s_activePieceSmooth.sequence != pieceSeq) {
|
||||
s_activePieceSmooth.sequence = pieceSeq;
|
||||
s_activePieceSmooth.visualX = static_cast<float>(game->current().x);
|
||||
s_activePieceSmooth.initialized = true;
|
||||
}
|
||||
|
||||
const float targetX = static_cast<float>(game->current().x);
|
||||
constexpr float HORIZONTAL_SMOOTH_MS = 55.0f;
|
||||
const float lerpFactor = std::clamp(sparkDeltaMs / HORIZONTAL_SMOOTH_MS, 0.0f, 1.0f);
|
||||
s_activePieceSmooth.visualX = std::lerp(s_activePieceSmooth.visualX, targetX, lerpFactor);
|
||||
activePiecePixelOffsetX = (s_activePieceSmooth.visualX - targetX) * finalBlockSize;
|
||||
} else {
|
||||
s_activePieceSmooth.sequence = game->getCurrentPieceSequence();
|
||||
s_activePieceSmooth.visualX = static_cast<float>(game->current().x);
|
||||
s_activePieceSmooth.initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
auto computeFallOffset = [&]() -> float {
|
||||
if (game->isPaused()) {
|
||||
return 0.0f;
|
||||
@ -398,8 +429,8 @@ void GameRenderer::renderPlayingState(
|
||||
return progress * finalBlockSize;
|
||||
};
|
||||
|
||||
float activePieceOffset = (!game->isPaused() && smoothScrollEnabled) ? computeFallOffset() : 0.0f;
|
||||
if (activePieceOffset > 0.0f) {
|
||||
float activePiecePixelOffsetY = (!game->isPaused() && smoothScrollEnabled) ? computeFallOffset() : 0.0f;
|
||||
if (activePiecePixelOffsetY > 0.0f) {
|
||||
const auto& boardRef = game->boardRef();
|
||||
const Game::Piece& piece = game->current();
|
||||
float maxAllowed = finalBlockSize;
|
||||
@ -430,7 +461,7 @@ void GameRenderer::renderPlayingState(
|
||||
maxAllowed = std::min(maxAllowed, cellLimit);
|
||||
}
|
||||
}
|
||||
activePieceOffset = std::min(activePieceOffset, maxAllowed);
|
||||
activePiecePixelOffsetY = std::min(activePiecePixelOffsetY, maxAllowed);
|
||||
}
|
||||
|
||||
// Draw ghost piece (where current piece will land)
|
||||
@ -468,7 +499,7 @@ void GameRenderer::renderPlayingState(
|
||||
|
||||
// Draw the falling piece
|
||||
if (allowActivePieceRender) {
|
||||
drawPiece(renderer, blocksTex, game->current(), gridX, gridY, finalBlockSize, false, activePieceOffset);
|
||||
drawPiece(renderer, blocksTex, game->current(), gridX, gridY, finalBlockSize, false, activePiecePixelOffsetX, activePiecePixelOffsetY);
|
||||
}
|
||||
|
||||
// Draw line clearing effects
|
||||
|
||||
@ -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, float pixelOffsetY = 0.0f);
|
||||
static void drawPiece(SDL_Renderer* renderer, SDL_Texture* blocksTex, const Game::Piece& piece, float ox, float oy, float tileSize, bool isGhost = false, float pixelOffsetX = 0.0f, 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
|
||||
|
||||
Reference in New Issue
Block a user