feat: implement textured line clear effects and refine UI alignment
- **Visual Effects**: Upgraded line clear particles to use the game's block texture instead of simple circles, matching the reference web game's aesthetic. - **Particle Physics**: Tuned particle velocity, gravity, and fade rates for a more dynamic explosion effect. - **Rendering Integration**: Updated [main.cpp](cci:7://file:///d:/Sites/Work/tetris/src/main.cpp:0:0-0:0) and `GameRenderer` to pass the block texture to the effect system and correctly trigger animations upon line completion. - **Menu UI**: Fixed [MenuState](cci:1://file:///d:/Sites/Work/tetris/src/states/MenuState.cpp:19:0-19:55) layout calculations to use fixed logical dimensions (1200x1000), ensuring consistent centering and alignment of the logo, buttons, and settings icon across different window sizes. - **Code Cleanup**: Refactored `PlayingState` to delegate effect triggering to the rendering layer where correct screen coordinates are available.
This commit is contained in:
72
src/gameplay/effects/LineEffect.h
Normal file
72
src/gameplay/effects/LineEffect.h
Normal file
@ -0,0 +1,72 @@
|
||||
// LineEffect.h - Line clearing visual and audio effects
|
||||
#pragma once
|
||||
#include <SDL3/SDL.h>
|
||||
#include <vector>
|
||||
#include <random>
|
||||
|
||||
class LineEffect {
|
||||
public:
|
||||
struct Particle {
|
||||
float x, y;
|
||||
float vx, vy;
|
||||
float size;
|
||||
float alpha;
|
||||
int blockType; // Added for textured particles
|
||||
SDL_Color color;
|
||||
|
||||
Particle(float px, float py);
|
||||
void update();
|
||||
void render(SDL_Renderer* renderer, SDL_Texture* blocksTex);
|
||||
bool isAlive() const { return alpha > 0.0f; }
|
||||
};
|
||||
|
||||
enum class AnimationState {
|
||||
IDLE,
|
||||
FLASH_WHITE,
|
||||
EXPLODE_BLOCKS,
|
||||
BLOCKS_DROP
|
||||
};
|
||||
|
||||
LineEffect();
|
||||
~LineEffect();
|
||||
|
||||
bool init(SDL_Renderer* renderer);
|
||||
void shutdown();
|
||||
|
||||
// Start line clear effect for the specified rows
|
||||
void startLineClear(const std::vector<int>& rows, int gridX, int gridY, int blockSize);
|
||||
|
||||
// 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);
|
||||
|
||||
// Audio
|
||||
void playLineClearSound(int lineCount);
|
||||
|
||||
bool isActive() const { return state != AnimationState::IDLE; }
|
||||
|
||||
private:
|
||||
SDL_Renderer* renderer{nullptr};
|
||||
AnimationState state{AnimationState::IDLE};
|
||||
float timer{0.0f};
|
||||
std::vector<int> clearingRows;
|
||||
std::vector<Particle> particles;
|
||||
std::mt19937 rng{std::random_device{}()};
|
||||
|
||||
// Audio resources
|
||||
SDL_AudioStream* audioStream{nullptr};
|
||||
std::vector<int16_t> lineClearSample;
|
||||
std::vector<int16_t> tetrisSample;
|
||||
|
||||
// Animation timing - Flash then immediate explosion effect
|
||||
static constexpr float FLASH_DURATION = 0.12f; // Very brief white flash
|
||||
static constexpr float EXPLODE_DURATION = 0.15f; // Quick explosive effect
|
||||
static constexpr float DROP_DURATION = 0.05f; // Almost instant block drop
|
||||
|
||||
void createParticles(int row, int gridX, int gridY, int blockSize);
|
||||
void updateParticles();
|
||||
void renderFlash(int gridX, int gridY, int blockSize);
|
||||
void renderExplosion(SDL_Texture* blocksTex);
|
||||
bool loadAudioSample(const std::string& path, std::vector<int16_t>& sample);
|
||||
void initAudio();
|
||||
};
|
||||
Reference in New Issue
Block a user