2a45c98fb3
Main / Build (BookPlayer) (push) Has been cancelled
Main / Build (Brainfuck) (push) Has been cancelled
Main / Build (Breakout) (push) Has been cancelled
Main / Build (Calculator) (push) Has been cancelled
Main / Build (Diceware) (push) Has been cancelled
Main / Build (EpubReader) (push) Has been cancelled
Main / Build (GPIO) (push) Has been cancelled
Main / Build (GraphicsDemo) (push) Has been cancelled
Main / Build (HelloWorld) (push) Has been cancelled
Main / Build (M5UnitTest) (push) Has been cancelled
Main / Build (Magic8Ball) (push) Has been cancelled
Main / Build (MediaKeys) (push) Has been cancelled
Main / Build (MystifyDemo) (push) Has been cancelled
Main / Build (SerialConsole) (push) Has been cancelled
Main / Build (Snake) (push) Has been cancelled
Main / Build (TamaTac) (push) Has been cancelled
Main / Build (TodoList) (push) Has been cancelled
Main / Build (TwoEleven) (push) Has been cancelled
Main / Bundle (push) Has been cancelled
- Intro redesign QVGA: left scrollable column 2 cards GOAL+CONTROLS only, right 44px rail small icons Play 38 accent + Exit 30 muted (fixes cramped) - Tutorial by play: floor0 TUTORIAL_ROWS=2 player+stairs, floor1 bat+gold+stairs, real game from floor2 infinite with displayFloor mapping - Model: renderRows, isTutorial(), tutorialId(), clearAllTiles(), generateTutorialFloor - Renderer: respects renderRows HIDDEN, board height 2 rows centered, TUT messages - Game: reset tutorials=true, skip moveMonsters in tutorial, bests only real floors - Keep audio-stream migration: SDK 0.8.0-dev IDF5.5, CMake GLOB SfxEngine, SfxEngine audio-stream - No unexported LVGL: no max_width/scrollbar_mode -> 0 missing symbols Installed 192.168.68.134 verified screenshot 6.1K airy left+right
64 lines
2.0 KiB
C++
64 lines
2.0 KiB
C++
#pragma once
|
|
|
|
#include <GameKitGrid.h>
|
|
#include <cstdint>
|
|
|
|
namespace PocketDungeon {
|
|
static constexpr uint8_t DUNGEON_COLS = 9;
|
|
static constexpr uint8_t DUNGEON_ROWS = 7;
|
|
static constexpr uint8_t TUTORIAL_ROWS = 2;
|
|
static constexpr uint8_t MAX_ENTITIES = 8;
|
|
|
|
enum class Tile : uint8_t { Floor, Wall, Stairs, Treasure };
|
|
enum class EntityType : uint8_t { Player, Slime, Bat };
|
|
enum class MoveResult : uint8_t { None, Moved, Blocked, Attacked, Treasure, Stairs, Dead };
|
|
|
|
struct Entity {
|
|
EntityType type = EntityType::Slime;
|
|
GameKit::GridPos pos {};
|
|
int8_t hp = 1;
|
|
bool alive = false;
|
|
};
|
|
|
|
struct DungeonState {
|
|
Tile tiles[DUNGEON_ROWS][DUNGEON_COLS] {};
|
|
Entity entities[MAX_ENTITIES] {};
|
|
uint8_t entityCount = 0;
|
|
GameKit::GridPos playerPos {1, 1};
|
|
uint16_t floor = 0; // 0,1 tutorial, 2+ real
|
|
uint16_t gold = 0;
|
|
int8_t hp = 5;
|
|
bool gameOver = false;
|
|
uint8_t renderRows = DUNGEON_ROWS;
|
|
};
|
|
|
|
class DungeonModel {
|
|
DungeonState state {};
|
|
uint32_t seed = 0xC0FFEE;
|
|
uint16_t bestFloor = 1;
|
|
uint16_t bestGold = 0;
|
|
|
|
uint32_t nextRandom();
|
|
void addEnemy(EntityType type, GameKit::GridPos pos, int8_t hp);
|
|
int findEnemyAt(GameKit::GridPos pos) const;
|
|
bool isWalkable(GameKit::GridPos pos) const;
|
|
void moveMonsters();
|
|
void generateTutorialFloor(uint8_t tId);
|
|
void clearAllTiles();
|
|
|
|
public:
|
|
void reset(uint32_t seedValue = 0xC0FFEE, bool tutorials = true);
|
|
void generateFloor();
|
|
MoveResult movePlayer(int dx, int dy);
|
|
|
|
const DungeonState& getState() const { return state; }
|
|
uint16_t getBestFloor() const { return bestFloor; }
|
|
uint16_t getBestGold() const { return bestGold; }
|
|
void setBests(uint16_t floor, uint16_t gold) { bestFloor = floor; bestGold = gold; }
|
|
bool isTutorial() const { return state.floor < 2; }
|
|
uint8_t tutorialId() const { return static_cast<uint8_t>(state.floor); }
|
|
uint16_t displayFloor() const { return state.floor < 2 ? 1 : state.floor - 1; }
|
|
};
|
|
|
|
} // namespace PocketDungeon
|