I block rotation fix

This commit is contained in:
2025-12-07 10:45:12 +01:00
parent 59dc3a1638
commit 5a95c9180c

View File

@ -2,6 +2,7 @@
#include "Game.h" #include "Game.h"
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <limits>
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
// Piece rotation bitmasks (row-major 4x4). Bit 0 = (0,0). // Piece rotation bitmasks (row-major 4x4). Bit 0 = (0,0).
@ -400,8 +401,28 @@ void Game::rotate(int dir) {
// Try rotation at current position first // Try rotation at current position first
if (!collides(p)) { if (!collides(p)) {
cur = p; // If rotation at current position would place cells above the top,
return; // attempt to shift it down so the topmost block sits at gy == 0.
int minGy = std::numeric_limits<int>::max();
for (int cy = 0; cy < 4; ++cy) {
for (int cx = 0; cx < 4; ++cx) {
if (!cellFilled(p, cx, cy)) continue;
minGy = std::min(minGy, p.y + cy);
}
}
if (minGy < 0) {
Piece adj = p;
adj.y += -minGy;
if (!collides(adj)) {
cur = adj;
return;
}
// Can't shift into place without collision - fall through to kicks
} else {
cur = p;
return;
}
} }
// Standard SRS Wall Kicks // Standard SRS Wall Kicks
@ -457,8 +478,30 @@ void Game::rotate(int dir) {
test.x = cur.x + kick.first; test.x = cur.x + kick.first;
test.y = cur.y + kick.second; test.y = cur.y + kick.second;
if (!collides(test)) { if (!collides(test)) {
cur = test; // Prevent rotated piece from ending up above the visible playfield.
return; // If any cell of `test` is above the top (gy < 0), try shifting it
// downward so the highest block sits at row 0. Accept the shift
// only if it doesn't collide; otherwise keep searching kicks.
int minGy = std::numeric_limits<int>::max();
for (int cy = 0; cy < 4; ++cy) {
for (int cx = 0; cx < 4; ++cx) {
if (!cellFilled(test, cx, cy)) continue;
minGy = std::min(minGy, test.y + cy);
}
}
if (minGy < 0) {
Piece adj = test;
adj.y += -minGy; // shift down so topmost block is at gy == 0
if (!collides(adj)) {
cur = adj;
return;
}
// couldn't shift without collision, try next kick
} else {
cur = test;
return;
}
} }
} }
} }