Added challenge mode
This commit is contained in:
@ -7,12 +7,26 @@
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <SDL3/SDL.h>
|
||||
#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
|
||||
|
||||
// Game runtime mode
|
||||
enum class GameMode { Endless, Challenge };
|
||||
|
||||
// Special obstacle blocks used by Challenge mode
|
||||
enum class AsteroidType : uint8_t { Normal = 0, Armored = 1, Falling = 2, Core = 3 };
|
||||
|
||||
struct AsteroidCell {
|
||||
AsteroidType type{AsteroidType::Normal};
|
||||
uint8_t hitsRemaining{1};
|
||||
bool gravityEnabled{false};
|
||||
uint8_t visualState{0};
|
||||
};
|
||||
|
||||
class Game {
|
||||
public:
|
||||
static constexpr int COLS = 10;
|
||||
@ -21,8 +35,10 @@ public:
|
||||
|
||||
struct Piece { PieceType type{PIECE_COUNT}; int rot{0}; int x{3}; int y{-2}; };
|
||||
|
||||
explicit Game(int startLevel = 0) { reset(startLevel); }
|
||||
explicit Game(int startLevel = 0, GameMode mode = GameMode::Endless) : mode(mode) { reset(startLevel); }
|
||||
void reset(int startLevel = 0);
|
||||
void startChallengeRun(int startingLevel = 1); // resets stats and starts challenge level 1 (or provided)
|
||||
void beginNextChallengeLevel(); // advances to the next challenge level preserving score/time
|
||||
|
||||
// Simulation -----------------------------------------------------------
|
||||
void tickGravity(double frameMs); // advance gravity accumulator & drop
|
||||
@ -42,13 +58,20 @@ public:
|
||||
bool isGameOver() const { return gameOver; }
|
||||
bool isPaused() const { return paused; }
|
||||
void setPaused(bool p);
|
||||
GameMode getMode() const { return mode; }
|
||||
void setMode(GameMode m) { mode = m; }
|
||||
int score() const { return _score; }
|
||||
int lines() const { return _lines; }
|
||||
int level() const { return _level; }
|
||||
int challengeLevel() const { return challengeLevelIndex; }
|
||||
int asteroidsRemaining() const { return asteroidsRemainingCount; }
|
||||
int asteroidsTotal() const { return asteroidsTotalThisLevel; }
|
||||
bool isChallengeComplete() const { return challengeComplete; }
|
||||
int startLevelBase() const { return startLevel; }
|
||||
double elapsed() const; // Now calculated from start time
|
||||
void updateElapsedTime(); // Update elapsed time from system clock
|
||||
bool isSoftDropping() const { return softDropping; }
|
||||
const std::array<std::optional<AsteroidCell>, COLS*ROWS>& asteroidCells() const { return asteroidGrid; }
|
||||
|
||||
// Block statistics
|
||||
const std::array<int, PIECE_COUNT>& getBlockCounts() const { return blockCounts; }
|
||||
@ -87,6 +110,9 @@ public:
|
||||
int comboCount() const { return _comboCount; }
|
||||
|
||||
private:
|
||||
static constexpr int ASTEROID_BASE = 100; // sentinel offset for board encoding
|
||||
static constexpr int ASTEROID_MAX_LEVEL = 100;
|
||||
|
||||
std::array<int, COLS*ROWS> board{}; // 0 empty else color index
|
||||
Piece cur{}, hold{}, nextPiece{}; // current, held & next piece
|
||||
bool canHold{true};
|
||||
@ -132,6 +158,17 @@ private:
|
||||
uint32_t hardDropFxId{0};
|
||||
uint64_t pieceSequence{0};
|
||||
|
||||
// Challenge mode state -------------------------------------------------
|
||||
GameMode mode{GameMode::Endless};
|
||||
int challengeLevelIndex{1};
|
||||
int asteroidsRemainingCount{0};
|
||||
int asteroidsTotalThisLevel{0};
|
||||
bool challengeComplete{false};
|
||||
std::array<std::optional<AsteroidCell>, COLS*ROWS> asteroidGrid{};
|
||||
uint32_t challengeSeedBase{0};
|
||||
std::mt19937 challengeRng{ std::random_device{}() };
|
||||
bool challengeLevelActive{false};
|
||||
|
||||
// Internal helpers ----------------------------------------------------
|
||||
void refillBag();
|
||||
void spawn();
|
||||
@ -140,5 +177,14 @@ private:
|
||||
int checkLines(); // Find completed lines and store them
|
||||
void actualClearLines(); // Actually remove lines from board
|
||||
bool tryMoveDown(); // one-row fall; returns true if moved
|
||||
void clearAsteroidGrid();
|
||||
void setupChallengeLevel(int level, bool preserveStats);
|
||||
void placeAsteroidsForLevel(int level);
|
||||
AsteroidType chooseAsteroidTypeForLevel(int level);
|
||||
AsteroidCell makeAsteroidForType(AsteroidType t) const;
|
||||
void handleAsteroidsOnClearedRows(const std::vector<int>& clearedRows,
|
||||
std::array<int, COLS*ROWS>& outBoard,
|
||||
std::array<std::optional<AsteroidCell>, COLS*ROWS>& outAsteroids);
|
||||
void applyAsteroidGravity();
|
||||
// Gravity tuning helpers (public API declared above)
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user