Added challenge mode

This commit is contained in:
2025-12-20 13:08:16 +01:00
parent fd29ae271e
commit 34447f0245
15 changed files with 535 additions and 1227 deletions

View File

@ -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)
};