smooth scroll added
This commit is contained in:
BIN
FreeSans.ttf
BIN
FreeSans.ttf
Binary file not shown.
@ -5,7 +5,7 @@
|
|||||||
Fullscreen=1
|
Fullscreen=1
|
||||||
|
|
||||||
[Audio]
|
[Audio]
|
||||||
Music=1
|
Music=0
|
||||||
Sound=1
|
Sound=1
|
||||||
|
|
||||||
[Player]
|
[Player]
|
||||||
|
|||||||
@ -103,6 +103,24 @@ void Game::setPaused(bool p) {
|
|||||||
paused = 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() {
|
void Game::refillBag() {
|
||||||
bag.clear();
|
bag.clear();
|
||||||
for (int i=0;i<PIECE_COUNT;++i) bag.push_back(static_cast<PieceType>(i));
|
for (int i=0;i<PIECE_COUNT;++i) bag.push_back(static_cast<PieceType>(i));
|
||||||
|
|||||||
@ -28,7 +28,7 @@ public:
|
|||||||
void tickGravity(double frameMs); // advance gravity accumulator & drop
|
void tickGravity(double frameMs); // advance gravity accumulator & drop
|
||||||
void softDropBoost(double frameMs); // accelerate fall while held
|
void softDropBoost(double frameMs); // accelerate fall while held
|
||||||
void hardDrop(); // instant drop & lock
|
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 move(int dx); // horizontal move
|
||||||
void rotate(int dir); // +1 cw, -1 ccw (simple wall-kick)
|
void rotate(int dir); // +1 cw, -1 ccw (simple wall-kick)
|
||||||
void holdCurrent(); // swap with hold (once per spawn)
|
void holdCurrent(); // swap with hold (once per spawn)
|
||||||
|
|||||||
@ -47,14 +47,14 @@ void GameRenderer::drawBlockTexture(SDL_Renderer* renderer, SDL_Texture* blocksT
|
|||||||
SDL_RenderTexture(renderer, blocksTex, &srcRect, &dstRect);
|
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;
|
if (piece.type >= PIECE_COUNT) return;
|
||||||
|
|
||||||
for (int cy = 0; cy < 4; ++cy) {
|
for (int cy = 0; cy < 4; ++cy) {
|
||||||
for (int cx = 0; cx < 4; ++cx) {
|
for (int cx = 0; cx < 4; ++cx) {
|
||||||
if (Game::cellFilled(piece, cx, cy)) {
|
if (Game::cellFilled(piece, cx, cy)) {
|
||||||
float px = ox + (piece.x + cx) * tileSize;
|
float px = ox + (piece.x + cx) * tileSize;
|
||||||
float py = oy + (piece.y + cy) * tileSize;
|
float py = oy + (piece.y + cy) * tileSize + pixelOffsetY;
|
||||||
|
|
||||||
if (isGhost) {
|
if (isGhost) {
|
||||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
|
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
|
||||||
@ -239,6 +239,59 @@ void GameRenderer::renderPlayingState(
|
|||||||
|
|
||||||
bool allowActivePieceRender = true;
|
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<float>(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)
|
// Draw ghost piece (where current piece will land)
|
||||||
if (allowActivePieceRender) {
|
if (allowActivePieceRender) {
|
||||||
Game::Piece ghostPiece = game->current();
|
Game::Piece ghostPiece = game->current();
|
||||||
@ -274,7 +327,7 @@ void GameRenderer::renderPlayingState(
|
|||||||
|
|
||||||
// Draw the falling piece
|
// Draw the falling piece
|
||||||
if (allowActivePieceRender) {
|
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
|
// Draw line clearing effects
|
||||||
|
|||||||
@ -50,7 +50,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
// Helper functions for drawing game elements
|
// 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 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);
|
static void drawSmallPiece(SDL_Renderer* renderer, SDL_Texture* blocksTex, PieceType pieceType, float x, float y, float tileSize);
|
||||||
|
|
||||||
// Helper function for drawing rectangles
|
// Helper function for drawing rectangles
|
||||||
|
|||||||
Reference in New Issue
Block a user