mirror of
https://github.com/eried/portapack-mayhem.git
synced 2025-08-07 06:02:20 -04:00
Made the Dino Game (#2697)
This commit is contained in:
parent
20f28c8331
commit
18bc2cf11c
7 changed files with 1716 additions and 0 deletions
254
firmware/application/external/dinogame/ui_dinogame.hpp
vendored
Normal file
254
firmware/application/external/dinogame/ui_dinogame.hpp
vendored
Normal file
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
* ------------------------------------------------------------
|
||||
* | 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 <string>
|
||||
#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__ */
|
Loading…
Add table
Add a link
Reference in a new issue