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:
116
src/gameplay/core/Game.h
Normal file
116
src/gameplay/core/Game.h
Normal file
@ -0,0 +1,116 @@
|
||||
|
||||
// Game.h - Core Tetris game logic (board, piece mechanics, scoring events only)
|
||||
#pragma once
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <random>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include "../../core/GravityManager.h"
|
||||
|
||||
enum PieceType { I, O, T, S, Z, J, L, PIECE_COUNT };
|
||||
using Shape = std::array<uint16_t, 4>; // four rotation bitmasks
|
||||
|
||||
class Game {
|
||||
public:
|
||||
static constexpr int COLS = 10;
|
||||
static constexpr int ROWS = 20;
|
||||
static constexpr int TILE = 28; // logical cell size in pixels (render layer decides use)
|
||||
|
||||
struct Piece { PieceType type{PIECE_COUNT}; int rot{0}; int x{3}; int y{-2}; };
|
||||
|
||||
explicit Game(int startLevel = 0) { reset(startLevel); }
|
||||
void reset(int startLevel = 0);
|
||||
|
||||
// Simulation -----------------------------------------------------------
|
||||
void tickGravity(double frameMs); // advance gravity accumulator & drop
|
||||
void softDropBoost(double frameMs); // accelerate fall while held
|
||||
void hardDrop(); // instant drop & lock
|
||||
void setSoftDropping(bool on) { softDropping = on; } // mark if player holds Down
|
||||
void move(int dx); // horizontal move
|
||||
void rotate(int dir); // +1 cw, -1 ccw (simple wall-kick)
|
||||
void holdCurrent(); // swap with hold (once per spawn)
|
||||
|
||||
// Accessors -----------------------------------------------------------
|
||||
const std::array<int, COLS*ROWS>& boardRef() const { return board; }
|
||||
const Piece& current() const { return cur; }
|
||||
const Piece& next() const { return nextPiece; }
|
||||
const Piece& held() const { return hold; }
|
||||
bool canHoldPiece() const { return canHold; }
|
||||
bool isGameOver() const { return gameOver; }
|
||||
bool isPaused() const { return paused; }
|
||||
void setPaused(bool p) { paused = p; }
|
||||
int score() const { return _score; }
|
||||
int lines() const { return _lines; }
|
||||
int level() const { return _level; }
|
||||
int startLevelBase() const { return startLevel; }
|
||||
double elapsed() const { return _elapsedSec; }
|
||||
void addElapsed(double frameMs) { if (!paused) _elapsedSec += frameMs/1000.0; }
|
||||
|
||||
// Block statistics
|
||||
const std::array<int, PIECE_COUNT>& getBlockCounts() const { return blockCounts; }
|
||||
|
||||
// Line clearing effects support
|
||||
bool hasCompletedLines() const { return !completedLines.empty(); }
|
||||
const std::vector<int>& getCompletedLines() const { return completedLines; }
|
||||
void clearCompletedLines(); // Actually remove the lines from the board
|
||||
|
||||
// Sound effect callbacks
|
||||
using SoundCallback = std::function<void(int)>; // Callback for line clear sounds (number of lines)
|
||||
using LevelUpCallback = std::function<void(int)>; // Callback for level up sounds
|
||||
void setSoundCallback(SoundCallback callback) { soundCallback = callback; }
|
||||
void setLevelUpCallback(LevelUpCallback callback) { levelUpCallback = callback; }
|
||||
|
||||
// Shape helper --------------------------------------------------------
|
||||
static bool cellFilled(const Piece& p, int cx, int cy);
|
||||
|
||||
// Gravity tuning accessors (public API for HUD/tuning)
|
||||
void setGravityGlobalMultiplier(double m) { gravityGlobalMultiplier = m; }
|
||||
double getGravityGlobalMultiplier() const;
|
||||
double getGravityMs() const;
|
||||
void setLevelGravityMultiplier(int level, double m);
|
||||
|
||||
private:
|
||||
std::array<int, COLS*ROWS> board{}; // 0 empty else color index
|
||||
Piece cur{}, hold{}, nextPiece{}; // current, held & next piece
|
||||
bool canHold{true};
|
||||
bool paused{false};
|
||||
std::vector<PieceType> bag; // 7-bag randomizer
|
||||
std::mt19937 rng{ std::random_device{}() };
|
||||
std::array<int, PIECE_COUNT> blockCounts{}; // Count of each piece type used
|
||||
|
||||
int _score{0};
|
||||
int _lines{0};
|
||||
int _level{1};
|
||||
double gravityMs{800.0};
|
||||
double fallAcc{0.0};
|
||||
double _elapsedSec{0.0};
|
||||
bool gameOver{false};
|
||||
int startLevel{0};
|
||||
bool softDropping{false}; // true while player holds Down key
|
||||
|
||||
// Line clearing support
|
||||
std::vector<int> completedLines; // Rows that are complete and ready for effects
|
||||
|
||||
// Sound effect callbacks
|
||||
SoundCallback soundCallback;
|
||||
LevelUpCallback levelUpCallback;
|
||||
// Gravity tuning -----------------------------------------------------
|
||||
// Global multiplier applied to all level timings (use to slow/speed whole-game gravity)
|
||||
double gravityGlobalMultiplier{1.0};
|
||||
// Gravity manager encapsulates frames table, multipliers and conversions
|
||||
GravityManager gravityMgr;
|
||||
// Backwards-compatible accessors (delegate to gravityMgr)
|
||||
double computeGravityMsForLevel(int level) const;
|
||||
|
||||
// Internal helpers ----------------------------------------------------
|
||||
void refillBag();
|
||||
void spawn();
|
||||
bool collides(const Piece& p) const;
|
||||
void lockPiece();
|
||||
int checkLines(); // Find completed lines and store them
|
||||
void actualClearLines(); // Actually remove lines from board
|
||||
bool tryMoveDown(); // one-row fall; returns true if moved
|
||||
// Gravity tuning helpers (public API declared above)
|
||||
};
|
||||
Reference in New Issue
Block a user