70 lines
1.8 KiB
C++
70 lines
1.8 KiB
C++
#ifndef GAME_STATE_H
|
|
#define GAME_STATE_H
|
|
|
|
#include <array>
|
|
#include <deque>
|
|
#include <vector>
|
|
#include <nds/ndstypes.h>
|
|
|
|
#include "consts.h"
|
|
|
|
enum class Scene {
|
|
Menu,
|
|
Playing,
|
|
};
|
|
|
|
constexpr int MENU_ITEM_COUNT = 3;
|
|
|
|
enum class BarrierPhase : uint8_t {
|
|
Inactive, // Slot free
|
|
Warning, // Flashing announcement, harmless
|
|
Active, // Solid and fatal to the snake head
|
|
};
|
|
|
|
// Temporary hard-mode wall: a straight line of `length` cells starting at (x, y).
|
|
// Lifetime is tracked in VBlank frames (see tick_barriers_frame()).
|
|
struct Barrier {
|
|
BarrierPhase phase = BarrierPhase::Inactive;
|
|
int8_t x = 0;
|
|
int8_t y = 0;
|
|
bool vertical = false;
|
|
uint8_t length = 0;
|
|
uint16_t framesLeft = 0; // Frames remaining in the current phase
|
|
};
|
|
|
|
// Evil item (rotten apple or cursed apple) with position and lifetime in game ticks
|
|
struct EvilItem {
|
|
int8_t x = 0;
|
|
int8_t y = 0;
|
|
uint16_t ticksRemaining = 0;
|
|
};
|
|
|
|
struct GameState {
|
|
volatile uint16_t ticks = 0;
|
|
volatile uint16_t snakelength = 0;
|
|
volatile uint16_t snakeDirection = 1;
|
|
volatile uint16_t score = 0;
|
|
volatile uint16_t applesEaten = 0;
|
|
|
|
bool gameOver = false;
|
|
bool paused = false;
|
|
bool hardMode = false;
|
|
|
|
Scene scene = Scene::Menu;
|
|
int menuSelection = 0;
|
|
|
|
uint16_t curseTicksRemaining = 0;
|
|
|
|
// Fixed-size (no heap) because barriers are touched from both the VBlank
|
|
// and Timer 0 IRQs. Those IRQs don't nest, so no further locking is needed.
|
|
std::array<Barrier, BARRIER_MAX_COUNT> barriers{};
|
|
volatile uint16_t barrierSpawnCooldown = 0; // Frames until the next spawn attempt
|
|
|
|
std::deque<std::array<int, 3>> snake;
|
|
std::vector<std::array<int, 2>> apples;
|
|
std::vector<EvilItem> bad_apples;
|
|
std::vector<EvilItem> cursed_apples;
|
|
};
|
|
|
|
#endif
|