#ifndef GAME_H_7D2B65AE #define GAME_H_7D2B65AE #include #include #include #include #include "map.h" #include "muxer.h" #include "timer.h" #include "animation.h" #include "interpolation.h" #include "consts.h" #include "sign.h" #include "menu.h" #include "runtime.h" class Renderer; constexpr int TilesetIndex(int x, int y) { return x + y * 25; } enum class LoseState { NewGame, None, PoppingLamps, PoppingPlayer, Outro, Done }; enum class HelpState { PreWait, FadeIn, Hold, FadeOut, Done }; struct Input { bool left = false; bool right = false; bool up = false; bool down = false; bool operator==(const Input& rhs) const { return std::tie(left, right, up, down) == std::tie(rhs.left, rhs.right, rhs.up, rhs.down); } bool operator!=(const Input& rhs) const { return !(*this == rhs); } }; struct Kickup { int x; int y; size_t cur; size_t radius; size_t chain; std::set done; std::set front; }; class Game { public: Game(std::mt19937& rng, Muxer& muxer, Renderer& render); void update(size_t dt); std::mt19937& rng; Muxer& muxer; Renderer& renderer; bool quit = false; bool quitting = false; // <- whether we will quit after losing, vs starting a new game LoseState losing = LoseState::NewGame; Interpolation initialFade; bool startedMusic = false; HelpState helpState = HelpState::PreWait; Interpolation helpProgress; Map map; std::list kickups; int litSpots = 0; bool dirtyLighting = true; bool dirtyRender = true; size_t numLamps = 0; size_t numDust = 0; std::vector mapDoubleBuffer; int ticksNeeded = 0; Timer gradualTickTimer = {100}; int player_x = 0; int player_y = 0; int player_oldx = 0; int player_oldy = 0; bool renderPlayer = true; Animation playerAnim {Runtime::getResourcePath("player_anim.txt")}; int maxZoom = INIT_ZOOM; int curZoom = INIT_ZOOM; int oldZoom = INIT_ZOOM; bool zooming = false; Interpolation zoomProgress; double getZoomBasis() const { return zooming ? std::max(curZoom, oldZoom) : curZoom; } Input keystate; bool firstInput = false; Input lastInput; bool alreadyBumped = false; Timer bumpCooldown = {500}; Interpolation moveProgress; bool moving = false; bool queueDash = false; Timer dustTimer = {40}; Timer inputTimer = {50}; Timer losePopLampTimer = {800}; Timer losePopPlayerTimer = {3000}; std::vector signTexts; int nextSignIndex = 0; bool storyDone = false; SignInstructionState signInstructionState = SignInstructionState::Hidden; Interpolation signFade; Sign sign; bool clearedSigns = false; Menu menu; private: void tickDirty(bool onlyDark); void tickOuter(bool onlyDark = false); void tick( int x1, int y1, int x2, int y2, bool invert = false, bool onlyDark = false); void tick(bool onlyDark = false); bool isInitialCaveBigEnough() const; bool movePlayer(int x, int y); void recalculateLighting(); void recalculateRender(); bool processKeys(const Input& keystate); void kickUpDust(int x, int y, size_t chain); void popLamp(int x, int y, size_t chain); void processKickup(); void loadMap(); void setZoom(size_t zoom); void performDash(); void updatePlaying(size_t frameTime); }; #endif /* end of include guard: GAME_H_7D2B65AE */