Line drop by pixel

This commit is contained in:
2025-11-30 08:17:34 +01:00
parent 332e2efb74
commit 8279ccbe6d
3 changed files with 49 additions and 2 deletions

View File

@ -194,9 +194,28 @@ void LineEffect::startLineClear(const std::vector<int>& rows, int gridX, int gri
clearingRows = rows;
state = AnimationState::FLASH_WHITE;
timer = 0.0f;
dropProgress = 0.0f;
dropBlockSize = blockSize;
rowDropTargets.fill(0.0f);
particles.clear();
sparks.clear();
glowPulses.clear();
std::array<bool, Game::ROWS> rowClearing{};
for (int row : rows) {
if (row >= 0 && row < Game::ROWS) {
rowClearing[row] = true;
}
}
int clearedBelow = 0;
for (int row = Game::ROWS - 1; row >= 0; --row) {
if (rowClearing[row]) {
++clearedBelow;
} else if (clearedBelow > 0) {
rowDropTargets[row] = static_cast<float>(clearedBelow * blockSize);
}
}
// Create particles for each clearing row
for (int row : rows) {
@ -267,12 +286,16 @@ bool LineEffect::update(float deltaTime) {
updateParticles(deltaTime);
updateSparks(deltaTime);
updateGlowPulses(deltaTime);
dropProgress = std::min(1.0f, timer / DROP_DURATION);
if (timer >= DROP_DURATION) {
state = AnimationState::IDLE;
clearingRows.clear();
particles.clear();
sparks.clear();
glowPulses.clear();
rowDropTargets.fill(0.0f);
dropProgress = 0.0f;
dropBlockSize = 0;
return true; // Effect complete
}
break;
@ -335,6 +358,21 @@ void LineEffect::render(SDL_Renderer* renderer, SDL_Texture* blocksTex, int grid
}
}
float LineEffect::getRowDropOffset(int row) const {
if (state != AnimationState::BLOCKS_DROP) {
return 0.0f;
}
if (row < 0 || row >= Game::ROWS) {
return 0.0f;
}
float target = rowDropTargets[row];
if (target <= 0.0f) {
return 0.0f;
}
float eased = dropProgress * dropProgress * dropProgress;
return target * eased;
}
void LineEffect::renderFlash(int gridX, int gridY, int blockSize) {
// Create a flashing white effect with varying opacity
float progress = timer / FLASH_DURATION;

View File

@ -3,6 +3,9 @@
#include <SDL3/SDL.h>
#include <vector>
#include <random>
#include <array>
#include "../core/Game.h"
class LineEffect {
public:
@ -71,6 +74,7 @@ public:
// Update and render the effect
bool update(float deltaTime); // Returns true if effect is complete
void render(SDL_Renderer* renderer, SDL_Texture* blocksTex, int gridX, int gridY, int blockSize);
float getRowDropOffset(int row) const;
// Audio
void playLineClearSound(int lineCount);
@ -95,7 +99,7 @@ private:
// Animation timing - Flash then immediate explosion effect
static constexpr float FLASH_DURATION = 0.18f; // Slightly longer flash for anticipation
static constexpr float EXPLODE_DURATION = 0.9f; // Extended fireworks time
static constexpr float DROP_DURATION = 0.20f; // Allow lingering sparks before collapse
static constexpr float DROP_DURATION = 0.35f; // Allow lingering sparks before collapse
void createParticles(int row, int gridX, int gridY, int blockSize);
void spawnShardBurst(float x, float y, SDL_Color tint);
@ -112,4 +116,8 @@ private:
bool loadAudioSample(const std::string& path, std::vector<int16_t>& sample);
void initAudio();
SDL_Color pickFireColor() const;
std::array<float, Game::ROWS> rowDropTargets{};
float dropProgress = 0.0f;
int dropBlockSize = 0;
};

View File

@ -226,11 +226,12 @@ void GameRenderer::renderPlayingState(
// Draw the game board
const auto &board = game->boardRef();
for (int y = 0; y < Game::ROWS; ++y) {
float dropOffset = (lineEffect ? lineEffect->getRowDropOffset(y) : 0.0f);
for (int x = 0; x < Game::COLS; ++x) {
int v = board[y * Game::COLS + x];
if (v > 0) {
float bx = gridX + x * finalBlockSize;
float by = gridY + y * finalBlockSize;
float by = gridY + y * finalBlockSize + dropOffset;
drawBlockTexture(renderer, blocksTex, bx, by, finalBlockSize, v - 1);
}
}