Line drop by pixel
This commit is contained in:
@ -194,10 +194,29 @@ void LineEffect::startLineClear(const std::vector<int>& rows, int gridX, int gri
|
|||||||
clearingRows = rows;
|
clearingRows = rows;
|
||||||
state = AnimationState::FLASH_WHITE;
|
state = AnimationState::FLASH_WHITE;
|
||||||
timer = 0.0f;
|
timer = 0.0f;
|
||||||
|
dropProgress = 0.0f;
|
||||||
|
dropBlockSize = blockSize;
|
||||||
|
rowDropTargets.fill(0.0f);
|
||||||
particles.clear();
|
particles.clear();
|
||||||
sparks.clear();
|
sparks.clear();
|
||||||
glowPulses.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
|
// Create particles for each clearing row
|
||||||
for (int row : rows) {
|
for (int row : rows) {
|
||||||
createParticles(row, gridX, gridY, blockSize);
|
createParticles(row, gridX, gridY, blockSize);
|
||||||
@ -267,12 +286,16 @@ bool LineEffect::update(float deltaTime) {
|
|||||||
updateParticles(deltaTime);
|
updateParticles(deltaTime);
|
||||||
updateSparks(deltaTime);
|
updateSparks(deltaTime);
|
||||||
updateGlowPulses(deltaTime);
|
updateGlowPulses(deltaTime);
|
||||||
|
dropProgress = std::min(1.0f, timer / DROP_DURATION);
|
||||||
if (timer >= DROP_DURATION) {
|
if (timer >= DROP_DURATION) {
|
||||||
state = AnimationState::IDLE;
|
state = AnimationState::IDLE;
|
||||||
clearingRows.clear();
|
clearingRows.clear();
|
||||||
particles.clear();
|
particles.clear();
|
||||||
sparks.clear();
|
sparks.clear();
|
||||||
glowPulses.clear();
|
glowPulses.clear();
|
||||||
|
rowDropTargets.fill(0.0f);
|
||||||
|
dropProgress = 0.0f;
|
||||||
|
dropBlockSize = 0;
|
||||||
return true; // Effect complete
|
return true; // Effect complete
|
||||||
}
|
}
|
||||||
break;
|
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) {
|
void LineEffect::renderFlash(int gridX, int gridY, int blockSize) {
|
||||||
// Create a flashing white effect with varying opacity
|
// Create a flashing white effect with varying opacity
|
||||||
float progress = timer / FLASH_DURATION;
|
float progress = timer / FLASH_DURATION;
|
||||||
|
|||||||
@ -3,6 +3,9 @@
|
|||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
#include "../core/Game.h"
|
||||||
|
|
||||||
class LineEffect {
|
class LineEffect {
|
||||||
public:
|
public:
|
||||||
@ -71,6 +74,7 @@ public:
|
|||||||
// Update and render the effect
|
// Update and render the effect
|
||||||
bool update(float deltaTime); // Returns true if effect is complete
|
bool update(float deltaTime); // Returns true if effect is complete
|
||||||
void render(SDL_Renderer* renderer, SDL_Texture* blocksTex, int gridX, int gridY, int blockSize);
|
void render(SDL_Renderer* renderer, SDL_Texture* blocksTex, int gridX, int gridY, int blockSize);
|
||||||
|
float getRowDropOffset(int row) const;
|
||||||
|
|
||||||
// Audio
|
// Audio
|
||||||
void playLineClearSound(int lineCount);
|
void playLineClearSound(int lineCount);
|
||||||
@ -95,7 +99,7 @@ private:
|
|||||||
// Animation timing - Flash then immediate explosion effect
|
// Animation timing - Flash then immediate explosion effect
|
||||||
static constexpr float FLASH_DURATION = 0.18f; // Slightly longer flash for anticipation
|
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 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 createParticles(int row, int gridX, int gridY, int blockSize);
|
||||||
void spawnShardBurst(float x, float y, SDL_Color tint);
|
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);
|
bool loadAudioSample(const std::string& path, std::vector<int16_t>& sample);
|
||||||
void initAudio();
|
void initAudio();
|
||||||
SDL_Color pickFireColor() const;
|
SDL_Color pickFireColor() const;
|
||||||
|
|
||||||
|
std::array<float, Game::ROWS> rowDropTargets{};
|
||||||
|
float dropProgress = 0.0f;
|
||||||
|
int dropBlockSize = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -226,11 +226,12 @@ void GameRenderer::renderPlayingState(
|
|||||||
// Draw the game board
|
// Draw the game board
|
||||||
const auto &board = game->boardRef();
|
const auto &board = game->boardRef();
|
||||||
for (int y = 0; y < Game::ROWS; ++y) {
|
for (int y = 0; y < Game::ROWS; ++y) {
|
||||||
|
float dropOffset = (lineEffect ? lineEffect->getRowDropOffset(y) : 0.0f);
|
||||||
for (int x = 0; x < Game::COLS; ++x) {
|
for (int x = 0; x < Game::COLS; ++x) {
|
||||||
int v = board[y * Game::COLS + x];
|
int v = board[y * Game::COLS + x];
|
||||||
if (v > 0) {
|
if (v > 0) {
|
||||||
float bx = gridX + x * finalBlockSize;
|
float bx = gridX + x * finalBlockSize;
|
||||||
float by = gridY + y * finalBlockSize;
|
float by = gridY + y * finalBlockSize + dropOffset;
|
||||||
drawBlockTexture(renderer, blocksTex, bx, by, finalBlockSize, v - 1);
|
drawBlockTexture(renderer, blocksTex, bx, by, finalBlockSize, v - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user