/* * ------------------------------------------------------------ * | Made by RocketGod | * | Find me at https://betaskynet.com | * | Argh matey! | * ------------------------------------------------------------ */ /* * Chrome Dino Game for Portapack Mayhem * Based on the original DinoGame by various contributors */ #ifndef __UI_DINOGAME_H__ #define __UI_DINOGAME_H__ #include "ui.hpp" #include "ui_navigation.hpp" #include "event_m0.hpp" #include "message.hpp" #include "irq_controls.hpp" #include "random.hpp" #include "lpc43xx_cpp.hpp" #include "ui_widget.hpp" #include "file.hpp" #include #include "app_settings.hpp" namespace ui::external_app::dinogame { // Color definitions enum { White, Blue, Yellow, Purple, Green, Red, Maroon, Orange, Black, }; // Game constants #define DINO_WIDTH 34 #define DINO_HEIGHT 36 #define DINO_DUCK_WIDTH 45 #define DINO_DUCK_HEIGHT 22 #define BIRD_WIDTH 34 #define BIRD_HEIGHT 27 #define GROUND_HEIGHT 10 #define GAME_AREA_TOP 78 #define GAME_AREA_HEIGHT 160 #define DINO_X 30 #define DINO_Y (GAME_AREA_TOP + GAME_AREA_HEIGHT - GROUND_HEIGHT - DINO_HEIGHT) #define DINO_DUCK_Y (GAME_AREA_TOP + GAME_AREA_HEIGHT - GROUND_HEIGHT - DINO_DUCK_HEIGHT) #define BIRD_Y_UP (GAME_AREA_TOP + 20) #define BIRD_Y_DOWN (GAME_AREA_TOP + 60) #define JUMP_MAX_HEIGHT 70 #define JUMP_SPEED 3 #define GAME_SPEED_BASE 3 #define SPRITE_COLOR 0x528A #define TRANSPARENT_COLOR 0xFFFF #define MIN_OBSTACLE_DISTANCE 300 #define MAX_OBSTACLE_DISTANCE 600 // Game states enum class GameState { MENU, PLAYING, GAME_OVER }; // Walk styles enum class WalkStyle { WALKING, DUCKING }; // Bird position enum class BirdPosition { UP, DOWN }; // Structures struct Pterodactyl { bool inGame = false; BirdPosition y_position = BirdPosition::UP; int16_t x_offset = 320; int16_t y_offset = 0; int8_t y_velocity = 0; bool flop = false; }; // Simple obstacle structure with proper initialization struct SimpleObstacle { bool active; int16_t x; int16_t last_x; uint8_t width; uint8_t height; uint8_t type; // 0=small, 1=large, 2=double, 3=triple SimpleObstacle() : active(false), x(0), last_x(0), width(0), height(0), type(0) {} }; // External references to sprite data extern const uint16_t dino_default[]; extern const uint16_t dino_leftstep[]; extern const uint16_t dino_rightstep[]; extern const uint16_t dino_ducking_leftstep[]; extern const uint16_t dino_ducking_rightstep[]; extern const uint16_t dino_gameover[]; extern const uint16_t pterodactyl_upflop[]; extern const uint16_t pterodactyl_downflop[]; // Global painter extern Painter painter; // Function declarations void cls(); void fillrect(int x1, int y1, int x2, int y2, int color); void rect(int x1, int y1, int x2, int y2, int color); void check_game_timer(); void game_timer_check(); // Ticker class using Callback = void (*)(void); class Ticker { public: Ticker() = default; void attach(Callback func, double delay_sec); void detach(); }; // Main view class class DinoGameView : public View { public: DinoGameView(NavigationView& nav); void on_show() override; std::string title() const override { return "Dino Game"; } void focus() override { dummy.focus(); } void paint(Painter& painter) override; void frame_sync(); bool on_encoder(const EncoderEvent event) override; bool on_key(KeyEvent key) override; // Public for timer callback GameState game_state = GameState::MENU; void game_loop(); void show_menu(); private: bool initialized = false; NavigationView& nav_; // Game variables static constexpr uint8_t MAX_OBSTACLES = 1; SimpleObstacle obstacles[MAX_OBSTACLES]; Pterodactyl bird_info; int16_t jumpHeight = 0; uint8_t ground_offset = 0; uint8_t speed_modifier = 0; bool runstate = false; bool jumping = false; bool falling = false; bool collided = false; bool ducking = false; bool displayedGameOver = false; bool last_ducking = false; bool last_runstate = false; uint32_t steps = 0; uint32_t score = 0; uint32_t highScore = 0; uint32_t last_score = 999999; // Initialize to impossible value int32_t next_obstacle_distance = 100; int16_t last_obstacle_x = 320; // Track position of last spawned obstacle int32_t obstacle_spawn_timer = 0; // Position tracking for minimal redraw int16_t last_dino_y = DINO_Y; int16_t last_bird_x = -1; int16_t last_bird_y = -1; uint8_t duck_timer = 0; // Menu animation bool menu_initialized = false; bool blink_state = true; uint32_t blink_counter = 0; // Current Score bool score_drawn = false; // Game timer Ticker game_timer; // Private methods void init_game(); void new_game(); void update_obstacles(); void spawn_obstacle(); void draw_screen(); void draw_ground(); void draw_obstacle(const SimpleObstacle& obstacle); void clear_obstacle_area(int x, int width, int height); void draw_dino_sprite(int x, int y, const uint16_t* sprite); void draw_bird_sprite(int x, int y, const uint16_t* sprite); void draw_dino_at(int x, int y, bool is_ducking, bool run_frame); void manage_bird(); void draw_score(); void draw_high_score(); void draw_current_score(); void show_game_over(); void jump(); void duck(); void stand(); void check_collision(); void step(); uint32_t get_steps() { return steps; } std::string score_to_string(uint32_t score); bool easy_mode = false; Button button_difficulty{ {70, 195, 100, 20}, "Mode: HARD"}; app_settings::SettingsManager settings_{ "dinogame", app_settings::Mode::NO_RF, {{"highscore"sv, &highScore}, {"easy_mode"sv, &easy_mode}}}; Button dummy{ {screen_width, 0, 0, 0}, ""}; MessageHandlerRegistration message_handler_frame_sync{ Message::ID::DisplayFrameSync, [this](const Message* const) { this->frame_sync(); }}; }; } // namespace ui::external_app::dinogame #endif /* __UI_DINOGAME_H__ */