From dbe43445c70dd705f92ea079fb961ae36b8e82e6 Mon Sep 17 00:00:00 2001 From: JustScott Date: Sat, 13 Jan 2024 12:17:23 -0600 Subject: [PATCH] Add app/game: Bird --- src/CMakeLists.txt | 1 + src/displayapp/DisplayApp.cpp | 1 + src/displayapp/apps/Apps.h.in | 1 + src/displayapp/apps/CMakeLists.txt | 1 + src/displayapp/fonts/fonts.json | 2 +- src/displayapp/screens/Bird.cpp | 143 +++++++++++++++++++++++++++++ src/displayapp/screens/Bird.h | 63 +++++++++++++ src/displayapp/screens/Symbols.h | 1 + 8 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 src/displayapp/screens/Bird.cpp create mode 100644 src/displayapp/screens/Bird.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1b3de51c..b2007cbd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -383,6 +383,7 @@ list(APPEND SOURCE_FILES displayapp/screens/ApplicationList.cpp displayapp/screens/Notifications.cpp displayapp/screens/Twos.cpp + displayapp/screens/Bird.cpp displayapp/screens/HeartRate.cpp displayapp/screens/FlashLight.cpp displayapp/screens/List.cpp diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 938d1179..c6be65a2 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -14,6 +14,7 @@ #include "displayapp/screens/FirmwareUpdate.h" #include "displayapp/screens/FirmwareValidation.h" #include "displayapp/screens/InfiniPaint.h" +#include "displayapp/screens/Bird.h" #include "displayapp/screens/Paddle.h" #include "displayapp/screens/StopWatch.h" #include "displayapp/screens/Metronome.h" diff --git a/src/displayapp/apps/Apps.h.in b/src/displayapp/apps/Apps.h.in index e6e8d7dc..98bcfa60 100644 --- a/src/displayapp/apps/Apps.h.in +++ b/src/displayapp/apps/Apps.h.in @@ -21,6 +21,7 @@ namespace Pinetime { Paint, Paddle, Twos, + Bird, HeartRate, Navigation, StopWatch, diff --git a/src/displayapp/apps/CMakeLists.txt b/src/displayapp/apps/CMakeLists.txt index a531bdff..78c03e96 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -10,6 +10,7 @@ else () set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Paint") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Paddle") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Twos") + set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Bird") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Metronome") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Navigation") #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Weather") diff --git a/src/displayapp/fonts/fonts.json b/src/displayapp/fonts/fonts.json index ead5239e..dc287117 100644 --- a/src/displayapp/fonts/fonts.json +++ b/src/displayapp/fonts/fonts.json @@ -7,7 +7,7 @@ }, { "file": "FontAwesome5-Solid+Brands+Regular.woff", - "range": "0xf294, 0xf242, 0xf54b, 0xf21e, 0xf1e6, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252, 0xf569, 0xf06e, 0xf015, 0xf00c, 0xf743" + "range": "0xf294, 0xf242, 0xf54b, 0xf21e, 0xf1e6, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252, 0xf569, 0xf06e, 0xf015, 0xf00c, 0xf743, 0xf4ba" } ], "bpp": 1, diff --git a/src/displayapp/screens/Bird.cpp b/src/displayapp/screens/Bird.cpp new file mode 100644 index 00000000..d2d78fde --- /dev/null +++ b/src/displayapp/screens/Bird.cpp @@ -0,0 +1,143 @@ +#include "displayapp/screens/Bird.h" +#include "displayapp/DisplayApp.h" +#include "displayapp/LittleVgl.h" +#include "displayapp/screens/Symbols.h" + +#include // for rand() + +using namespace Pinetime::Applications::Screens; + +Bird::Bird() { + + lv_obj_t* background = lv_obj_create(lv_scr_act(), nullptr); + lv_obj_set_size(background, LV_HOR_RES, LV_VER_RES); + lv_obj_set_style_local_radius(background, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); + lv_obj_set_style_local_bg_color(background, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x2874a6)); + + cactus_top = lv_obj_create(lv_scr_act(), nullptr); + lv_obj_set_size(cactus_top, CACTUS_WIDTH, CACTUS_HEIGHT); + lv_obj_set_style_local_bg_color(cactus_top, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN); + lv_obj_set_style_local_border_color(cactus_top, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + lv_obj_set_style_local_border_width(cactus_top, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 1); + + cactus_bottom = lv_obj_create(lv_scr_act(), nullptr); + lv_obj_set_size(cactus_bottom, CACTUS_WIDTH, CACTUS_HEIGHT); + lv_obj_set_style_local_bg_color(cactus_bottom, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN); + lv_obj_set_style_local_border_color(cactus_bottom, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + lv_obj_set_style_local_border_width(cactus_bottom, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 1); + + MovePipe(); + + points = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(points, " "); + lv_obj_align(points, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -10, 5); + + info = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(info, "touch to start"); + lv_obj_align(info, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 40); + + bird = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(bird, Symbols::dove); + lv_obj_set_style_local_text_color(bird, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW); + lv_obj_set_pos(bird, BIRD_X, pos); + + taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this); +} + +Bird::~Bird() { + lv_task_del(taskRefresh); + lv_obj_clean(lv_scr_act()); +} + +void Bird::MovePipe() { + lv_obj_set_pos(cactus_top, cactus_x, -cactus_y_offset); + lv_obj_set_pos(cactus_bottom, cactus_x, CACTUS_HEIGHT + CACTUS_GAP - cactus_y_offset); + return; +} + +void Bird::Refresh() { + if (is_stopped) { + return; + } + + pos += accel / 6; + + if (is_ascending) { + if (accel >= -18) { + accel -= 3; + } + } else { + if (accel <= 42) { + accel++; + } + } + + // checks if it has hit the floor or ceiling + if (pos <= 1 || pos >= LV_VER_RES - BIRD_SIZE) { + GameOver(); + return; + } + + // checks if it has rammed into cacti + // BIRD_X-CACTUS_WIDTH to BIRD_X+BIRD_SIZE + if (90 < cactus_x && cactus_x < 130) { + if (pos < CACTUS_HEIGHT - cactus_y_offset || pos > CACTUS_HEIGHT + CACTUS_GAP - BIRD_SIZE - cactus_y_offset) { + GameOver(); + return; + } + } + + lv_obj_set_pos(bird, BIRD_X, pos); + + lv_label_set_text_fmt(points, "%04d", score / 10); + is_ascending = false; + + score++; + if (cactus_x == 0) { + while (true) { + uint8_t new_offset = rand() % 5 * 40; + if (new_offset != cactus_y_offset) { + cactus_y_offset = new_offset; + break; + } + } + cactus_x = 240; + } + cactus_x--; + if (cactus_x % 4 == 0) { + MovePipe(); + } +} + +void Bird::GameOver() { + is_stopped = true; + lv_label_set_text_static(info, "Game Over"); + lv_obj_align(info, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 40); + lv_obj_set_style_local_text_color(bird, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); + return; +} + +bool Bird::OnTouchEvent(Pinetime::Applications::TouchEvents /*event*/) { + if (is_stopped) { + if (pos != 120) { + pos = 120; + lv_label_set_text_static(info, "Touch to Start"); + lv_obj_align(info, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 40); + lv_obj_set_style_local_text_color(bird, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW); + return true; + } + // reset + cactus_x = 240; + accel = 0; + score = 0; + is_stopped = false; + lv_label_set_text_static(info, ""); + } + is_ascending = true; + return true; +} + +bool Bird::OnTouchEvent(uint16_t /*x*/, uint16_t /*y*/) { + is_ascending = true; + return true; +} diff --git a/src/displayapp/screens/Bird.h b/src/displayapp/screens/Bird.h new file mode 100644 index 00000000..b6d44d30 --- /dev/null +++ b/src/displayapp/screens/Bird.h @@ -0,0 +1,63 @@ +#pragma once + +#include +#include +#include "displayapp/screens/Screen.h" +#include "Symbols.h" +#include "systemtask/SystemTask.h" + +#define BIRD_X 110 +#define BIRD_SIZE 20 +#define CACTUS_HEIGHT 160 +#define CACTUS_WIDTH 30 +#define CACTUS_GAP 80 + +namespace Pinetime { + namespace Components { + class LittleVgl; + } + + namespace Applications { + namespace Screens { + + class Bird : public Screen { + public: + Bird(); + ~Bird() override; + + void Refresh() override; + + bool OnTouchEvent(TouchEvents event) override; + bool OnTouchEvent(uint16_t x, uint16_t y) override; + + private: + void GameOver(); + void MovePipe(); + + bool is_stopped = true; + bool is_ascending = false; + + uint8_t cactus_x = 240; + uint8_t cactus_y_offset = 40; + + int8_t accel = 0; + uint8_t pos = 120; + uint16_t score = 0; + + lv_obj_t *info, *points, *bird, *cactus_top, *cactus_bottom; + + lv_task_t* taskRefresh; + }; + } + + template <> + struct AppTraits { + static constexpr Apps app = Apps::Bird; + static constexpr const char* icon = Screens::Symbols::dove; + + static Screens::Screen* Create(AppControllers& /*controllers*/) { + return new Screens::Bird(); + }; + }; + } +} diff --git a/src/displayapp/screens/Symbols.h b/src/displayapp/screens/Symbols.h index 549ea04f..495c3261 100644 --- a/src/displayapp/screens/Symbols.h +++ b/src/displayapp/screens/Symbols.h @@ -20,6 +20,7 @@ namespace Pinetime { static constexpr const char* paintbrush = "\xEF\x87\xBC"; static constexpr const char* paddle = "\xEF\x91\x9D"; static constexpr const char* map = "\xEF\x96\xa0"; + static constexpr const char* dove = "\xEF\x92\xBA"; static constexpr const char* phone = "\xEF\x82\x95"; static constexpr const char* phoneSlash = "\xEF\x8F\x9D"; static constexpr const char* volumMute = "\xEF\x9A\xA9";