TamaTac & SfxEngine + Sprite tools (#24)

This commit is contained in:
Shadowtrance
2026-02-14 06:26:23 +10:00
committed by GitHub
parent 9ba1d460bd
commit 0b22f67a82
56 changed files with 8282 additions and 0 deletions
+16
View File
@@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 3.20)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
if (DEFINED ENV{TACTILITY_SDK_PATH})
set(TACTILITY_SDK_PATH $ENV{TACTILITY_SDK_PATH})
else()
set(TACTILITY_SDK_PATH "../../release/TactilitySDK")
message(WARNING "⚠️ TACTILITY_SDK_PATH environment variable is not set, defaulting to ${TACTILITY_SDK_PATH}")
endif()
include("${TACTILITY_SDK_PATH}/TactilitySDK.cmake")
set(EXTRA_COMPONENT_DIRS ${TACTILITY_SDK_PATH})
project(TamaTac)
tactility_project(TamaTac)
+240
View File
@@ -0,0 +1,240 @@
# TamaTac
A virtual pet game for Tactility OS, inspired by Tamagotchi and Tactiligotchi.
## About
TamaTac is a digital pet that lives in your ESP32 device. Feed it, play with it, keep it healthy, and watch it grow through different life stages. Your pet persists even when the app is closed, and stats decay while you're away.
## Features
### Core Pet System
- **5 Stats**: Hunger, Happiness, Health, Energy, Cleanliness (0-100%)
- **6 Life Stages**: Egg > Baby > Teen > Adult > Elder > Ghost
- **5 Personalities**: Energetic, Lazy, Glutton, Cheerful, Hardy — each affects stat decay rates
- **Automatic Decay**: Stats decay on a 30-second FreeRTOS timer
- **Configurable Speed**: Slow (0.5x), Normal (1x), Fast (2x) decay rates
- **Sickness**: Health below 20% triggers sick state
- **Death**: Health reaching 0 ends the game
### Actions
- **Feed**: Restores hunger (+30%), may cause poop (40% chance)
- **Play**: Randomly launches Simon Says or Reaction Time mini-game
- **Medicine**: Cures sickness (+30% health) or small boost (+5%)
- **Sleep**: Restores energy (+50%)
- **Clean**: Toolbar button clears all poop, restores cleanliness
- **Pet**: Tap the pet sprite for a small happiness boost (+5%, 3s cooldown)
### Day/Night Cycle
A 1-hour real-time cycle (30 min day / 30 min night):
- **Day**: Increased energy drain (more active)
- **Night**: Increased hunger drain (metabolism), auto-sleep when energy is critically low
- **Visual indicator**: Pet area background changes color between day and night
- MainView refreshes every 5 seconds to reflect changes
### Random Events
Random events occur during timer ticks (~12% chance per tick):
- **Found Treat**: +15 hunger
- **Made a Friend**: +15 happiness
- **Caught a Cold**: Pet gets sick, -10 health
- **Got Muddy**: -20 cleanliness
- **Had a Nap**: +15 energy
- **Sunny Day**: +10 happiness (day only)
Events are contextual — only eligible events trigger based on current stats.
### Mini-Games
#### Simon Says (Pattern Game)
- 4 colored buttons (red, blue, green, yellow) in a 2x2 grid
- Watch the sequence flash, then repeat it
- 3 rounds with increasing pattern length (starts at 3)
- **Win all 3 rounds**: +30 happiness, -10 energy, -5 hunger
- **Partial win (1-2 rounds)**: +10-20 happiness, -5 energy
- **Lose immediately**: +5 happiness, -5 energy
#### Reaction Time Game
- Large green circle target appears after a random delay (1-3.5 seconds)
- Tap as fast as possible when it appears
- Tapping too early = penalty round
- 3 rounds, scored by average reaction time
- Performance mapped to happiness reward
### Pet Cemetery
When your pet dies, it's remembered in the Cemetery:
- Stores up to 5 most recent pets (FIFO)
- Records personality, life stage reached, and age at death
- Accessible from the Menu
### Achievement System
12 achievements to unlock, stored as a bitfield:
- **First Feed**: Feed your pet
- **First Play**: Play a mini-game
- **First Cure**: Cure sickness
- **Baby Steps**: Evolve to Baby
- **Growing Up**: Evolve to Teen
- **All Grown Up**: Evolve to Adult
- **Wise Elder**: Evolve to Elder
- **Perfect Pet**: All stats >= 90%
- **Survivor**: Pet lives 24 hours
- **Pro Gamer**: Perfect mini-game score
- **Clean Freak**: Clean 10 times
- **Night Owl**: Play at night
### Persistence
- Auto-saves every 30 seconds and on every action
- All stats, state flags, and timestamps preserved
- **Time-Away Logic**: Calculates elapsed time since last save, applies decay (capped at ~50 minutes to prevent wipeout), ages pet, and checks evolution
### Sound
Uses the shared SfxEngine library:
- **SFX**: Unique sounds for Feed, Play, Medicine, Sleep, Clean actions; Chirp for tap-to-pet; mini-game sounds (Blip, Confirm, Error, Success)
- Sound toggle in Settings
### Responsive Scaling
Adapts to all Tactility screen sizes:
- **Small** (Cardputer 240x135, T-Dongle): Compact layout, 2x sprites
- **Medium** (T-Deck 320x240): Default layout, 3x sprites
- **Large** (480x320 panels): Spacious layout
- **XLarge** (800x480+): Full-size layout
### Views
- **Main View**: Pet sprite, stat bars with icons, action buttons, poop display, day/night visuals
- **Menu View**: Navigation to Stats, Settings, Cemetery, and Achievements
- **Stats View**: Detailed stats with exact values, age, life stage, personality
- **Settings View**: Sound toggle, decay speed selector
- **Pattern Game**: Simon Says mini-game
- **Reaction Game**: Reaction time mini-game
- **Cemetery View**: Hall of fame for past pets
- **Achievements View**: Progress tracker for all 12 achievements
### Animated Sprites
- 24x24 RGB565 full-color sprites with transparency (magenta color key)
- 12 animated pet sprites (2-3 frames each) for all life stages and states
- 9 monochrome 8x8 UI icons for stats and action buttons
- Canvas-rendered with responsive scaling (2x on small screens, 3x on medium+)
- Animation timer at ~5fps for smooth frame cycling
#### Sprite Preview
| Life Stages | | | | |
|:-:|:-:|:-:|:-:|:-:|
| ![Egg](sprites/egg_idle.png) | ![Baby](sprites/baby_idle.png) | ![Teen](sprites/teen_idle.png) | ![Adult](sprites/adult_idle.png) | ![Elder](sprites/elder_idle.png) |
| Egg (cream) | Baby (pink) | Teen (blue) | Adult (green) | Elder (purple) |
| States | | | | | | |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| ![Happy](sprites/happy.png) | ![Sad](sprites/sad.png) | ![Sick](sprites/sick.png) | ![Eating](sprites/eating.png) | ![Playing](sprites/playing.png) | ![Sleeping](sprites/sleeping.png) | ![Ghost](sprites/ghost.png) |
| Happy | Sad | Sick | Eating | Playing | Sleeping | Ghost |
### Visual Polish
- **Evolution flash**: Brief white flash when pet evolves to a new life stage
- **Night sky**: Twinkling star dots in the pet area during night phase
- **Sleep Z's**: Floating animated Z characters while pet sleeps
- **Mood indicator**: Colored dot in pet area corner (green = happy, orange = warning, red = sick)
## How to Play
### Starting Out
- Your pet starts as an Egg with healthy stats
- After 1 hour it evolves to Baby, then Teen (8h), Adult (24h), Elder (72h)
- Keep stats above 30% to prevent sickness
- Tap the pet sprite anytime for a small happiness boost
### Daily Care
1. **Feed** when hunger drops below 50%
2. **Play** the mini-game to boost happiness
3. **Sleep** when energy is low
4. **Medicine** if pet gets sick
5. **Clean** poop from the toolbar button
### Evolution Timeline
| Stage | Age |
|-------|-----|
| Egg | 0-1 hour |
| Baby | 1-8 hours |
| Teen | 8-24 hours |
| Adult | 24-72 hours |
| Elder | 72+ hours |
## Building
```bash
cd Apps/TamaTac
# Build
python tactility.py build
# Build, install, and run
python tactility.py bir <device-ip>
```
## Project Structure
```text
TamaTac/
CMakeLists.txt
manifest.properties
tactility.py
main/
CMakeLists.txt
Source/
main.cpp # Entry point (registerApp)
TamaTac.h/cpp # Main app class, view management, action handlers
MainView.h/cpp # Pet display, stat bars, action buttons, day/night
MenuView.h/cpp # Navigation menu
StatsView.h/cpp # Detailed stats display (incl. personality)
SettingsView.h/cpp # Sound toggle and decay speed settings
PatternGame.h/cpp # Simon Says mini-game
ReactionGame.h/cpp # Reaction time mini-game
CemeteryView.h/cpp # Pet cemetery / hall of fame
Achievements.h/cpp # Achievement system (12 achievements)
PetLogic.h/cpp # Game mechanics, persistence, decay, events
PetStats.h # Data structures, enums, constants, thresholds
Sprites.h # Sprite/icon types, enums, 8x8 icon data
SpriteData.h # 24x24 RGB565 animated sprite pixel data
```
## Architecture
### View Management
TamaTac uses a multi-view pattern with a shared `wrapperWidget`. Views are swapped via `stopActiveView()` + `lv_obj_clean()` + `newView.onStart()`. Each view has `onStart()`/`onStop()` lifecycle methods.
### Key Components
- **TamaTac**: App lifecycle, view routing, action handlers, achievement triggers, static game state
- **PetLogic**: Stat management, decay, evolution, personality modifiers, day/night cycle, random events, save/load
- **MainView**: Animated pet canvas, stat bars, action buttons, tap-to-pet, day/night visuals, polish effects, 5s refresh timer
- **PatternGame**: Self-contained Simon Says with timer-based sequence display
- **ReactionGame**: Phase-based state machine (wait > target > result > final)
- **CemeteryView**: FIFO record storage for up to 5 past pets
- **AchievementsView**: Bitfield-based achievement tracking with 12 unlockables
- **SfxEngine**: Shared library for synthesized sound effects
### Save Data
| Namespace | Keys |
|-----------|------|
| `"TamaTac"` | `hunger`, `happiness`, `health`, `energy`, `cleanliness`, `poopCount`, `ageSeconds`, `ageHours`, `lifespan`, `isSick`, `isAsleep`, `isDead`, `stage`, `currentAnim`, `lastSaveTime`, `personality` |
| `"TamaTacCfg"` | `soundEnabled`, `decaySpeed` |
| `"TamaTacCem"` | `count`, `pers0..4`, `stage0..4`, `age0..4`, `valid0..4` |
| `"TamaTacAch"` | `bits` (uint16 bitfield), `cleanCnt` |
## Screenshots
| | | | |
|:-:|:-:|:-:|:-:|
| ![Main](images/screenshot-one.tactility.tamatac.png) | ![Main with poops](images/screenshot-12.png) | ![Teen](images/screenshot-11.png) | ![Sleeping](images/screenshot-16.png) |
| Main View | Poops! | Teen | Sleeping |
| ![Menu](images/screenshot-13.png) | ![Stats](images/screenshot-14.png) | ![Settings](images/screenshot-15.png) | ![Achievements](images/screenshot-1.png) |
| Menu | Stats | Settings | Achievements |
## Known Issues
- **Offline time not tracked across reboots**: `lastSaveTime` uses uptime milliseconds (`tt::kernel::getMillis()`), which resets to 0 on device reboot. This means stat decay during power-off periods is not applied. A proper fix would require RTC or epoch-based timestamps, which are not currently available on all Tactility devices.
## Credits
- **Inspired by**: Tamagotchi (Bandai), Tactiligotchi (NellowTCS)
- **Built with**: TactilitySDK, LVGL, ESP-IDF, SfxEngine
- **Platform**: Tactility OS
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

+10
View File
@@ -0,0 +1,10 @@
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
file(GLOB_RECURSE SFX_ENGINE_FILES ../../../Libraries/SfxEngine/Source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES} ${SFX_ENGINE_FILES}
# Library headers must be included directly,
# because all regular dependencies get stripped by elf_loader's cmake script
INCLUDE_DIRS ../../../Libraries/TactilityCpp/Include ../../../Libraries/SfxEngine/Include
REQUIRES TactilitySDK
)
+143
View File
@@ -0,0 +1,143 @@
/**
* @file Achievements.cpp
* @brief Achievement system implementation
*/
#include "Achievements.h"
#include "TamaTac.h"
#include <TactilityCpp/Preferences.h>
#include <cstdio>
static constexpr const char* PREF_NS = "TamaTacAch";
static const AchievementInfo achievementInfos[] = {
{"First Feed", "Feed your pet"},
{"First Play", "Play a mini-game"},
{"First Cure", "Cure sickness"},
{"Baby Steps", "Evolve to Baby"},
{"Growing Up", "Evolve to Teen"},
{"All Grown Up", "Evolve to Adult"},
{"Wise Elder", "Evolve to Elder"},
{"Perfect Pet", "All stats >= 90"},
{"Survivor", "Pet lives 24h"},
{"Pro Gamer", "Perfect mini-game"},
{"Clean Freak", "Clean 10 times"},
{"Night Owl", "Play at night"},
};
const AchievementInfo& AchievementsView::getInfo(AchievementId id) {
int idx = static_cast<int>(id);
if (idx < 0 || idx >= static_cast<int>(AchievementId::COUNT)) {
idx = 0;
}
return achievementInfos[idx];
}
uint16_t AchievementsView::loadAchievements() {
Preferences prefs(PREF_NS);
return static_cast<uint16_t>(prefs.getInt32("bits", 0));
}
void AchievementsView::saveAchievements(uint16_t bits) {
Preferences prefs(PREF_NS);
prefs.putInt32("bits", static_cast<int32_t>(bits));
}
bool AchievementsView::hasAchievement(uint16_t bits, AchievementId id) {
return (bits >> static_cast<uint8_t>(id)) & 1;
}
void AchievementsView::unlock(AchievementId id) {
if (static_cast<int>(id) >= static_cast<int>(AchievementId::COUNT)) {
return;
}
uint16_t bits = loadAchievements();
uint16_t mask = static_cast<uint16_t>(1 << static_cast<int>(id));
if (!(bits & mask)) {
bits |= mask;
saveAchievements(bits);
}
}
int AchievementsView::countUnlocked(uint16_t bits) {
int count = 0;
for (int i = 0; i < static_cast<int>(AchievementId::COUNT); i++) {
if ((bits >> i) & 1) count++;
}
return count;
}
uint16_t AchievementsView::loadCleanCount() {
Preferences prefs(PREF_NS);
return static_cast<uint16_t>(prefs.getInt32("cleanCnt", 0));
}
void AchievementsView::incrementCleanCount() {
Preferences prefs(PREF_NS);
int32_t count = prefs.getInt32("cleanCnt", 0) + 1;
prefs.putInt32("cleanCnt", count);
if (count >= 10) {
unlock(AchievementId::CleanFreak);
}
}
void AchievementsView::onStart(lv_obj_t* parentWidget, TamaTac* appInstance) {
parent = parentWidget;
app = appInstance;
lv_coord_t screenWidth = lv_display_get_horizontal_resolution(nullptr);
lv_coord_t screenHeight = lv_display_get_vertical_resolution(nullptr);
bool isSmall = (screenWidth < 280 || screenHeight < 180);
bool isXLarge = (screenWidth >= 600);
int padAll = isSmall ? 4 : (isXLarge ? 16 : 8);
int padRow = isSmall ? 2 : (isXLarge ? 8 : 4);
mainWrapper = lv_obj_create(parent);
lv_obj_set_size(mainWrapper, LV_PCT(100), LV_PCT(100));
lv_obj_set_style_pad_all(mainWrapper, padAll, 0);
lv_obj_set_style_pad_row(mainWrapper, padRow, 0);
lv_obj_set_style_bg_opa(mainWrapper, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(mainWrapper, 0, 0);
lv_obj_set_flex_flow(mainWrapper, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(mainWrapper, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
uint16_t bits = loadAchievements();
int unlocked = countUnlocked(bits);
// Title with count
lv_obj_t* title = lv_label_create(mainWrapper);
char titleText[48];
snprintf(titleText, sizeof(titleText), "Achievements %d/%d", unlocked, static_cast<int>(AchievementId::COUNT));
lv_label_set_text(title, titleText);
lv_obj_set_style_text_color(title, lv_color_hex(0xFFFFFF), 0);
// Achievement list
for (int i = 0; i < static_cast<int>(AchievementId::COUNT); i++) {
AchievementId id = static_cast<AchievementId>(i);
bool has = hasAchievement(bits, id);
const AchievementInfo& info = getInfo(id);
lv_obj_t* row = lv_obj_create(mainWrapper);
lv_obj_set_size(row, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_set_style_pad_all(row, isSmall ? 2 : (isXLarge ? 8 : 4), 0);
lv_obj_set_style_bg_color(row, has ? lv_color_hex(0x2a4a2e) : lv_color_hex(0x2a2a4e), 0);
lv_obj_set_style_border_width(row, 0, 0);
lv_obj_set_style_radius(row, isSmall ? 2 : (isXLarge ? 8 : 4), 0);
char text[80];
snprintf(text, sizeof(text), "%s %s - %s",
has ? LV_SYMBOL_OK : LV_SYMBOL_CLOSE,
info.name, info.description);
lv_obj_t* label = lv_label_create(row);
lv_label_set_text(label, text);
lv_obj_set_style_text_color(label, has ? lv_color_hex(0x88FF88) : lv_color_hex(0x888888), 0);
}
}
void AchievementsView::onStop() {
mainWrapper = nullptr;
parent = nullptr;
app = nullptr;
}
+59
View File
@@ -0,0 +1,59 @@
/**
* @file Achievements.h
* @brief Achievement system for TamaTac
*/
#pragma once
#include <lvgl.h>
#include <cstdint>
class TamaTac;
// Achievement IDs (bit positions in uint16_t bitfield)
enum class AchievementId : uint8_t {
FirstFeed = 0, // Feed pet for the first time
FirstPlay = 1, // Play a mini-game
FirstCure = 2, // Cure sickness
ReachBaby = 3, // Evolve to Baby
ReachTeen = 4, // Evolve to Teen
ReachAdult = 5, // Evolve to Adult
ReachElder = 6, // Evolve to Elder
FullStats = 7, // All primary stats >= 90
Survivor24h = 8, // Pet survives 24 hours
PerfectGame = 9, // Win a mini-game with perfect score
CleanFreak = 10, // Clean 10 times total
NightOwl = 11, // Play during night phase
COUNT = 12
};
struct AchievementInfo {
const char* name;
const char* description;
};
class AchievementsView {
private:
TamaTac* app = nullptr;
lv_obj_t* parent = nullptr;
lv_obj_t* mainWrapper = nullptr;
public:
AchievementsView() = default;
~AchievementsView() = default;
AchievementsView(const AchievementsView&) = delete;
AchievementsView& operator=(const AchievementsView&) = delete;
void onStart(lv_obj_t* parentWidget, TamaTac* appInstance);
void onStop();
// Bitfield operations
static uint16_t loadAchievements();
static void saveAchievements(uint16_t bits);
static bool hasAchievement(uint16_t bits, AchievementId id);
static void unlock(AchievementId id);
static int countUnlocked(uint16_t bits);
static uint16_t loadCleanCount();
static void incrementCleanCount();
static const AchievementInfo& getInfo(AchievementId id);
};
+135
View File
@@ -0,0 +1,135 @@
/**
* @file CemeteryView.cpp
* @brief Pet Cemetery / Hall of Fame view implementation
*/
#include "CemeteryView.h"
#include "TamaTac.h"
#include <TactilityCpp/Preferences.h>
#include <cstdio>
static constexpr const char* PREF_NS = "TamaTacCem";
void CemeteryView::loadRecords(PetRecord records[MAX_RECORDS]) {
Preferences prefs(PREF_NS);
for (int i = 0; i < MAX_RECORDS; i++) {
char key[16];
snprintf(key, sizeof(key), "valid%d", i);
records[i].valid = prefs.getBool(key, false);
if (records[i].valid) {
snprintf(key, sizeof(key), "pers%d", i);
records[i].personality = static_cast<Personality>(prefs.getInt32(key, 0));
snprintf(key, sizeof(key), "stage%d", i);
records[i].stageReached = static_cast<LifeStage>(prefs.getInt32(key, 0));
snprintf(key, sizeof(key), "age%d", i);
records[i].ageHours = static_cast<uint16_t>(prefs.getInt32(key, 0));
}
}
}
void CemeteryView::recordDeath(Personality personality, LifeStage stage, uint16_t ageHours) {
Preferences prefs(PREF_NS);
// Shift existing records down (newest at index 0)
for (int i = MAX_RECORDS - 1; i > 0; i--) {
char srcKey[16], dstKey[16];
snprintf(srcKey, sizeof(srcKey), "valid%d", i - 1);
snprintf(dstKey, sizeof(dstKey), "valid%d", i);
bool srcValid = prefs.getBool(srcKey, false);
prefs.putBool(dstKey, srcValid);
if (srcValid) {
snprintf(srcKey, sizeof(srcKey), "pers%d", i - 1);
snprintf(dstKey, sizeof(dstKey), "pers%d", i);
prefs.putInt32(dstKey, prefs.getInt32(srcKey, 0));
snprintf(srcKey, sizeof(srcKey), "stage%d", i - 1);
snprintf(dstKey, sizeof(dstKey), "stage%d", i);
prefs.putInt32(dstKey, prefs.getInt32(srcKey, 0));
snprintf(srcKey, sizeof(srcKey), "age%d", i - 1);
snprintf(dstKey, sizeof(dstKey), "age%d", i);
prefs.putInt32(dstKey, prefs.getInt32(srcKey, 0));
}
}
// Write new record at index 0
prefs.putBool("valid0", true);
prefs.putInt32("pers0", static_cast<int32_t>(personality));
prefs.putInt32("stage0", static_cast<int32_t>(stage));
prefs.putInt32("age0", static_cast<int32_t>(ageHours));
}
void CemeteryView::onStart(lv_obj_t* parentWidget, TamaTac* appInstance) {
parent = parentWidget;
app = appInstance;
lv_coord_t screenWidth = lv_display_get_horizontal_resolution(nullptr);
lv_coord_t screenHeight = lv_display_get_vertical_resolution(nullptr);
bool isSmall = (screenWidth < 280 || screenHeight < 180);
bool isXLarge = (screenWidth >= 600);
int padAll = isSmall ? 4 : (isXLarge ? 16 : 8);
int padRow = isSmall ? 4 : (isXLarge ? 12 : 6);
mainWrapper = lv_obj_create(parent);
lv_obj_set_size(mainWrapper, LV_PCT(100), LV_PCT(100));
lv_obj_set_style_pad_all(mainWrapper, padAll, 0);
lv_obj_set_style_pad_row(mainWrapper, padRow, 0);
lv_obj_set_style_bg_opa(mainWrapper, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(mainWrapper, 0, 0);
lv_obj_set_flex_flow(mainWrapper, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(mainWrapper, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
// Title
lv_obj_t* title = lv_label_create(mainWrapper);
lv_label_set_text(title, "Pet Cemetery");
lv_obj_set_style_text_color(title, lv_color_hex(0xFFFFFF), 0);
// Load records
PetRecord records[MAX_RECORDS];
loadRecords(records);
bool anyRecords = false;
for (int i = 0; i < MAX_RECORDS; i++) {
if (!records[i].valid) continue;
anyRecords = true;
lv_obj_t* row = lv_obj_create(mainWrapper);
lv_obj_set_size(row, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_set_style_pad_all(row, isSmall ? 4 : (isXLarge ? 12 : 6), 0);
lv_obj_set_style_bg_color(row, lv_color_hex(0x2a2a4e), 0);
lv_obj_set_style_border_width(row, 0, 0);
lv_obj_set_style_radius(row, isSmall ? 4 : (isXLarge ? 10 : 6), 0);
char text[80];
int days = records[i].ageHours / 24;
int hours = records[i].ageHours % 24;
snprintf(text, sizeof(text), "#%d %s %s %dd %dh",
i + 1,
personalityToString(records[i].personality),
lifeStageToString(records[i].stageReached),
days, hours);
lv_obj_t* label = lv_label_create(row);
lv_label_set_text(label, text);
lv_obj_set_style_text_color(label, lv_color_hex(0xCCCCCC), 0);
}
if (!anyRecords) {
lv_obj_t* emptyLabel = lv_label_create(mainWrapper);
lv_label_set_text(emptyLabel, "No records yet.");
lv_obj_set_style_text_color(emptyLabel, lv_palette_lighten(LV_PALETTE_GREY, 3), 0);
}
}
void CemeteryView::onStop() {
mainWrapper = nullptr;
parent = nullptr;
app = nullptr;
}
+40
View File
@@ -0,0 +1,40 @@
/**
* @file CemeteryView.h
* @brief Pet Cemetery / Hall of Fame view for TamaTac
*/
#pragma once
#include <lvgl.h>
#include <cstdint>
#include "PetStats.h"
class TamaTac;
// Record of a deceased pet
struct PetRecord {
Personality personality;
LifeStage stageReached;
uint16_t ageHours;
bool valid = false;
};
class CemeteryView {
public:
static constexpr int MAX_RECORDS = 5;
private:
TamaTac* app = nullptr;
lv_obj_t* parent = nullptr;
lv_obj_t* mainWrapper = nullptr;
public:
void onStart(lv_obj_t* parentWidget, TamaTac* appInstance);
void onStop();
// Record a pet death (called from TamaTac when pet dies)
static void recordDeath(Personality personality, LifeStage stage, uint16_t ageHours);
// Load all records
static void loadRecords(PetRecord records[MAX_RECORDS]);
};
+625
View File
@@ -0,0 +1,625 @@
/**
* @file MainView.cpp
* @brief Main pet view implementation
*/
#include "MainView.h"
#include "TamaTac.h"
#include <Tactility/kernel/Kernel.h>
#include <cstdio>
extern lv_color_t TamaTac_canvasBuffer[72 * 72];
extern lv_color_t TamaTac_iconBuffers[12][16 * 16];
void MainView::onStart(lv_obj_t* parentWidget, TamaTac* appInstance) {
parent = parentWidget;
app = appInstance;
// Detect screen size for responsive layout
lv_coord_t screenWidth = lv_display_get_horizontal_resolution(nullptr);
lv_coord_t screenHeight = lv_display_get_vertical_resolution(nullptr);
bool isSmall = (screenWidth < 280 || screenHeight < 180);
bool isXLarge = (screenWidth >= 600);
bool isLarge = !isXLarge && (screenWidth >= 400 && screenHeight >= 300);
// Scaled dimensions based on screen tier
int petAreaSize, statBarWidth, statBarHeight;
int btnWidth, btnHeight, padMain, padRow, poopHeight;
if (isSmall) {
petAreaSize = 56; petCanvasSize = 48; spriteScale = 2; // 24*2=48
statBarWidth = 85; statBarHeight = 5;
btnWidth = 54; btnHeight = 32;
padMain = 1; padRow = 1; poopHeight = 14;
} else if (isXLarge) {
petAreaSize = 136; petCanvasSize = 72; spriteScale = 3; // 24*3=72
statBarWidth = 300; statBarHeight = 10;
btnWidth = 120; btnHeight = 56;
padMain = 8; padRow = 6; poopHeight = 24;
} else if (isLarge) {
petAreaSize = 100; petCanvasSize = 72; spriteScale = 3;
statBarWidth = 200; statBarHeight = 8;
btnWidth = 90; btnHeight = 50;
padMain = 4; padRow = 4; poopHeight = 22;
} else {
// Medium (default)
petAreaSize = 76; petCanvasSize = 72; spriteScale = 3;
statBarWidth = 135; statBarHeight = 6;
btnWidth = 70; btnHeight = 42;
padMain = 1; padRow = 1; poopHeight = 16;
}
// Initialize animation state
animStartTime = tt::kernel::getMillis();
currentSpriteId = SPRITE_EGG_IDLE;
// Main content wrapper
mainWrapper = lv_obj_create(parent);
lv_obj_set_size(mainWrapper, LV_PCT(100), LV_PCT(100));
lv_obj_set_style_pad_all(mainWrapper, padMain, 0);
lv_obj_set_style_bg_opa(mainWrapper, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(mainWrapper, 0, 0);
lv_obj_set_flex_flow(mainWrapper, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(mainWrapper, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_remove_flag(mainWrapper, LV_OBJ_FLAG_SCROLLABLE);
// Pet and stats container (horizontal layout)
lv_obj_t* petStatsRow = lv_obj_create(mainWrapper);
lv_obj_set_size(petStatsRow, LV_PCT(98), LV_SIZE_CONTENT);
lv_obj_set_style_bg_opa(petStatsRow, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(petStatsRow, 0, 0);
lv_obj_set_style_pad_all(petStatsRow, 0, 0);
lv_obj_set_style_pad_left(petStatsRow, isSmall ? 2 : (isXLarge ? 16 : 8), 0);
lv_obj_set_flex_flow(petStatsRow, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(petStatsRow, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER);
// Pet column (left side)
lv_obj_t* petColumn = lv_obj_create(petStatsRow);
lv_obj_set_size(petColumn, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_set_style_bg_opa(petColumn, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(petColumn, 0, 0);
lv_obj_set_style_pad_all(petColumn, 0, 0);
lv_obj_set_style_pad_row(petColumn, isSmall ? 1 : (isXLarge ? 8 : 2), 0);
lv_obj_set_flex_flow(petColumn, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(petColumn, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
// Pet display area
petArea = lv_obj_create(petColumn);
lv_obj_set_size(petArea, petAreaSize, petAreaSize);
lv_obj_set_style_bg_color(petArea, lv_color_hex(0x333333), 0);
lv_obj_set_style_border_color(petArea, lv_color_hex(0x666666), 0);
lv_obj_set_style_border_width(petArea, isSmall ? 1 : (isXLarge ? 3 : 2), 0);
lv_obj_set_style_pad_all(petArea, 0, 0);
// Make pet area tappable for pet interaction
lv_obj_add_flag(petArea, LV_OBJ_FLAG_CLICKABLE);
lv_obj_add_event_cb(petArea, onPetTapped, LV_EVENT_CLICKED, app);
// Create canvas for sprite rendering
petCanvas = lv_canvas_create(petArea);
lv_canvas_set_buffer(petCanvas, TamaTac_canvasBuffer, petCanvasSize, petCanvasSize, LV_COLOR_FORMAT_NATIVE);
lv_obj_center(petCanvas);
// Poop container
poopContainer = lv_obj_create(petColumn);
lv_obj_set_size(poopContainer, petAreaSize, poopHeight);
lv_obj_set_style_bg_opa(poopContainer, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(poopContainer, 0, 0);
lv_obj_set_style_pad_all(poopContainer, 1, 0);
lv_obj_set_style_pad_column(poopContainer, isSmall ? 1 : (isXLarge ? 4 : 2), 0);
lv_obj_set_flex_flow(poopContainer, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(poopContainer, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_remove_flag(poopContainer, LV_OBJ_FLAG_SCROLLABLE);
// Create 3 poop icon canvases
for (int i = 0; i < 3; i++) {
poopIcons[i] = lv_canvas_create(poopContainer);
lv_canvas_set_buffer(poopIcons[i], TamaTac_iconBuffers[i], 16, 16, LV_COLOR_FORMAT_NATIVE);
lv_obj_add_flag(poopIcons[i], LV_OBJ_FLAG_HIDDEN);
}
// Stat bars container
lv_obj_t* statsContainer = lv_obj_create(petStatsRow);
lv_obj_set_size(statsContainer, LV_SIZE_CONTENT, petAreaSize);
lv_obj_set_style_bg_opa(statsContainer, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(statsContainer, 0, 0);
lv_obj_set_style_pad_all(statsContainer, padRow, 0);
lv_obj_set_style_pad_left(statsContainer, isSmall ? 4 : (isXLarge ? 16 : 8), 0);
lv_obj_set_style_pad_row(statsContainer, padRow, 0);
lv_obj_set_flex_flow(statsContainer, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(statsContainer, LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
lv_obj_set_flex_grow(statsContainer, 1);
lv_obj_remove_flag(statsContainer, LV_OBJ_FLAG_SCROLLABLE);
// Helper to create stat row
auto createStatRow = [&](lv_obj_t* parent, int iconBufferIdx, IconId iconId,
lv_obj_t** bar, lv_color_t barColor) {
lv_obj_t* row = lv_obj_create(parent);
lv_obj_set_size(row, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_set_style_bg_opa(row, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(row, 0, 0);
lv_obj_set_style_pad_all(row, 0, 0);
lv_obj_set_style_pad_column(row, isSmall ? 2 : (isXLarge ? 6 : 3), 0);
lv_obj_set_flex_flow(row, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(row, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_t* iconCanvas = lv_canvas_create(row);
lv_canvas_set_buffer(iconCanvas, TamaTac_iconBuffers[iconBufferIdx], 16, 16, LV_COLOR_FORMAT_NATIVE);
drawIcon(iconCanvas, iconId);
*bar = lv_bar_create(row);
lv_obj_set_size(*bar, statBarWidth, statBarHeight);
lv_bar_set_range(*bar, 0, 100);
lv_obj_set_style_bg_color(*bar, lv_color_hex(0x444444), LV_PART_MAIN);
lv_obj_set_style_bg_color(*bar, barColor, LV_PART_INDICATOR);
return iconCanvas;
};
statIcons[0] = createStatRow(statsContainer, 3, ICON_HUNGER, &hungerBar, lv_color_hex(0xFF9900));
statIcons[1] = createStatRow(statsContainer, 4, ICON_HAPPINESS, &happinessBar, lv_color_hex(0xFFCC00));
statIcons[2] = createStatRow(statsContainer, 5, ICON_HEALTH, &healthBar, lv_color_hex(0x00FF00));
statIcons[3] = createStatRow(statsContainer, 6, ICON_ENERGY, &energyBar, lv_color_hex(0x00CCFF));
// Status label
statusLabel = lv_label_create(mainWrapper);
lv_label_set_text(statusLabel, "Your pet is ready!");
lv_obj_set_style_text_align(statusLabel, LV_TEXT_ALIGN_CENTER, 0);
lv_obj_set_style_pad_top(statusLabel, 0, 0);
lv_obj_set_style_pad_bottom(statusLabel, 0, 0);
// Button container
lv_obj_t* btnContainer = lv_obj_create(mainWrapper);
lv_obj_set_width(btnContainer, LV_PCT(100));
lv_obj_set_height(btnContainer, LV_SIZE_CONTENT);
lv_obj_set_style_bg_opa(btnContainer, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(btnContainer, 0, 0);
lv_obj_set_style_pad_all(btnContainer, 0, 0);
lv_obj_set_style_pad_column(btnContainer, isSmall ? 3 : (isXLarge ? 16 : 6), 0);
lv_obj_set_style_pad_top(btnContainer, padRow, 0);
lv_obj_set_flex_flow(btnContainer, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(btnContainer, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_align(btnContainer, LV_ALIGN_BOTTOM_MID, 0, 0);
// Helper to create action button with icon
auto createActionBtn = [&](lv_obj_t** btn, const char* text, IconId iconId, int bufferIdx, lv_event_cb_t callback) {
*btn = lv_btn_create(btnContainer);
lv_obj_set_size(*btn, btnWidth, btnHeight);
lv_obj_set_flex_flow(*btn, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(*btn, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_set_style_pad_all(*btn, isSmall ? 1 : (isXLarge ? 4 : 2), 0);
lv_obj_set_style_pad_row(*btn, isSmall ? 1 : (isXLarge ? 4 : 2), 0);
// Get the actual button background color from the theme
lv_color_t btnBgColor = lv_theme_get_color_primary(*btn);
// Icon canvas with button background color
lv_obj_t* iconCanvas = lv_canvas_create(*btn);
lv_canvas_set_buffer(iconCanvas, TamaTac_iconBuffers[bufferIdx], 16, 16, LV_COLOR_FORMAT_NATIVE);
drawIconWithBg(iconCanvas, iconId, btnBgColor, lv_color_hex(0xFFFFFF));
// Label
if (!isSmall) {
lv_obj_t* label = lv_label_create(*btn);
lv_label_set_text(label, text);
lv_obj_set_style_text_font(label, lv_font_get_default(), 0);
}
lv_obj_add_event_cb(*btn, callback, LV_EVENT_CLICKED, app);
};
createActionBtn(&feedBtn, "Feed", ICON_FEED, 7, onFeedClicked);
createActionBtn(&playBtn, "Play", ICON_PLAY, 8, onPlayClicked);
createActionBtn(&medicineBtn, "Med", ICON_MEDICINE, 9, onMedicineClicked);
createActionBtn(&sleepBtn, "Sleep", ICON_SLEEP, 10, onSleepClicked);
// Refresh timer for periodic UI updates (day/night, random events, etc.)
refreshTimer = lv_timer_create(onRefreshTimer, 5000, this);
// Animation timer (~5fps for smooth frame cycling)
animTimer = lv_timer_create(onAnimTimer, 200, this);
}
void MainView::onStop() {
if (refreshTimer) {
lv_timer_del(refreshTimer);
refreshTimer = nullptr;
}
if (animTimer) {
lv_timer_del(animTimer);
animTimer = nullptr;
}
mainWrapper = nullptr;
statusLabel = nullptr;
petArea = nullptr;
petCanvas = nullptr;
poopContainer = nullptr;
for (int i = 0; i < 3; i++) {
poopIcons[i] = nullptr;
}
for (int i = 0; i < 4; i++) {
statIcons[i] = nullptr;
}
hungerBar = nullptr;
happinessBar = nullptr;
healthBar = nullptr;
energyBar = nullptr;
feedBtn = nullptr;
playBtn = nullptr;
medicineBtn = nullptr;
sleepBtn = nullptr;
parent = nullptr;
app = nullptr;
}
void MainView::updateUI(PetLogic* petLogic, LifeStage& lastKnownStage) {
updateStatBars(petLogic);
updatePetDisplay(petLogic, lastKnownStage);
}
void MainView::updateStatBars(PetLogic* petLogic) {
if (petLogic == nullptr) return;
const PetStats& stats = petLogic->getStats();
if (hungerBar) lv_bar_set_value(hungerBar, stats.hunger, LV_ANIM_OFF);
if (happinessBar) lv_bar_set_value(happinessBar, stats.happiness, LV_ANIM_OFF);
if (healthBar) lv_bar_set_value(healthBar, stats.health, LV_ANIM_OFF);
if (energyBar) lv_bar_set_value(energyBar, stats.energy, LV_ANIM_OFF);
}
void MainView::updatePetDisplay(PetLogic* petLogic, LifeStage& lastKnownStage) {
if (petLogic == nullptr) return;
const PetStats& stats = petLogic->getStats();
// Check for evolution (Ghost is death, not evolution)
if (stats.stage != lastKnownStage && statusLabel != nullptr) {
lastKnownStage = stats.stage;
if (stats.stage == LifeStage::Ghost) {
lv_label_set_text(statusLabel, LV_SYMBOL_WARNING " Your pet has died...");
} else {
char msg[64];
snprintf(msg, sizeof(msg), LV_SYMBOL_UP " Evolved to %s!", lifeStageToString(stats.stage));
lv_label_set_text(statusLabel, msg);
// Trigger evolution flash effect (400ms white flash)
evolutionFlashUntil = tt::kernel::getMillis() + 400;
}
}
// Update day/night visual
DayPhase phase = petLogic->getDayPhase();
currentDayPhase = phase;
if (petArea) {
lv_color_t bg = (phase == DayPhase::Night) ? lv_color_hex(0x1a1a2e) : lv_color_hex(0x333333);
lv_obj_set_style_bg_color(petArea, bg, 0);
}
// Update current sprite (animation timer will handle actual drawing)
SpriteId newSprite = getSpriteForCurrentState(stats);
if (newSprite != currentSpriteId) {
currentSpriteId = newSprite;
animStartTime = tt::kernel::getMillis();
}
drawSprite(currentSpriteId, &stats);
// Update poop display
for (int i = 0; i < 3; i++) {
if (poopIcons[i]) {
if (i < stats.poopCount) {
drawIcon(poopIcons[i], ICON_POOP);
lv_obj_clear_flag(poopIcons[i], LV_OBJ_FLAG_HIDDEN);
} else {
lv_obj_add_flag(poopIcons[i], LV_OBJ_FLAG_HIDDEN);
}
}
}
}
void MainView::setStatusText(const char* text) {
if (statusLabel) {
lv_label_set_text(statusLabel, text);
}
}
SpriteId MainView::getSpriteForCurrentState(const PetStats& stats) const {
if (stats.isDead) {
return SPRITE_GHOST;
}
// Egg always shows egg — no action/mood sprite overrides
if (stats.stage == LifeStage::Egg) {
return SPRITE_EGG_IDLE;
}
switch (stats.currentAnim) {
case AnimState::Eating: return SPRITE_EATING;
case AnimState::Playing: return SPRITE_PLAYING;
case AnimState::Sleeping: return SPRITE_SLEEPING;
case AnimState::Sick: return SPRITE_SICK;
case AnimState::Sad: return SPRITE_SAD;
default: break;
}
if (stats.isSick) {
return SPRITE_SICK;
}
if (stats.isAsleep) {
return SPRITE_SLEEPING;
}
if (stats.happiness >= 70) {
return SPRITE_HAPPY;
} else if (stats.happiness < 30) {
return SPRITE_SAD;
}
switch (stats.stage) {
case LifeStage::Baby: return SPRITE_BABY_IDLE;
case LifeStage::Teen: return SPRITE_TEEN_IDLE;
case LifeStage::Adult: return SPRITE_ADULT_IDLE;
case LifeStage::Elder: return SPRITE_ELDER_IDLE;
case LifeStage::Ghost: return SPRITE_GHOST;
default: break;
}
return SPRITE_EGG_IDLE;
}
void MainView::drawSprite(SpriteId spriteId, const PetStats* stats) {
if (petCanvas == nullptr) return;
uint32_t now = tt::kernel::getMillis();
int canvasSize = SPRITE_WIDTH * spriteScale;
if (canvasSize > petCanvasSize) return;
// Evolution flash: fill entire canvas with white
if (evolutionFlashUntil > 0 && now < evolutionFlashUntil) {
lv_canvas_fill_bg(petCanvas, lv_color_hex(0xFFFFFF), LV_OPA_COVER);
return;
} else if (evolutionFlashUntil > 0) {
evolutionFlashUntil = 0;
}
// Fill background
lv_color_t bgColor = (currentDayPhase == DayPhase::Night) ? lv_color_hex(0x1a1a2e) : lv_color_hex(0x333333);
lv_canvas_fill_bg(petCanvas, bgColor, LV_OPA_COVER);
// Night stars: draw twinkly dots in the background
if (currentDayPhase == DayPhase::Night) {
// Update star seed every 2 seconds for twinkling effect
uint32_t starPhase = now / 2000;
uint32_t seed = starPhase * 7919; // Simple deterministic hash
for (int i = 0; i < 6; i++) {
seed = seed * 1103515245 + 12345; // LCG
int sx = (seed >> 16) % canvasSize;
seed = seed * 1103515245 + 12345;
int sy = (seed >> 16) % (canvasSize / 3); // Stars only in top third
// Alternate bright/dim stars
lv_color_t starColor = (i % 2 == 0) ? lv_color_hex(0xFFFFFF) : lv_color_hex(0x888899);
lv_canvas_set_px(petCanvas, sx, sy, starColor, LV_OPA_COVER);
}
}
// Determine current animation frame
const AnimatedSprite& anim = getAnimSprite(spriteId);
int frameIdx = 0;
if (anim.frameCount > 1 && anim.frameDelayMs > 0) {
uint32_t elapsed = now - animStartTime;
if (anim.loop) {
frameIdx = (elapsed / anim.frameDelayMs) % anim.frameCount;
} else {
frameIdx = elapsed / anim.frameDelayMs;
if (frameIdx >= anim.frameCount) frameIdx = anim.frameCount - 1;
}
}
// Render RGB565 sprite with transparency and scaling
const uint16_t* pixelData = anim.frames[frameIdx].data;
for (int y = 0; y < SPRITE_HEIGHT; y++) {
for (int x = 0; x < SPRITE_WIDTH; x++) {
uint16_t pixel = pixelData[y * SPRITE_WIDTH + x];
if (pixel == SPRITE_TRANSPARENT) continue;
uint8_t r = (pixel >> 11) << 3;
uint8_t g = ((pixel >> 5) & 0x3F) << 2;
uint8_t b = (pixel & 0x1F) << 3;
lv_color_t color = lv_color_make(r, g, b);
for (int dy = 0; dy < spriteScale; dy++) {
for (int dx = 0; dx < spriteScale; dx++) {
lv_canvas_set_px(petCanvas,
x * spriteScale + dx,
y * spriteScale + dy,
color, LV_OPA_COVER);
}
}
}
}
// Draw overlays (Z's, mood indicator)
drawOverlays(spriteId, stats);
}
void MainView::drawOverlays(SpriteId spriteId, const PetStats* stats) {
if (petCanvas == nullptr) return;
int canvasSize = SPRITE_WIDTH * spriteScale;
uint32_t now = tt::kernel::getMillis();
lv_color_t white = lv_color_hex(0xFFFFFF);
lv_color_t gray = lv_color_hex(0xAAAAAA);
// Floating Z's during sleep
if (spriteId == SPRITE_SLEEPING) {
// Two Z's at different positions, bobbing up and down
int phase = (now / 500) % 4; // 4-step bob cycle
int bobOffset = (phase < 2) ? phase : (4 - phase); // 0,1,2,1 pattern
// Large Z (top-right area)
int zx = canvasSize - 8 * spriteScale / 3;
int zy = 2 + bobOffset;
if (zx >= 0 && zx + 3 < canvasSize && zy + 3 < canvasSize) {
// Z shape: top bar, diagonal, bottom bar
lv_canvas_set_px(petCanvas, zx, zy, white, LV_OPA_COVER);
lv_canvas_set_px(petCanvas, zx + 1, zy, white, LV_OPA_COVER);
lv_canvas_set_px(petCanvas, zx + 2, zy, white, LV_OPA_COVER);
lv_canvas_set_px(petCanvas, zx + 1, zy + 1, white, LV_OPA_COVER);
lv_canvas_set_px(petCanvas, zx, zy + 2, white, LV_OPA_COVER);
lv_canvas_set_px(petCanvas, zx + 1, zy + 2, white, LV_OPA_COVER);
lv_canvas_set_px(petCanvas, zx + 2, zy + 2, white, LV_OPA_COVER);
}
// Small z (offset from large Z, staggered bob)
int zx2 = zx - 5;
int bobOffset2 = ((phase + 2) % 4 < 2) ? 0 : 1;
int zy2 = zy + 4 + bobOffset2;
if (zx2 >= 0 && zx2 + 2 < canvasSize && zy2 >= 0 && zy2 + 2 < canvasSize) {
lv_canvas_set_px(petCanvas, zx2, zy2, gray, LV_OPA_COVER);
lv_canvas_set_px(petCanvas, zx2 + 1, zy2, gray, LV_OPA_COVER);
lv_canvas_set_px(petCanvas, zx2, zy2 + 1, gray, LV_OPA_COVER);
lv_canvas_set_px(petCanvas, zx2 + 1, zy2 + 1, gray, LV_OPA_COVER);
}
}
// Mood indicator: small colored dot in bottom-right corner
if (stats != nullptr && !stats->isDead) {
lv_color_t moodColor;
bool showMood = true;
if (stats->isSick) {
moodColor = lv_color_hex(0xFF0000); // Red for sick
} else if (stats->hunger < 30 || stats->happiness < 30 || stats->energy < 30) {
moodColor = lv_color_hex(0xFF8800); // Orange for warning
} else if (stats->hunger >= 70 && stats->happiness >= 70 && stats->health >= 70 && stats->energy >= 70) {
moodColor = lv_color_hex(0x00FF00); // Green for happy
} else {
showMood = false; // Neutral — no indicator
}
if (showMood) {
// 2x2 dot in bottom-right corner
int mx = canvasSize - 3;
int my = canvasSize - 3;
for (int dy = 0; dy < 2; dy++) {
for (int dx = 0; dx < 2; dx++) {
lv_canvas_set_px(petCanvas, mx + dx, my + dy, moodColor, LV_OPA_COVER);
}
}
}
}
}
void MainView::drawIcon(lv_obj_t* canvas, IconId iconId) {
drawIconWithBg(canvas, iconId, lv_color_hex(0x333333), lv_color_hex(0xFFFFFF));
}
void MainView::drawIconWithBg(lv_obj_t* canvas, IconId iconId, lv_color_t bgColor, lv_color_t fgColor) {
if (canvas == nullptr) return;
const Icon& icon = getIcon(iconId);
const uint8_t* data = icon.data;
if (icon.width > 8 || icon.height > 8) return;
lv_canvas_fill_bg(canvas, bgColor, LV_OPA_COVER);
const int scale = 2;
const int width = icon.width;
const int height = icon.height;
for (int y = 0; y < height; y++) {
uint8_t row = data[y];
for (int x = 0; x < width; x++) {
bool pixelOn = (row >> (7 - x)) & 1;
if (pixelOn) {
for (int dy = 0; dy < scale; dy++) {
for (int dx = 0; dx < scale; dx++) {
lv_canvas_set_px(canvas, x * scale + dx, y * scale + dy, fgColor, LV_OPA_COVER);
}
}
}
}
}
}
void MainView::onAnimTimer(lv_timer_t* timer) {
MainView* view = static_cast<MainView*>(lv_timer_get_user_data(timer));
if (view == nullptr || view->petCanvas == nullptr) return;
// Pick up deferred reset quickly (200ms vs 5s refresh timer)
if (TamaTac::pendingResetUI) {
TamaTac::pendingResetUI = false;
PetLogic* petLogic = TamaTac::petLogic;
if (petLogic) {
view->updateUI(petLogic, TamaTac::lastKnownStage);
}
return;
}
const PetStats* stats = TamaTac::petLogic ? &TamaTac::petLogic->getStats() : nullptr;
view->drawSprite(view->currentSpriteId, stats);
}
void MainView::onRefreshTimer(lv_timer_t* timer) {
MainView* view = static_cast<MainView*>(lv_timer_get_user_data(timer));
if (view == nullptr || view->app == nullptr) return;
PetLogic* petLogic = TamaTac::petLogic;
if (petLogic == nullptr) return;
view->updateUI(petLogic, TamaTac::lastKnownStage);
// Display random event messages
RandomEvent event = petLogic->getLastEvent();
if (event != RandomEvent::None && view->statusLabel) {
const char* msg = nullptr;
switch (event) {
case RandomEvent::FoundTreat: msg = "Found a treat!"; break;
case RandomEvent::MadeFriend: msg = "Made a friend!"; break;
case RandomEvent::CaughtCold: msg = "Caught a cold!"; break;
case RandomEvent::GotMuddy: msg = "Got muddy!"; break;
case RandomEvent::HadNap: msg = "Had a nap!"; break;
case RandomEvent::SunnyDay: msg = "Sunny day!"; break;
default: break;
}
if (msg) {
lv_label_set_text(view->statusLabel, msg);
}
petLogic->clearLastEvent();
}
}
// Event handlers
void MainView::onFeedClicked(lv_event_t* e) {
TamaTac* app = static_cast<TamaTac*>(lv_event_get_user_data(e));
if (app == nullptr) return;
app->handleFeedAction();
}
void MainView::onPlayClicked(lv_event_t* e) {
TamaTac* app = static_cast<TamaTac*>(lv_event_get_user_data(e));
if (app == nullptr) return;
app->handlePlayAction();
}
void MainView::onMedicineClicked(lv_event_t* e) {
TamaTac* app = static_cast<TamaTac*>(lv_event_get_user_data(e));
if (app == nullptr) return;
app->handleMedicineAction();
}
void MainView::onSleepClicked(lv_event_t* e) {
TamaTac* app = static_cast<TamaTac*>(lv_event_get_user_data(e));
if (app == nullptr) return;
app->handleSleepAction();
}
void MainView::onPetTapped(lv_event_t* e) {
TamaTac* app = static_cast<TamaTac*>(lv_event_get_user_data(e));
if (app == nullptr) return;
app->handlePetTap();
}
+76
View File
@@ -0,0 +1,76 @@
/**
* @file MainView.h
* @brief Main pet view for TamaTac
*/
#pragma once
#include <lvgl.h>
#include "PetLogic.h"
#include "Sprites.h"
class TamaTac;
class MainView {
private:
TamaTac* app = nullptr;
lv_obj_t* parent = nullptr;
// UI elements
lv_obj_t* mainWrapper = nullptr;
lv_obj_t* statusLabel = nullptr;
lv_obj_t* petArea = nullptr;
lv_obj_t* petCanvas = nullptr;
lv_obj_t* poopContainer = nullptr;
lv_obj_t* poopIcons[3] = {nullptr, nullptr, nullptr};
lv_obj_t* statIcons[4] = {nullptr, nullptr, nullptr, nullptr};
lv_obj_t* hungerBar = nullptr;
lv_obj_t* happinessBar = nullptr;
lv_obj_t* healthBar = nullptr;
lv_obj_t* energyBar = nullptr;
lv_obj_t* feedBtn = nullptr;
lv_obj_t* playBtn = nullptr;
lv_obj_t* medicineBtn = nullptr;
lv_obj_t* sleepBtn = nullptr;
// Refresh timer for periodic UI updates
lv_timer_t* refreshTimer = nullptr;
DayPhase currentDayPhase = DayPhase::Day;
// Animation
lv_timer_t* animTimer = nullptr;
uint32_t animStartTime = 0;
SpriteId currentSpriteId = SPRITE_EGG_IDLE;
// Polish effects
uint32_t evolutionFlashUntil = 0; // Millis timestamp when flash ends (0 = no flash)
uint32_t starSeed = 0; // Seed for deterministic star positions (changes slowly)
// Scaling
int spriteScale = 3;
int petCanvasSize = 72;
public:
void onStart(lv_obj_t* parentWidget, TamaTac* appInstance);
void onStop();
void updateUI(PetLogic* petLogic, LifeStage& lastKnownStage);
void updateStatBars(PetLogic* petLogic);
void updatePetDisplay(PetLogic* petLogic, LifeStage& lastKnownStage);
void setStatusText(const char* text);
private:
void drawSprite(SpriteId spriteId, const PetStats* stats = nullptr);
void drawOverlays(SpriteId spriteId, const PetStats* stats);
void drawIcon(lv_obj_t* canvas, IconId iconId);
void drawIconWithBg(lv_obj_t* canvas, IconId iconId, lv_color_t bgColor, lv_color_t fgColor);
SpriteId getSpriteForCurrentState(const PetStats& stats) const;
// Static event handlers
static void onFeedClicked(lv_event_t* e);
static void onPlayClicked(lv_event_t* e);
static void onMedicineClicked(lv_event_t* e);
static void onSleepClicked(lv_event_t* e);
static void onPetTapped(lv_event_t* e);
static void onRefreshTimer(lv_timer_t* timer);
static void onAnimTimer(lv_timer_t* timer);
};
+87
View File
@@ -0,0 +1,87 @@
/**
* @file MenuView.cpp
* @brief Menu view implementation
*/
#include "MenuView.h"
#include "TamaTac.h"
void MenuView::onStart(lv_obj_t* parentWidget, TamaTac* appInstance) {
parent = parentWidget;
app = appInstance;
// Detect screen size for responsive layout
// Use display resolution for reliable sizing (parent may not be laid out yet on first load)
lv_coord_t screenWidth = lv_display_get_horizontal_resolution(nullptr);
lv_coord_t screenHeight = lv_display_get_vertical_resolution(nullptr);
bool isSmall = (screenWidth < 280 || screenHeight < 180);
bool isXLarge = (screenWidth >= 600);
// Main wrapper
mainWrapper = lv_obj_create(parent);
lv_obj_set_size(mainWrapper, LV_PCT(100), LV_PCT(100));
lv_obj_set_style_pad_all(mainWrapper, isSmall ? 4 : (isXLarge ? 16 : 8), 0);
lv_obj_set_style_bg_opa(mainWrapper, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(mainWrapper, 0, 0);
lv_obj_set_flex_flow(mainWrapper, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(mainWrapper, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_remove_flag(mainWrapper, LV_OBJ_FLAG_SCROLLABLE);
// Menu list
menuList = lv_list_create(mainWrapper);
lv_obj_set_size(menuList, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_set_style_pad_all(menuList, isSmall ? 2 : (isXLarge ? 8 : 4), 0);
lv_obj_set_style_bg_color(menuList, lv_color_hex(0x1a1a2e), 0);
lv_obj_set_style_border_width(menuList, isXLarge ? 2 : 1, 0);
lv_obj_set_style_border_color(menuList, lv_color_hex(0x3a3a5e), 0);
lv_obj_set_style_radius(menuList, isSmall ? 4 : (isXLarge ? 12 : 8), 0);
addStyledListBtn(LV_SYMBOL_LIST, "Stats", onStatsClicked);
addStyledListBtn(LV_SYMBOL_SETTINGS, "Settings", onSettingsClicked);
addStyledListBtn(LV_SYMBOL_EYE_OPEN, "Cemetery", onCemeteryClicked);
addStyledListBtn(LV_SYMBOL_OK, "Achievements", onAchievementsClicked);
}
lv_obj_t* MenuView::addStyledListBtn(const char* icon, const char* text, lv_event_cb_t cb) {
lv_obj_t* btn = lv_list_add_btn(menuList, icon, text);
lv_obj_add_event_cb(btn, cb, LV_EVENT_CLICKED, this);
lv_obj_set_style_bg_color(btn, lv_color_hex(0x2a2a4e), LV_STATE_DEFAULT);
lv_obj_set_style_bg_color(btn, lv_color_hex(0x4a4a7e), LV_STATE_PRESSED);
lv_obj_set_style_text_color(btn, lv_color_hex(0xFFFFFF), 0);
return btn;
}
void MenuView::onStop() {
mainWrapper = nullptr;
menuList = nullptr;
parent = nullptr;
app = nullptr;
}
void MenuView::onStatsClicked(lv_event_t* e) {
MenuView* view = static_cast<MenuView*>(lv_event_get_user_data(e));
if (view && view->app) {
view->app->showStatsView();
}
}
void MenuView::onSettingsClicked(lv_event_t* e) {
MenuView* view = static_cast<MenuView*>(lv_event_get_user_data(e));
if (view && view->app) {
view->app->showSettingsView();
}
}
void MenuView::onCemeteryClicked(lv_event_t* e) {
MenuView* view = static_cast<MenuView*>(lv_event_get_user_data(e));
if (view && view->app) {
view->app->showCemeteryView();
}
}
void MenuView::onAchievementsClicked(lv_event_t* e) {
MenuView* view = static_cast<MenuView*>(lv_event_get_user_data(e));
if (view && view->app) {
view->app->showAchievementsView();
}
}
+38
View File
@@ -0,0 +1,38 @@
/**
* @file MenuView.h
* @brief Menu view for TamaTac navigation
*/
#pragma once
#include <lvgl.h>
class TamaTac;
class MenuView {
private:
TamaTac* app = nullptr;
lv_obj_t* parent = nullptr;
// UI elements
lv_obj_t* mainWrapper = nullptr;
lv_obj_t* menuList = nullptr;
public:
MenuView() = default;
~MenuView() = default;
MenuView(const MenuView&) = delete;
MenuView& operator=(const MenuView&) = delete;
void onStart(lv_obj_t* parentWidget, TamaTac* appInstance);
void onStop();
lv_obj_t* addStyledListBtn(const char* icon, const char* text, lv_event_cb_t cb);
private:
// Static event handlers
static void onStatsClicked(lv_event_t* e);
static void onSettingsClicked(lv_event_t* e);
static void onCemeteryClicked(lv_event_t* e);
static void onAchievementsClicked(lv_event_t* e);
};
+302
View File
@@ -0,0 +1,302 @@
/**
* @file PatternGame.cpp
* @brief Simon Says mini-game implementation
*/
#include "PatternGame.h"
#include "TamaTac.h"
#include "SfxEngine.h"
#include <cstdlib>
#include <cstdio>
void PatternGame::onStart(lv_obj_t* parent, TamaTac* appInstance) {
app = appInstance;
// Screen size detection
lv_coord_t screenWidth = lv_display_get_horizontal_resolution(nullptr);
lv_coord_t screenHeight = lv_display_get_vertical_resolution(nullptr);
bool isSmall = (screenWidth < 280 || screenHeight < 180);
bool isXLarge = (screenWidth >= 600);
bool isLarge = !isXLarge && (screenWidth >= 400 && screenHeight >= 300);
// Scaled dimensions
int btnSize = isSmall ? 50 : (isXLarge ? 120 : (isLarge ? 90 : 70));
int gap = isSmall ? 4 : (isXLarge ? 12 : (isLarge ? 8 : 6));
int pad = isSmall ? 4 : (isXLarge ? 16 : 8);
int radius = isSmall ? 6 : (isXLarge ? 16 : 10);
// Main wrapper
lv_obj_t* wrapper = lv_obj_create(parent);
lv_obj_set_size(wrapper, LV_PCT(100), LV_PCT(100));
lv_obj_set_style_pad_all(wrapper, pad, 0);
lv_obj_set_style_bg_opa(wrapper, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(wrapper, 0, 0);
lv_obj_set_flex_flow(wrapper, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(wrapper, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_set_style_pad_row(wrapper, gap, 0);
lv_obj_remove_flag(wrapper, LV_OBJ_FLAG_SCROLLABLE);
// Status label
statusLabel = lv_label_create(wrapper);
lv_label_set_text(statusLabel, "Get ready...");
lv_obj_set_style_text_align(statusLabel, LV_TEXT_ALIGN_CENTER, 0);
// 2x2 button grid
lv_obj_t* grid = lv_obj_create(wrapper);
int gridSize = btnSize * 2 + gap * 3;
lv_obj_set_size(grid, gridSize, gridSize);
lv_obj_set_style_pad_all(grid, gap, 0);
lv_obj_set_style_pad_row(grid, gap, 0);
lv_obj_set_style_pad_column(grid, gap, 0);
lv_obj_set_style_bg_color(grid, lv_color_hex(0x1a1a2e), 0);
lv_obj_set_style_border_width(grid, 0, 0);
lv_obj_set_style_radius(grid, radius, 0);
lv_obj_set_flex_flow(grid, LV_FLEX_FLOW_ROW_WRAP);
lv_obj_set_flex_align(grid, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_remove_flag(grid, LV_OBJ_FLAG_SCROLLABLE);
// Create 4 game buttons
for (int i = 0; i < 4; i++) {
buttons[i] = lv_btn_create(grid);
lv_obj_set_size(buttons[i], btnSize, btnSize);
lv_obj_set_style_bg_color(buttons[i], lv_color_hex(DIM_COLORS[i]), 0);
lv_obj_set_style_bg_color(buttons[i], lv_color_hex(BRIGHT_COLORS[i]), LV_STATE_PRESSED);
lv_obj_set_style_radius(buttons[i], radius, 0);
lv_obj_set_style_border_width(buttons[i], 0, 0);
lv_obj_set_style_shadow_width(buttons[i], 0, 0);
lv_obj_add_event_cb(buttons[i], onButtonClicked, LV_EVENT_CLICKED, this);
}
// Initialize game
round = 0;
patternLength = START_LENGTH;
acceptingInput = false;
generatePattern();
startRound();
}
void PatternGame::onStop() {
clearTimers();
statusLabel = nullptr;
for (int i = 0; i < 4; i++) buttons[i] = nullptr;
app = nullptr;
}
void PatternGame::clearTimers() {
if (sequenceTimer) {
lv_timer_del(sequenceTimer);
sequenceTimer = nullptr;
}
if (delayTimer) {
lv_timer_del(delayTimer);
delayTimer = nullptr;
}
}
void PatternGame::generatePattern() {
for (int i = 0; i < MAX_PATTERN; i++) {
pattern[i] = rand() % 4;
}
}
void PatternGame::startRound() {
acceptingInput = false;
dimAllButtons();
char msg[32];
snprintf(msg, sizeof(msg), "Round %d - Watch!", round + 1);
if (statusLabel) lv_label_set_text(statusLabel, msg);
// Delay before showing pattern
pendingAction = DelayAction::StartSequence;
scheduleDelay(800);
}
void PatternGame::beginSequenceDisplay() {
showIndex = 0;
showPhase = false;
sequenceTimer = lv_timer_create(onSequenceTick, 350, this);
}
void PatternGame::startInputPhase() {
acceptingInput = true;
inputIndex = 0;
if (statusLabel) lv_label_set_text(statusLabel, "Your turn!");
}
void PatternGame::scheduleDelay(uint32_t ms) {
if (delayTimer) {
lv_timer_del(delayTimer);
delayTimer = nullptr;
}
delayTimer = lv_timer_create(onDelayDone, ms, this);
lv_timer_set_repeat_count(delayTimer, 1);
}
//==============================================================================
// Timer Callbacks
//==============================================================================
void PatternGame::onSequenceTick(lv_timer_t* timer) {
auto* self = static_cast<PatternGame*>(lv_timer_get_user_data(timer));
if (self->showPhase) {
// Was highlighting → dim it
self->dimButton(self->pattern[self->showIndex]);
self->showIndex++;
self->showPhase = false;
// Check if all shown
if (self->showIndex >= self->patternLength) {
lv_timer_del(self->sequenceTimer);
self->sequenceTimer = nullptr;
self->startInputPhase();
return;
}
// Short gap before next highlight
lv_timer_set_period(self->sequenceTimer, 200);
} else {
// Gap done → highlight next button
self->highlightButton(self->pattern[self->showIndex]);
self->showPhase = true;
// Play blip for each flash
SfxEngine* se = TamaTac::getSfxEngine();
if (se) se->play(SfxId::Blip);
// Longer highlight duration
lv_timer_set_period(self->sequenceTimer, 400);
}
}
void PatternGame::onDelayDone(lv_timer_t* timer) {
auto* self = static_cast<PatternGame*>(lv_timer_get_user_data(timer));
self->delayTimer = nullptr;
switch (self->pendingAction) {
case DelayAction::StartSequence:
self->beginSequenceDisplay();
break;
case DelayAction::NextRound:
self->startRound();
break;
case DelayAction::EndGame:
self->returnToMain(self->gameWon);
break;
}
}
//==============================================================================
// Input Handling
//==============================================================================
void PatternGame::onButtonClicked(lv_event_t* e) {
auto* self = static_cast<PatternGame*>(lv_event_get_user_data(e));
if (!self->acceptingInput) return;
lv_obj_t* target = lv_event_get_target_obj(e);
for (int i = 0; i < 4; i++) {
if (target == self->buttons[i]) {
self->handleInput(i);
return;
}
}
}
void PatternGame::handleInput(int buttonIndex) {
SfxEngine* se = TamaTac::getSfxEngine();
if (buttonIndex == pattern[inputIndex]) {
// Correct!
if (se) se->play(SfxId::Blip);
inputIndex++;
if (inputIndex >= patternLength) {
// Completed the full pattern
acceptingInput = false;
roundWin();
}
} else {
// Wrong!
acceptingInput = false;
gameLose();
}
}
void PatternGame::roundWin() {
round++;
SfxEngine* se = TamaTac::getSfxEngine();
if (se) se->play(SfxId::Confirm);
if (round >= MAX_ROUNDS) {
gameWin();
return;
}
// Show success message, then start next round
char msg[48];
snprintf(msg, sizeof(msg), "Correct! Round %d next...", round + 1);
if (statusLabel) lv_label_set_text(statusLabel, msg);
patternLength++;
if (patternLength > MAX_PATTERN) patternLength = MAX_PATTERN;
pendingAction = DelayAction::NextRound;
scheduleDelay(1200);
}
void PatternGame::gameWin() {
if (statusLabel) lv_label_set_text(statusLabel, LV_SYMBOL_OK " You win!");
dimAllButtons();
SfxEngine* se = TamaTac::getSfxEngine();
if (se) se->play(SfxId::Success);
gameWon = true;
pendingAction = DelayAction::EndGame;
scheduleDelay(1500);
}
void PatternGame::gameLose() {
char msg[48];
snprintf(msg, sizeof(msg), LV_SYMBOL_CLOSE " Wrong! Rounds: %d/%d", round, MAX_ROUNDS);
if (statusLabel) lv_label_set_text(statusLabel, msg);
dimAllButtons();
SfxEngine* se = TamaTac::getSfxEngine();
if (se) se->play(SfxId::Error);
gameWon = false;
pendingAction = DelayAction::EndGame;
scheduleDelay(1500);
}
void PatternGame::returnToMain(bool won) {
if (app) {
app->onPatternGameComplete(round, won);
}
}
//==============================================================================
// Visual Helpers
//==============================================================================
void PatternGame::highlightButton(int index) {
if (index >= 0 && index < 4 && buttons[index]) {
lv_obj_set_style_bg_color(buttons[index], lv_color_hex(BRIGHT_COLORS[index]), 0);
}
}
void PatternGame::dimButton(int index) {
if (index >= 0 && index < 4 && buttons[index]) {
lv_obj_set_style_bg_color(buttons[index], lv_color_hex(DIM_COLORS[index]), 0);
}
}
void PatternGame::dimAllButtons() {
for (int i = 0; i < 4; i++) {
dimButton(i);
}
}
+74
View File
@@ -0,0 +1,74 @@
/**
* @file PatternGame.h
* @brief Simon Says mini-game for TamaTac Play action
*/
#pragma once
#include <lvgl.h>
#include <cstdint>
class TamaTac;
class PatternGame {
private:
TamaTac* app = nullptr;
// UI elements
lv_obj_t* statusLabel = nullptr;
lv_obj_t* buttons[4] = {};
lv_timer_t* sequenceTimer = nullptr;
lv_timer_t* delayTimer = nullptr;
// Game constants
static constexpr int MAX_PATTERN = 8;
static constexpr int START_LENGTH = 3;
// Button colors
static constexpr uint32_t BRIGHT_COLORS[4] = {0xFF4444, 0x4488FF, 0x44DD44, 0xFFDD44};
static constexpr uint32_t DIM_COLORS[4] = {0x661818, 0x182860, 0x186018, 0x605818};
// Game state
uint8_t pattern[MAX_PATTERN] = {};
int patternLength = START_LENGTH;
int showIndex = 0;
bool showPhase = false;
int inputIndex = 0;
int round = 0;
bool acceptingInput = false;
// Static callbacks
static void onButtonClicked(lv_event_t* e);
static void onSequenceTick(lv_timer_t* timer);
static void onDelayDone(lv_timer_t* timer);
// Game logic
void generatePattern();
void startRound();
void beginSequenceDisplay();
void startInputPhase();
void handleInput(int buttonIndex);
void roundWin();
void gameWin();
void gameLose();
void returnToMain(bool won);
// Visual helpers
void highlightButton(int index);
void dimButton(int index);
void dimAllButtons();
// Timer helpers
void clearTimers();
void scheduleDelay(uint32_t ms);
// Delay action tracking
enum class DelayAction { StartSequence, NextRound, EndGame };
DelayAction pendingAction = DelayAction::StartSequence;
bool gameWon = false;
public:
static constexpr int MAX_ROUNDS = 3;
void onStart(lv_obj_t* parent, TamaTac* appInstance);
void onStop();
};
+496
View File
@@ -0,0 +1,496 @@
/**
* @file PetLogic.cpp
* @brief Game logic implementation for TamaTac
*/
#include "PetLogic.h"
#include <TactilityCpp/Preferences.h>
#include <cstdlib>
#include <algorithm>
// Static member initialization (2 = normal 1x speed)
uint8_t PetLogic::decayMultiplier = 2;
void PetLogic::setDecaySpeed(uint8_t speed) {
// speed: 0=slow, 1=normal, 2=fast
// multiplier: 1=0.5x, 2=1x, 4=2x
switch (speed) {
case 0: decayMultiplier = 1; break; // Slow (0.5x)
case 1: decayMultiplier = 2; break; // Normal (1x)
case 2: decayMultiplier = 4; break; // Fast (2x)
default: decayMultiplier = 2; break;
}
}
PetLogic::PetLogic() {
stats = PetStats();
stats.lastUpdateTime = tt::kernel::getMillis();
}
void PetLogic::update(uint32_t currentTimeMs) {
if (stats.isDead) {
return;
}
// Calculate elapsed time since last update
uint32_t elapsedMs = currentTimeMs - stats.lastUpdateTime;
uint32_t elapsedSeconds = elapsedMs / 1000;
// Only advance lastUpdateTime by counted milliseconds to preserve sub-second remainder
stats.lastUpdateTime += elapsedSeconds * 1000;
if (elapsedSeconds == 0) {
return; // Nothing to update yet
}
// Update age
stats.ageSeconds += elapsedSeconds;
stats.lifespan += elapsedSeconds;
stats.ageHours = static_cast<uint16_t>(stats.ageSeconds / 3600);
// Reset transient action animations (eating, playing, happy) back to idle
// These are set by actions and should only persist until the next update tick
if (stats.currentAnim == AnimState::Eating ||
stats.currentAnim == AnimState::Playing ||
stats.currentAnim == AnimState::Happy) {
stats.currentAnim = AnimState::Idle;
}
// Apply time-based stat decay
applyStatDecay(elapsedSeconds);
// Check health status
checkHealth();
// Check evolution
checkEvolution();
// Random poop
randomPoopCheck();
// Random events
checkRandomEvent();
}
void PetLogic::performAction(PetAction action) {
if (stats.isDead) {
return;
}
// Wake up from sleep when performing any action (except Sleep itself)
if (action != PetAction::Sleep && stats.isAsleep) {
stats.isAsleep = false;
stats.currentAnim = AnimState::Idle;
}
switch (action) {
case PetAction::Feed:
feed();
break;
case PetAction::Play:
play();
break;
case PetAction::Medicine:
giveMedicine();
break;
case PetAction::Sleep:
sleep();
break;
case PetAction::Clean:
clean();
break;
case PetAction::Pet:
pet();
break;
}
}
void PetLogic::feed() {
uint32_t now = tt::kernel::getMillis();
stats.hunger = clampStat(stats.hunger + ActionEffects::FEED_HUNGER_GAIN);
stats.happiness = clampStat(stats.happiness - ActionEffects::FEED_HAPPINESS_LOSS);
if (rand() % 100 < ActionEffects::FEED_POOP_CHANCE) {
addPoop();
}
if (stats.poopCount > 0) {
stats.cleanliness = clampStat(100 - (stats.poopCount * 30));
}
stats.lastFeedTime = now;
stats.currentAnim = AnimState::Eating;
}
void PetLogic::play() {
uint32_t now = tt::kernel::getMillis();
stats.happiness = clampStat(stats.happiness + ActionEffects::PLAY_HAPPINESS_GAIN);
stats.energy = clampStat(stats.energy - ActionEffects::PLAY_ENERGY_LOSS);
stats.hunger = clampStat(stats.hunger - ActionEffects::PLAY_HUNGER_LOSS);
stats.lastPlayTime = now;
stats.currentAnim = AnimState::Playing;
}
void PetLogic::giveMedicine() {
if (stats.isSick) {
stats.isSick = false;
stats.health = clampStat(stats.health + ActionEffects::MEDICINE_HEALTH_GAIN);
stats.currentAnim = AnimState::Idle;
} else {
stats.health = clampStat(stats.health + ActionEffects::MEDICINE_HEALTH_BOOST);
}
}
void PetLogic::sleep() {
stats.energy = clampStat(stats.energy + ActionEffects::SLEEP_ENERGY_GAIN);
stats.happiness = clampStat(stats.happiness - ActionEffects::SLEEP_HAPPINESS_LOSS);
stats.isAsleep = true;
stats.currentAnim = AnimState::Sleeping;
}
void PetLogic::clean() {
if (stats.poopCount > 0) {
stats.poopCount = 0;
stats.cleanliness = PetThresholds::STAT_MAX;
stats.happiness = clampStat(stats.happiness + 10);
}
}
void PetLogic::pet() {
stats.happiness = clampStat(stats.happiness + ActionEffects::PET_HAPPINESS_GAIN);
stats.currentAnim = AnimState::Happy;
}
void PetLogic::applyPlayResult(int roundsCompleted, int maxRounds) {
if (stats.isDead) return;
if (stats.isAsleep) {
stats.isAsleep = false;
stats.currentAnim = AnimState::Idle;
}
if (maxRounds > 0 && roundsCompleted >= maxRounds) {
// Full win: generous reward
stats.happiness = clampStat(stats.happiness + 30);
stats.energy = clampStat(stats.energy - 10);
stats.hunger = clampStat(stats.hunger - 5);
} else if (roundsCompleted > 0) {
// Partial: scaled reward
stats.happiness = clampStat(stats.happiness + 10 + roundsCompleted * 5);
stats.energy = clampStat(stats.energy - 5);
} else {
// Lost immediately: token reward
stats.happiness = clampStat(stats.happiness + 5);
stats.energy = clampStat(stats.energy - 5);
}
stats.currentAnim = AnimState::Playing;
stats.lastPlayTime = tt::kernel::getMillis();
}
void PetLogic::applyStatDecay(uint32_t elapsedSeconds) {
uint32_t ticks = elapsedSeconds / DecayRates::TICK_INTERVAL_SEC;
if (ticks == 0) return;
// Cap ticks to prevent extreme decay after very long absence
if (ticks > 100) ticks = 100;
// Apply decay multiplier (1=slow 0.5x, 2=normal 1x, 4=fast 2x)
// We multiply ticks by decayMultiplier/2 to get effective ticks
uint32_t effectiveTicks = (ticks * decayMultiplier) / 2;
if (effectiveTicks == 0 && ticks > 0) effectiveTicks = 1; // At least 1 tick if time passed
for (uint32_t i = 0; i < effectiveTicks; i++) {
stats.hunger = clampStat(stats.hunger - DecayRates::HUNGER_DECAY);
stats.happiness = clampStat(stats.happiness - DecayRates::HAPPINESS_DECAY);
stats.energy = clampStat(stats.energy - DecayRates::ENERGY_DECAY);
if (stats.hunger < PetThresholds::HUNGRY_THRESHOLD ||
stats.happiness < PetThresholds::UNHAPPY_THRESHOLD) {
stats.health = clampStat(stats.health - DecayRates::HEALTH_DECAY_NEGLECT);
}
}
// Apply personality and day/night modifiers (per tick)
DayPhase phase = getDayPhase();
for (uint32_t i = 0; i < effectiveTicks; i++) {
// Personality modifiers
switch (stats.personality) {
case Personality::Energetic:
stats.energy = clampStat(stats.energy + 1);
stats.hunger = clampStat(stats.hunger - 1);
break;
case Personality::Lazy:
stats.energy = clampStat(stats.energy - 1);
stats.happiness = clampStat(stats.happiness + 1);
break;
case Personality::Glutton:
stats.hunger = clampStat(stats.hunger - 1);
stats.cleanliness = clampStat(stats.cleanliness - 1);
break;
case Personality::Cheerful:
stats.happiness = clampStat(stats.happiness + 1);
stats.energy = clampStat(stats.energy - 1);
break;
case Personality::Hardy:
stats.health = clampStat(stats.health + 1);
stats.hunger = clampStat(stats.hunger - 1);
break;
}
// Day/night modifiers
if (phase == DayPhase::Day) {
stats.energy = clampStat(stats.energy - 1); // More active during day
} else {
stats.hunger = clampStat(stats.hunger - 1); // Metabolism at night
// Auto-sleep if energy critically low at night
if (!stats.isAsleep && stats.energy < PetThresholds::TIRED_THRESHOLD) {
stats.isAsleep = true;
stats.currentAnim = AnimState::Sleeping;
}
}
}
if (stats.poopCount > 0) {
stats.cleanliness = clampStat(100 - (stats.poopCount * 30));
}
}
void PetLogic::checkHealth() {
if (stats.health < PetThresholds::SICK_THRESHOLD && !stats.isDead) {
stats.isSick = true;
}
if (stats.health <= 0) {
stats.isDead = true;
stats.isSick = false;
stats.stage = LifeStage::Ghost;
stats.currentAnim = AnimState::Dead;
}
}
void PetLogic::checkEvolution() {
if (stats.isDead) {
return;
}
LifeStage newStage = stats.stage;
if (stats.ageHours < 1) {
newStage = LifeStage::Egg;
} else if (stats.ageHours < 8) {
newStage = LifeStage::Baby;
} else if (stats.ageHours < 24) {
newStage = LifeStage::Teen;
} else if (stats.ageHours < 72) {
newStage = LifeStage::Adult;
} else {
newStage = LifeStage::Elder;
}
if (newStage != stats.stage) {
stats.stage = newStage;
}
}
DayPhase PetLogic::getDayPhase() const {
return (stats.ageSeconds % 3600 < 1800) ? DayPhase::Day : DayPhase::Night;
}
AnimState PetLogic::getCurrentAnimation() const {
if (stats.isDead) {
return AnimState::Dead;
}
if (stats.isAsleep) {
return AnimState::Sleeping;
}
if (stats.isSick) {
return AnimState::Sick;
}
if (stats.happiness < PetThresholds::UNHAPPY_THRESHOLD) {
return AnimState::Sad;
}
return stats.currentAnim;
}
void PetLogic::randomPoopCheck() {
if (rand() % 1000 < 10) {
addPoop();
}
}
void PetLogic::addPoop() {
if (stats.poopCount < 3) {
stats.poopCount++;
}
}
RandomEvent PetLogic::checkRandomEvent() {
if (stats.isDead || stats.isAsleep) return RandomEvent::None;
if (rand() % 100 >= 12) return RandomEvent::None; // 12% chance per tick
// Build eligible events based on current state
RandomEvent eligible[6];
int count = 0;
if (stats.hunger < 85) eligible[count++] = RandomEvent::FoundTreat;
if (stats.happiness < 85) eligible[count++] = RandomEvent::MadeFriend;
if (!stats.isSick && stats.health > 30) eligible[count++] = RandomEvent::CaughtCold;
if (stats.cleanliness > 30) eligible[count++] = RandomEvent::GotMuddy;
if (stats.energy < 85) eligible[count++] = RandomEvent::HadNap;
if (getDayPhase() == DayPhase::Day && stats.happiness < 90) eligible[count++] = RandomEvent::SunnyDay;
if (count == 0) return RandomEvent::None;
RandomEvent event = eligible[rand() % count];
// Apply effects
switch (event) {
case RandomEvent::FoundTreat:
stats.hunger = clampStat(stats.hunger + 15);
break;
case RandomEvent::MadeFriend:
stats.happiness = clampStat(stats.happiness + 15);
break;
case RandomEvent::CaughtCold:
stats.isSick = true;
stats.health = clampStat(stats.health - 10);
break;
case RandomEvent::GotMuddy:
stats.cleanliness = clampStat(stats.cleanliness - 20);
break;
case RandomEvent::HadNap:
stats.energy = clampStat(stats.energy + 15);
break;
case RandomEvent::SunnyDay:
stats.happiness = clampStat(stats.happiness + 10);
break;
default:
break;
}
stats.lastEvent = event;
return event;
}
uint8_t PetLogic::clampStat(int16_t value) {
if (value < PetThresholds::STAT_MIN) {
return PetThresholds::STAT_MIN;
}
if (value > PetThresholds::STAT_MAX) {
return PetThresholds::STAT_MAX;
}
return static_cast<uint8_t>(value);
}
void PetLogic::saveState() {
Preferences prefs("TamaTac");
prefs.putInt32("hunger", stats.hunger);
prefs.putInt32("happiness", stats.happiness);
prefs.putInt32("health", stats.health);
prefs.putInt32("energy", stats.energy);
prefs.putInt32("cleanliness", stats.cleanliness);
prefs.putInt32("poopCount", stats.poopCount);
prefs.putInt32("ageSeconds", stats.ageSeconds);
prefs.putInt32("ageHours", stats.ageHours);
prefs.putInt32("lifespan", stats.lifespan);
prefs.putBool("isSick", stats.isSick);
prefs.putBool("isAsleep", stats.isAsleep);
prefs.putBool("isDead", stats.isDead);
prefs.putInt32("stage", static_cast<int32_t>(stats.stage));
prefs.putInt32("currentAnim", static_cast<int32_t>(stats.currentAnim));
prefs.putInt32("personality", static_cast<int32_t>(stats.personality));
// Note: uint32_t millis stored as int32_t (Preferences API limitation).
// Two's complement round-trips correctly; no unsigned API available.
prefs.putInt32("lastSaveTime", static_cast<int32_t>(tt::kernel::getMillis()));
}
bool PetLogic::loadState() {
Preferences prefs("TamaTac");
// Check if save data exists
int32_t savedHunger = prefs.getInt32("hunger", -1);
if (savedHunger == -1) {
return false;
}
// Clamp loaded values to valid ranges (guard against corrupted preferences)
stats.hunger = clampStat(savedHunger);
stats.happiness = clampStat(prefs.getInt32("happiness", 70));
stats.health = clampStat(prefs.getInt32("health", 100));
stats.energy = clampStat(prefs.getInt32("energy", 90));
stats.cleanliness = clampStat(prefs.getInt32("cleanliness", 100));
int32_t loadedPoopCount = prefs.getInt32("poopCount", 0);
stats.poopCount = (loadedPoopCount < 0) ? 0 : (loadedPoopCount > 3) ? 3 : static_cast<uint8_t>(loadedPoopCount);
// uint32_t fields stored as int32_t (Preferences API limitation); cast back explicitly
stats.ageSeconds = static_cast<uint32_t>(prefs.getInt32("ageSeconds", 0));
stats.ageHours = static_cast<uint16_t>(prefs.getInt32("ageHours", 0));
stats.lifespan = static_cast<uint32_t>(prefs.getInt32("lifespan", 0));
stats.isSick = prefs.getBool("isSick", false);
stats.isAsleep = prefs.getBool("isAsleep", false);
stats.isDead = prefs.getBool("isDead", false);
int32_t loadedStage = prefs.getInt32("stage", static_cast<int32_t>(LifeStage::Egg));
if (loadedStage < 0 || loadedStage > static_cast<int32_t>(LifeStage::Ghost)) {
loadedStage = static_cast<int32_t>(LifeStage::Egg);
}
stats.stage = static_cast<LifeStage>(loadedStage);
int32_t loadedAnim = prefs.getInt32("currentAnim", static_cast<int32_t>(AnimState::Idle));
if (loadedAnim < 0 || loadedAnim > static_cast<int32_t>(AnimState::Dead)) {
loadedAnim = static_cast<int32_t>(AnimState::Idle);
}
stats.currentAnim = static_cast<AnimState>(loadedAnim);
int32_t loadedPersonality = prefs.getInt32("personality", 0);
if (loadedPersonality < 0 || loadedPersonality > static_cast<int32_t>(Personality::Hardy)) {
loadedPersonality = 0;
}
stats.personality = static_cast<Personality>(loadedPersonality);
// Handle time elapsed since last save
uint32_t lastSaveTime = prefs.getInt32("lastSaveTime", 0);
uint32_t currentTime = tt::kernel::getMillis();
if (lastSaveTime > 0 && currentTime > lastSaveTime) {
uint32_t elapsedMs = currentTime - lastSaveTime;
uint32_t elapsedSeconds = elapsedMs / 1000;
stats.ageSeconds += elapsedSeconds;
stats.lifespan += elapsedSeconds;
stats.ageHours = static_cast<uint16_t>(stats.ageSeconds / 3600);
// Apply time-based decay for time away
applyStatDecay(elapsedSeconds);
checkHealth();
checkEvolution();
}
stats.lastUpdateTime = currentTime;
return true;
}
void PetLogic::reset() {
stats = PetStats();
stats.personality = static_cast<Personality>(rand() % 5);
stats.lastUpdateTime = tt::kernel::getMillis();
}
+76
View File
@@ -0,0 +1,76 @@
/**
* @file PetLogic.h
* @brief Game logic for TamaTac virtual pet
*/
#pragma once
#include "PetStats.h"
#include <Tactility/kernel/Kernel.h>
class PetLogic {
private:
PetStats stats;
// Internal multiplier for decay calculation: 1=0.5x, 2=1x, 4=2x
// Set via setDecaySpeed() which converts speed enum to multiplier
static uint8_t decayMultiplier;
public:
PetLogic();
// Set decay speed: 0=Slow(0.5x), 1=Normal(1x), 2=Fast(2x)
// Maps to internal multiplier: 0->1, 1->2, 2->4
static void setDecaySpeed(uint8_t speed);
// Core update loop (called every 30 seconds)
void update(uint32_t currentTimeMs);
// Action handlers
void performAction(PetAction action);
// Getters
const PetStats& getStats() const { return stats; }
uint8_t getHunger() const { return stats.hunger; }
uint8_t getHappiness() const { return stats.happiness; }
uint8_t getHealth() const { return stats.health; }
uint8_t getEnergy() const { return stats.energy; }
uint8_t getCleanliness() const { return stats.cleanliness; }
bool isDead() const { return stats.isDead; }
bool isSick() const { return stats.isSick; }
bool isAsleep() const { return stats.isAsleep; }
LifeStage getStage() const { return stats.stage; }
AnimState getCurrentAnimation() const;
DayPhase getDayPhase() const;
RandomEvent getLastEvent() const { return stats.lastEvent; }
void clearLastEvent() { stats.lastEvent = RandomEvent::None; }
// Random events (called during update)
RandomEvent checkRandomEvent();
// Mini-game result (called when pattern game completes)
void applyPlayResult(int roundsCompleted, int maxRounds);
// Persistence
void saveState();
bool loadState();
void reset();
private:
// State checks (called internally during update)
void checkHealth();
void checkEvolution();
void applyStatDecay(uint32_t elapsedSeconds);
// Action implementations
void feed();
void play();
void giveMedicine();
void sleep();
void clean();
void pet();
// Helper functions
uint8_t clampStat(int16_t value);
void randomPoopCheck();
void addPoop();
};
+187
View File
@@ -0,0 +1,187 @@
/**
* @file PetStats.h
* @brief Data structures for TamaTac pet state
*/
#pragma once
#include <cstdint>
// Pet actions
enum class PetAction {
Feed,
Play,
Medicine,
Sleep,
Clean,
Pet // Tap-to-pet: small happiness boost
};
// Life stages (evolution)
enum class LifeStage {
Egg, // 0-1 hour
Baby, // 1-8 hours
Teen, // 8-24 hours
Adult, // 24-72 hours
Elder, // 72+ hours
Ghost // Dead
};
// Pet personality (affects stat decay rates)
enum class Personality : uint8_t {
Energetic = 0, // -1 energy decay, +1 hunger decay
Lazy = 1, // +1 energy decay, -1 happiness decay
Glutton = 2, // +1 hunger decay, +1 cleanliness decay
Cheerful = 3, // -1 happiness decay, +1 energy decay
Hardy = 4 // -1 health_neglect decay, +1 hunger decay
};
// Day/night cycle (derived from ageSeconds, not stored)
enum class DayPhase : uint8_t { Day = 0, Night = 1 };
// Random events (transient, not saved)
enum class RandomEvent : uint8_t {
None = 0,
FoundTreat, // +15 hunger
MadeFriend, // +15 happiness
CaughtCold, // becomes sick, -10 health
GotMuddy, // -20 cleanliness
HadNap, // +15 energy
SunnyDay // +10 happiness (day only)
};
// Animation states (for sprites)
enum class AnimState {
Idle,
Happy,
Sad,
Sleeping,
Eating,
Playing,
Sick,
Dead
};
// Pet statistics and state
struct PetStats {
// Primary stats (0-100 range)
uint8_t hunger; // 100 = full, 0 = starving
uint8_t happiness; // 100 = very happy, 0 = depressed
uint8_t health; // 100 = healthy, 0 = dead
uint8_t energy; // 100 = energized, 0 = exhausted
// Secondary stats
uint8_t cleanliness; // 100 = clean, 0 = filthy
uint8_t poopCount; // Number of poops that need cleaning
// Age tracking
uint32_t ageSeconds; // Total age in seconds
uint16_t ageHours; // Age in hours (for evolution) - supports up to ~7.5 years
// Longevity (for high scores)
uint32_t lifespan; // Total seconds alive (resets on death)
// State flags
bool isSick; // True when health < 20
bool isAsleep; // True during sleep action
bool isDead; // True when health reaches 0
// Current state
LifeStage stage;
AnimState currentAnim;
Personality personality;
RandomEvent lastEvent; // Transient — not saved/loaded
// Timestamps
uint32_t lastUpdateTime; // Last stat update (millis)
uint32_t lastFeedTime; // Last time fed (millis)
uint32_t lastPlayTime; // Last time played (millis)
// Initialize with default values
PetStats() :
hunger(80),
happiness(70),
health(100),
energy(90),
cleanliness(100),
poopCount(0),
ageSeconds(0),
ageHours(0),
lifespan(0),
isSick(false),
isAsleep(false),
isDead(false),
stage(LifeStage::Egg),
currentAnim(AnimState::Idle),
personality(Personality::Energetic),
lastEvent(RandomEvent::None),
lastUpdateTime(0),
lastFeedTime(0),
lastPlayTime(0)
{}
};
// Enum-to-string helpers (shared across views)
inline const char* lifeStageToString(LifeStage stage) {
switch (stage) {
case LifeStage::Egg: return "Egg";
case LifeStage::Baby: return "Baby";
case LifeStage::Teen: return "Teen";
case LifeStage::Adult: return "Adult";
case LifeStage::Elder: return "Elder";
case LifeStage::Ghost: return "Ghost";
default: return "Unknown";
}
}
inline const char* personalityToString(Personality p) {
switch (p) {
case Personality::Energetic: return "Energetic";
case Personality::Lazy: return "Lazy";
case Personality::Glutton: return "Glutton";
case Personality::Cheerful: return "Cheerful";
case Personality::Hardy: return "Hardy";
default: return "Unknown";
}
}
// Stat thresholds
namespace PetThresholds {
constexpr uint8_t STAT_MAX = 100;
constexpr uint8_t STAT_MIN = 0;
constexpr uint8_t HUNGRY_THRESHOLD = 30;
constexpr uint8_t UNHAPPY_THRESHOLD = 30;
constexpr uint8_t SICK_THRESHOLD = 20;
constexpr uint8_t TIRED_THRESHOLD = 20;
constexpr uint8_t DIRTY_THRESHOLD = 30;
}
// Decay rates (per 30-second tick)
namespace DecayRates {
constexpr uint8_t HUNGER_DECAY = 2; // Hungry every ~15 minutes
constexpr uint8_t HAPPINESS_DECAY = 1; // Bored every ~30 minutes
constexpr uint8_t ENERGY_DECAY = 2; // Tired every ~15 minutes
constexpr uint8_t HEALTH_DECAY_NEGLECT = 1; // When hungry or unhappy
constexpr uint32_t TICK_INTERVAL_SEC = 30; // Decay rates are calibrated for this interval
}
// Action effects
namespace ActionEffects {
constexpr uint8_t FEED_HUNGER_GAIN = 30;
constexpr uint8_t FEED_HAPPINESS_LOSS = 5; // Boring to just eat
constexpr uint8_t FEED_POOP_CHANCE = 40; // 40% chance to poop
constexpr uint8_t PLAY_HAPPINESS_GAIN = 25;
constexpr uint8_t PLAY_ENERGY_LOSS = 10;
constexpr uint8_t PLAY_HUNGER_LOSS = 5;
constexpr uint8_t MEDICINE_HEALTH_GAIN = 30;
constexpr uint8_t MEDICINE_HEALTH_BOOST = 5; // When not sick
constexpr uint8_t SLEEP_ENERGY_GAIN = 50;
constexpr uint8_t SLEEP_HAPPINESS_LOSS = 10; // Boring to sleep
constexpr uint32_t SLEEP_DURATION_MS = 5000; // 5 seconds sleep animation
constexpr uint8_t PET_HAPPINESS_GAIN = 5;
}
+223
View File
@@ -0,0 +1,223 @@
/**
* @file ReactionGame.cpp
* @brief Reaction time mini-game implementation
*/
#include "ReactionGame.h"
#include "TamaTac.h"
#include "SfxEngine.h"
#include <Tactility/kernel/Kernel.h>
#include <cstdlib>
#include <cstdio>
void ReactionGame::onStart(lv_obj_t* parent, TamaTac* appInstance) {
app = appInstance;
lv_coord_t screenWidth = lv_display_get_horizontal_resolution(nullptr);
lv_coord_t screenHeight = lv_display_get_vertical_resolution(nullptr);
bool isSmall = (screenWidth < 280 || screenHeight < 180);
bool isXLarge = (screenWidth >= 600);
int pad = isSmall ? 4 : (isXLarge ? 16 : 8);
int targetSize = isSmall ? 80 : (isXLarge ? 200 : 120);
// Main wrapper (tappable for early-tap detection)
lv_obj_t* wrapper = lv_obj_create(parent);
lv_obj_set_size(wrapper, LV_PCT(100), LV_PCT(100));
lv_obj_set_style_pad_all(wrapper, pad, 0);
lv_obj_set_style_bg_opa(wrapper, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(wrapper, 0, 0);
lv_obj_set_flex_flow(wrapper, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(wrapper, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_set_style_pad_row(wrapper, pad, 0);
lv_obj_remove_flag(wrapper, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_flag(wrapper, LV_OBJ_FLAG_CLICKABLE);
lv_obj_add_event_cb(wrapper, onAreaClicked, LV_EVENT_CLICKED, this);
// Status label
statusLabel = lv_label_create(wrapper);
lv_label_set_text(statusLabel, "Get ready...");
lv_obj_set_style_text_align(statusLabel, LV_TEXT_ALIGN_CENTER, 0);
// Target button (hidden initially)
targetBtn = lv_btn_create(wrapper);
lv_obj_set_size(targetBtn, targetSize, targetSize);
lv_obj_set_style_bg_color(targetBtn, lv_color_hex(0x44DD44), 0);
lv_obj_set_style_radius(targetBtn, targetSize / 2, 0);
lv_obj_set_style_border_width(targetBtn, 0, 0);
lv_obj_set_style_shadow_width(targetBtn, 0, 0);
lv_obj_add_flag(targetBtn, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_event_cb(targetBtn, onTargetClicked, LV_EVENT_CLICKED, this);
lv_obj_t* tapLabel = lv_label_create(targetBtn);
lv_label_set_text(tapLabel, "TAP!");
lv_obj_center(tapLabel);
// Initialize game
srand(static_cast<unsigned>(tt::kernel::getMillis()));
round = 0;
score = 0;
phase = Phase::WaitForTarget;
startRound();
}
void ReactionGame::onStop() {
clearTimers();
statusLabel = nullptr;
targetBtn = nullptr;
app = nullptr;
}
void ReactionGame::clearTimers() {
if (delayTimer) {
lv_timer_del(delayTimer);
delayTimer = nullptr;
}
}
void ReactionGame::scheduleTimer(uint32_t ms) {
clearTimers();
delayTimer = lv_timer_create(onTimerTick, ms, this);
lv_timer_set_repeat_count(delayTimer, 1);
}
void ReactionGame::startRound() {
phase = Phase::WaitForTarget;
if (targetBtn) lv_obj_add_flag(targetBtn, LV_OBJ_FLAG_HIDDEN);
char msg[48];
snprintf(msg, sizeof(msg), "Round %d/%d - Wait...", round + 1, MAX_ROUNDS);
if (statusLabel) lv_label_set_text(statusLabel, msg);
// Random delay before target appears
uint32_t delay = MIN_DELAY_MS + (rand() % (MAX_DELAY_MS - MIN_DELAY_MS));
scheduleTimer(delay);
}
void ReactionGame::showTarget() {
phase = Phase::TargetShown;
targetShowTime = tt::kernel::getMillis();
if (targetBtn) lv_obj_clear_flag(targetBtn, LV_OBJ_FLAG_HIDDEN);
if (statusLabel) lv_label_set_text(statusLabel, "TAP NOW!");
SfxEngine* se = TamaTac::getSfxEngine();
if (se) se->play(SfxId::Blip);
// Timeout if player doesn't tap within 3 seconds
scheduleTimer(3000);
}
void ReactionGame::handleTap() {
uint32_t reactionTime = tt::kernel::getMillis() - targetShowTime;
if (targetBtn) lv_obj_add_flag(targetBtn, LV_OBJ_FLAG_HIDDEN);
const char* rating;
if (reactionTime <= GREAT_TIME_MS) {
score++;
rating = "GREAT";
} else if (reactionTime <= GOOD_TIME_MS) {
score++;
rating = "Good";
} else {
rating = "Slow";
}
SfxEngine* se = TamaTac::getSfxEngine();
if (se) se->play(reactionTime <= GOOD_TIME_MS ? SfxId::Confirm : SfxId::Blip);
char msg[64];
snprintf(msg, sizeof(msg), "%s! %ldms", rating, (long)reactionTime);
if (statusLabel) lv_label_set_text(statusLabel, msg);
round++;
phase = Phase::RoundResult;
scheduleTimer(1500);
}
void ReactionGame::handleEarlyTap() {
clearTimers();
if (statusLabel) lv_label_set_text(statusLabel, "Too early!");
SfxEngine* se = TamaTac::getSfxEngine();
if (se) se->play(SfxId::Error);
round++;
phase = Phase::RoundResult;
scheduleTimer(1500);
}
void ReactionGame::showFinalResult() {
char msg[64];
if (score >= MAX_ROUNDS) {
snprintf(msg, sizeof(msg), LV_SYMBOL_OK " Perfect! %d/%d", score, MAX_ROUNDS);
} else if (score > 0) {
snprintf(msg, sizeof(msg), "Score: %d/%d", score, MAX_ROUNDS);
} else {
snprintf(msg, sizeof(msg), LV_SYMBOL_CLOSE " Score: 0/%d", MAX_ROUNDS);
}
if (statusLabel) lv_label_set_text(statusLabel, msg);
SfxEngine* se = TamaTac::getSfxEngine();
if (se) se->play(score > 0 ? SfxId::Success : SfxId::Error);
phase = Phase::Done;
scheduleTimer(1500);
}
void ReactionGame::returnToMain() {
if (app) {
app->onReactionGameComplete(score, score >= MAX_ROUNDS);
}
}
//==============================================================================
// Timer Callback
//==============================================================================
void ReactionGame::onTimerTick(lv_timer_t* timer) {
auto* self = static_cast<ReactionGame*>(lv_timer_get_user_data(timer));
self->delayTimer = nullptr;
switch (self->phase) {
case Phase::WaitForTarget:
self->showTarget();
break;
case Phase::TargetShown:
// Timeout — player didn't tap in time
if (self->targetBtn) lv_obj_add_flag(self->targetBtn, LV_OBJ_FLAG_HIDDEN);
if (self->statusLabel) lv_label_set_text(self->statusLabel, "Too slow!");
self->round++;
self->phase = Phase::RoundResult;
self->scheduleTimer(1500);
break;
case Phase::RoundResult:
if (self->round >= MAX_ROUNDS) {
self->showFinalResult();
} else {
self->startRound();
}
break;
case Phase::Done:
self->returnToMain();
break;
}
}
//==============================================================================
// Input Handling
//==============================================================================
void ReactionGame::onTargetClicked(lv_event_t* e) {
auto* self = static_cast<ReactionGame*>(lv_event_get_user_data(e));
if (self->phase == Phase::TargetShown) {
self->handleTap();
}
}
void ReactionGame::onAreaClicked(lv_event_t* e) {
auto* self = static_cast<ReactionGame*>(lv_event_get_user_data(e));
if (self->phase == Phase::WaitForTarget) {
self->handleEarlyTap();
}
}
+58
View File
@@ -0,0 +1,58 @@
/**
* @file ReactionGame.h
* @brief Reaction time mini-game for TamaTac Play action
*/
#pragma once
#include <lvgl.h>
#include <cstdint>
class TamaTac;
class ReactionGame {
private:
TamaTac* app = nullptr;
// UI elements
lv_obj_t* statusLabel = nullptr;
lv_obj_t* targetBtn = nullptr;
lv_timer_t* delayTimer = nullptr;
// Game constants (MAX_ROUNDS is public for external access)
static constexpr uint32_t MIN_DELAY_MS = 1000;
static constexpr uint32_t MAX_DELAY_MS = 3500;
static constexpr uint32_t GOOD_TIME_MS = 400;
static constexpr uint32_t GREAT_TIME_MS = 250;
// State machine
enum class Phase { WaitForTarget, TargetShown, RoundResult, Done };
Phase phase = Phase::WaitForTarget;
// Game state
int round = 0;
int score = 0; // 0-3 based on reaction quality
uint32_t targetShowTime = 0; // When target appeared (millis)
// Static callbacks
static void onTargetClicked(lv_event_t* e);
static void onAreaClicked(lv_event_t* e);
static void onTimerTick(lv_timer_t* timer);
// Game logic
void startRound();
void showTarget();
void handleTap();
void handleEarlyTap();
void showFinalResult();
void returnToMain();
// Timer helpers
void clearTimers();
void scheduleTimer(uint32_t ms);
public:
static constexpr int MAX_ROUNDS = 3;
void onStart(lv_obj_t* parent, TamaTac* appInstance);
void onStop();
};
+141
View File
@@ -0,0 +1,141 @@
/**
* @file SettingsView.cpp
* @brief Settings view implementation
*/
#include "SettingsView.h"
#include "TamaTac.h"
#include <TactilityCpp/Preferences.h>
lv_obj_t* SettingsView::createSettingRow(lv_obj_t* parentContainer, const char* labelText, bool isSmall, bool isXLarge) {
lv_obj_t* row = lv_obj_create(parentContainer);
lv_obj_set_size(row, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_set_flex_flow(row, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(row, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
int padAll = isSmall ? 4 : (isXLarge ? 16 : 8);
int padHoriz = isSmall ? 6 : (isXLarge ? 24 : 12);
lv_obj_set_style_pad_all(row, padAll, 0);
lv_obj_set_style_pad_left(row, padHoriz, 0);
lv_obj_set_style_pad_right(row, padHoriz, 0);
lv_obj_set_style_border_width(row, 0, 0);
lv_obj_set_style_bg_color(row, lv_color_hex(0x2a2a4e), 0);
lv_obj_set_style_radius(row, isSmall ? 4 : (isXLarge ? 10 : 6), 0);
lv_obj_t* label = lv_label_create(row);
lv_label_set_text(label, labelText);
lv_obj_set_style_text_color(label, lv_color_hex(0xFFFFFF), 0);
return row;
}
void SettingsView::onStart(lv_obj_t* parentWidget, TamaTac* appInstance) {
parent = parentWidget;
app = appInstance;
// Detect screen size for responsive layout
// Use display resolution for reliable sizing (parent may not be laid out yet on first load)
lv_coord_t screenWidth = lv_display_get_horizontal_resolution(nullptr);
lv_coord_t screenHeight = lv_display_get_vertical_resolution(nullptr);
bool isSmall = (screenWidth < 280 || screenHeight < 180);
bool isXLarge = (screenWidth >= 600);
// Load current settings
bool soundEnabled = true;
DecaySpeed decaySpeed = DecaySpeed::Normal;
loadSettings(&soundEnabled, &decaySpeed);
// Scaled dimensions
int padAll = isSmall ? 4 : (isXLarge ? 16 : 8);
int padRowVal = isSmall ? 4 : (isXLarge ? 16 : 8);
// Main wrapper
mainWrapper = lv_obj_create(parent);
lv_obj_set_size(mainWrapper, LV_PCT(100), LV_PCT(100));
lv_obj_set_style_pad_all(mainWrapper, padAll, 0);
lv_obj_set_style_pad_row(mainWrapper, padRowVal, 0);
lv_obj_set_style_bg_opa(mainWrapper, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(mainWrapper, 0, 0);
lv_obj_set_flex_flow(mainWrapper, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(mainWrapper, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_remove_flag(mainWrapper, LV_OBJ_FLAG_SCROLLABLE);
// Sound setting row
lv_obj_t* soundRow = createSettingRow(mainWrapper, "Sound", isSmall, isXLarge);
soundSwitch = lv_switch_create(soundRow);
lv_obj_set_style_bg_color(soundSwitch, lv_color_hex(0x1a1a2e), LV_PART_MAIN);
lv_obj_set_style_bg_color(soundSwitch, lv_color_hex(0x00AA00), LV_PART_INDICATOR);
if (soundEnabled) {
lv_obj_add_state(soundSwitch, LV_STATE_CHECKED);
}
lv_obj_add_event_cb(soundSwitch, onSoundToggled, LV_EVENT_VALUE_CHANGED, this);
// Decay speed row
lv_obj_t* decayRow = createSettingRow(mainWrapper, "Speed", isSmall, isXLarge);
decayDropdown = lv_dropdown_create(decayRow);
lv_dropdown_set_options(decayDropdown, "Slow\nNormal\nFast");
lv_dropdown_set_selected(decayDropdown, static_cast<uint16_t>(decaySpeed));
lv_obj_set_width(decayDropdown, isSmall ? 80 : (isXLarge ? 140 : 100));
lv_obj_set_style_bg_color(decayDropdown, lv_color_hex(0x1a1a2e), LV_PART_MAIN);
lv_obj_set_style_text_color(decayDropdown, lv_color_hex(0xFFFFFF), LV_PART_MAIN);
lv_obj_add_event_cb(decayDropdown, onDecayChanged, LV_EVENT_VALUE_CHANGED, this);
}
void SettingsView::onStop() {
mainWrapper = nullptr;
soundSwitch = nullptr;
decayDropdown = nullptr;
parent = nullptr;
app = nullptr;
}
void SettingsView::loadSettings(bool* soundEnabled, DecaySpeed* decaySpeed) {
Preferences prefs("TamaTacSet");
*soundEnabled = prefs.getBool("soundOn", true);
int32_t speed = prefs.getInt32("decaySpd", static_cast<int32_t>(DecaySpeed::Normal));
if (speed < 0 || speed > 2) {
speed = static_cast<int32_t>(DecaySpeed::Normal);
}
*decaySpeed = static_cast<DecaySpeed>(speed);
}
void SettingsView::saveSettings(bool soundEnabled, DecaySpeed decaySpeed) {
Preferences prefs("TamaTacSet");
prefs.putBool("soundOn", soundEnabled);
prefs.putInt32("decaySpd", static_cast<int32_t>(decaySpeed));
}
void SettingsView::onSoundToggled(lv_event_t* e) {
SettingsView* view = static_cast<SettingsView*>(lv_event_get_user_data(e));
if (view == nullptr || view->soundSwitch == nullptr || view->decayDropdown == nullptr || view->app == nullptr) return;
bool isChecked = lv_obj_has_state(view->soundSwitch, LV_STATE_CHECKED);
view->app->setSoundEnabled(isChecked);
// Read decay speed from UI widget instead of redundant preferences load
DecaySpeed decaySpeed = static_cast<DecaySpeed>(lv_dropdown_get_selected(view->decayDropdown));
view->saveSettings(isChecked, decaySpeed);
}
void SettingsView::onDecayChanged(lv_event_t* e) {
SettingsView* view = static_cast<SettingsView*>(lv_event_get_user_data(e));
if (view == nullptr || view->decayDropdown == nullptr || view->soundSwitch == nullptr || view->app == nullptr) return;
uint16_t selected = lv_dropdown_get_selected(view->decayDropdown);
if (selected > 2) {
selected = 1;
}
DecaySpeed newSpeed = static_cast<DecaySpeed>(selected);
view->app->setDecaySpeed(newSpeed);
// Read sound state from UI widget instead of redundant preferences load
bool soundEnabled = lv_obj_has_state(view->soundSwitch, LV_STATE_CHECKED);
view->saveSettings(soundEnabled, newSpeed);
}
+48
View File
@@ -0,0 +1,48 @@
/**
* @file SettingsView.h
* @brief Settings view for TamaTac preferences
*/
#pragma once
#include <lvgl.h>
class TamaTac;
// Decay speed multipliers
enum class DecaySpeed {
Slow = 0, // 0.5x decay
Normal = 1, // 1x decay
Fast = 2 // 2x decay
};
class SettingsView {
private:
TamaTac* app = nullptr;
lv_obj_t* parent = nullptr;
// UI elements
lv_obj_t* mainWrapper = nullptr;
lv_obj_t* soundSwitch = nullptr;
lv_obj_t* decayDropdown = nullptr;
public:
SettingsView() = default;
~SettingsView() = default;
SettingsView(const SettingsView&) = delete;
SettingsView& operator=(const SettingsView&) = delete;
void onStart(lv_obj_t* parentWidget, TamaTac* appInstance);
void onStop();
// Load/save settings
static void loadSettings(bool* soundEnabled, DecaySpeed* decaySpeed);
static void saveSettings(bool soundEnabled, DecaySpeed decaySpeed);
private:
lv_obj_t* createSettingRow(lv_obj_t* parentContainer, const char* labelText, bool isSmall = false, bool isXLarge = false);
// Static event handlers
static void onSoundToggled(lv_event_t* e);
static void onDecayChanged(lv_event_t* e);
};
+794
View File
@@ -0,0 +1,794 @@
/**
* @file SpriteData.h
* @brief Placeholder 24x24 RGB565 sprite data for TamaTac
*
* Auto-generated by generate_placeholders.py
* Replace with real pixel art via sprite2c.py
*/
#pragma once
#include "Sprites.h"
constexpr uint16_t sprite_egg_idle_frame0[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xFF9B, 0xFF9B, 0xA325, 0xFF9B, 0xA325, 0xFF9B, 0xA325, 0xFF9B, 0xFF9B, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xA325, 0xFF9B, 0xA325, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_egg_idle_frame1[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xA325, 0xFF9B, 0xA325, 0xFF9B, 0xA325, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xA325, 0xFF9B, 0xA325, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xCC6A, 0xFF9B, 0xFF9B, 0xFF9B, 0xCC6A, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCC6A, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_baby_idle_frame0[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB0E3, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB0E3, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xB0E3, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB0E3, 0xFCB6, 0xFFFF, 0x10A2, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFFFF, 0x10A2, 0xFCB6, 0xB0E3, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFCB6, 0xFCB6, 0x10A2, 0x10A2, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0x10A2, 0x10A2, 0xFCB6, 0xFCB6, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB0E3, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xB0E3, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFCB6, 0xFE5B, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFE5B, 0xFCB6, 0xFCB6, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0x10A2, 0x10A2, 0x10A2, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB0E3, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xB0E3, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB0E3, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xB0E3, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB0E3, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_baby_idle_frame1[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB0E3, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB0E3, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xB0E3, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB0E3, 0xFCB6, 0xFFFF, 0x10A2, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFFFF, 0x10A2, 0xFCB6, 0xB0E3, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFCB6, 0xFCB6, 0x10A2, 0x10A2, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0x10A2, 0x10A2, 0xFCB6, 0xFCB6, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB0E3, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xB0E3, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFCB6, 0xFE5B, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFE5B, 0xFCB6, 0xFCB6, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0x10A2, 0x10A2, 0x10A2, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB0E3, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xB0E3, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB0E3, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xFCB6, 0xB0E3, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB0E3, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_teen_idle_frame0[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0xF81F, 0xF81F, 0x53DF, 0xF81F, 0xF81F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0xF81F, 0xF81F, 0x53DF, 0xF81F, 0xF81F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0xFFFF, 0x10A2, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0xFFFF, 0x10A2, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x965F, 0x965F, 0x965F, 0x10A2, 0x10A2, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x10A2, 0x10A2, 0x965F, 0x965F, 0x965F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x10A2, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x10A2, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_teen_idle_frame1[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0xF81F, 0xF81F, 0x53DF, 0xF81F, 0xF81F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0xF81F, 0xF81F, 0x53DF, 0xF81F, 0xF81F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0xFFFF, 0x10A2, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0xFFFF, 0x10A2, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x965F, 0x965F, 0x965F, 0x10A2, 0x10A2, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x10A2, 0x10A2, 0x965F, 0x965F, 0x965F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x10A2, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x10A2, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_adult_idle_frame0[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x3E47, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0x3E47, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0xFFFF, 0x10A2, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0xFFFF, 0x10A2, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x10A2, 0x10A2, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x10A2, 0x10A2, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x10A2, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x10A2, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_adult_idle_frame1[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x3E47, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0x3E47, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0xFFFF, 0x10A2, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0xFFFF, 0x10A2, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x10A2, 0x10A2, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x10A2, 0x10A2, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x10A2, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x10A2, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_adult_idle_frame2[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x3E47, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0x3E47, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0xFFFF, 0x10A2, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0xFFFF, 0x10A2, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x10A2, 0x10A2, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x10A2, 0x10A2, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x10A2, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x10A2, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x35B4, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x3E47, 0x35B4, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_elder_idle_frame0[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xFFFF, 0x10A2, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xFFFF, 0x10A2, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0x10A2, 0x10A2, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0x10A2, 0x10A2, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0x10A2, 0x10A2, 0x10A2, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_elder_idle_frame1[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xFFFF, 0x10A2, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xFFFF, 0x10A2, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0x10A2, 0x10A2, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0x10A2, 0x10A2, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0x10A2, 0x10A2, 0x10A2, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_ghost_frame0[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x10A2, 0x10A2, 0xFFFF, 0xFFFF, 0xFFFF, 0x10A2, 0x10A2, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0x10A2, 0x10A2, 0xFFFF, 0xFFFF, 0xFFFF, 0x10A2, 0x10A2, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x528A, 0x528A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x528A, 0x528A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCE59, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE59, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE59, 0xCE59, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE59, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCE59, 0xFFFF, 0xFFFF, 0xCE59, 0xF81F, 0xCE59, 0xCE59, 0xFFFF, 0xCE59, 0xF81F, 0xF81F, 0xCE59, 0xFFFF, 0xCE59, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCE59, 0xCE59, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCE59, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCE59, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_ghost_frame1[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x10A2, 0x10A2, 0xFFFF, 0xFFFF, 0xFFFF, 0x10A2, 0x10A2, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0x10A2, 0x10A2, 0xFFFF, 0xFFFF, 0xFFFF, 0x10A2, 0x10A2, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x528A, 0x528A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x528A, 0x528A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE59, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE59, 0xCE59, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE59, 0xCE59, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCE59, 0xFFFF, 0xFFFF, 0xCE59, 0xF81F, 0xCE59, 0xCE59, 0xFFFF, 0xCE59, 0xF81F, 0xF81F, 0xCE59, 0xFFFF, 0xCE59, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCE59, 0xCE59, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCE59, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCE59, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_ghost_frame2[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x10A2, 0x10A2, 0xFFFF, 0xFFFF, 0xFFFF, 0x10A2, 0x10A2, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0x10A2, 0x10A2, 0xFFFF, 0xFFFF, 0xFFFF, 0x10A2, 0x10A2, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x528A, 0x528A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x528A, 0x528A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE59, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE59, 0xCE59, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE59, 0xCE59, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xCE59, 0xF81F, 0xCE59, 0xCE59, 0xFFFF, 0xCE59, 0xF81F, 0xF81F, 0xCE59, 0xFFFF, 0xCE59, 0xF81F, 0xF81F, 0xCE59, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCE59, 0xCE59, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCE59, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCE59, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_sick_frame0[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x64AA, 0x64AA, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x64AA, 0x965F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x64AA, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x64AA, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x64AA, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB6F2, 0xB6F2, 0xB6F2, 0x10A2, 0xB6F2, 0x10A2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x10A2, 0xB6F2, 0x10A2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x10A2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x10A2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0x10A2, 0xB6F2, 0x10A2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x10A2, 0xB6F2, 0x10A2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x64AA, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x64AA, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x10A2, 0xB6F2, 0x10A2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x64AA, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x10A2, 0xB6F2, 0x10A2, 0xB6F2, 0x10A2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x64AA, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x64AA, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x64AA, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x64AA, 0x64AA, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_sick_frame1[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x64AA, 0x64AA, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x64AA, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x965F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x53DF, 0x64AA, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x64AA, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x64AA, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB6F2, 0xB6F2, 0xB6F2, 0x10A2, 0xB6F2, 0x10A2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x10A2, 0xB6F2, 0x10A2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x10A2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x10A2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0x10A2, 0xB6F2, 0x10A2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x10A2, 0xB6F2, 0x10A2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x64AA, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x64AA, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x10A2, 0xB6F2, 0x10A2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x64AA, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x10A2, 0xB6F2, 0x10A2, 0xB6F2, 0x10A2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x64AA, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x64AA, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x64AA, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0x64AA, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0xB6F2, 0x64AA, 0x64AA, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x64AA, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_happy_frame0[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xFD05, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFFFF, 0x10A2, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFFFF, 0x10A2, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0x10A2, 0x10A2, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0x10A2, 0x10A2, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0x10A2, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0x10A2, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFEE6, 0xFEE6, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xFD05, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_happy_frame1[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xFD05, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xF81F, 0xF81F, 0xFFFF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFFFF, 0x10A2, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFFFF, 0x10A2, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0x10A2, 0x10A2, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0x10A2, 0x10A2, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0x10A2, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0x10A2, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFEE6, 0xFEE6, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFD05, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFEE6, 0xFD05, 0xFD05, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_sad_frame0[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0xFFFF, 0x10A2, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0xFFFF, 0x10A2, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x965F, 0x965F, 0x965F, 0x965F, 0x10A2, 0x10A2, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x10A2, 0x10A2, 0x965F, 0x965F, 0x965F, 0x965F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x965F, 0x965F, 0x965F, 0x56FB, 0x965F, 0x965F, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x53DF, 0x965F, 0x10A2, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x10A2, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_sad_frame1[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0xFFFF, 0x10A2, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0xFFFF, 0x10A2, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x965F, 0x965F, 0x965F, 0x965F, 0x10A2, 0x10A2, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x10A2, 0x10A2, 0x965F, 0x965F, 0x965F, 0x965F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x56FB, 0x965F, 0x10A2, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x10A2, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0x53DF, 0x965F, 0x965F, 0x965F, 0x965F, 0x965F, 0x53DF, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x53DF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_eating_frame0[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFFFF, 0x10A2, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFFFF, 0x10A2, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x3E47, 0x3E47, 0xFD05, 0xFD05, 0x10A2, 0x10A2, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0x10A2, 0x10A2, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x3E47, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0x10A2, 0xF9E7, 0xF9E7, 0xF9E7, 0x10A2, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_eating_frame1[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFFFF, 0x10A2, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFFFF, 0x10A2, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0x10A2, 0x10A2, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0x10A2, 0x10A2, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0x10A2, 0x10A2, 0x10A2, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_eating_frame2[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFFFF, 0x10A2, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFFFF, 0x10A2, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0x10A2, 0x10A2, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0x10A2, 0x10A2, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0x10A2, 0xF9E7, 0xF9E7, 0xF9E7, 0x10A2, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xA325, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xFD05, 0xA325, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xA325, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_playing_frame0[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0xFEE6, 0x10A2, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0xFEE6, 0x10A2, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x10A2, 0x10A2, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x10A2, 0x10A2, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x10A2, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x10A2, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_playing_frame1[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xCE59, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCE59, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xCE59, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCE59, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0xFEE6, 0x10A2, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0xFEE6, 0x10A2, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x10A2, 0x10A2, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x10A2, 0x10A2, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x10A2, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x10A2, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_playing_frame2[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0xFEE6, 0x10A2, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0xFEE6, 0x10A2, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x10A2, 0x10A2, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x10A2, 0x10A2, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x10A2, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x10A2, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x10A2, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0x35B4, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x56FB, 0x35B4, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0x35B4, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_sleeping_frame0[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCE59, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0x10A2, 0x10A2, 0x10A2, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0x10A2, 0x10A2, 0x10A2, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0x10A2, 0x10A2, 0x10A2, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr uint16_t sprite_sleeping_frame1[576] = {
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xCE59, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xFFFF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xFFFF, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0x10A2, 0x10A2, 0x10A2, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0x10A2, 0x10A2, 0x10A2, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0x10A2, 0x10A2, 0x10A2, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xB33F, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xDDBF, 0xB33F, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xB33F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F, 0xF81F,
};
constexpr AnimFrame frames_egg_idle[] = { {sprite_egg_idle_frame0}, {sprite_egg_idle_frame1} };
constexpr AnimFrame frames_baby_idle[] = { {sprite_baby_idle_frame0}, {sprite_baby_idle_frame1} };
constexpr AnimFrame frames_teen_idle[] = { {sprite_teen_idle_frame0}, {sprite_teen_idle_frame1} };
constexpr AnimFrame frames_adult_idle[] = { {sprite_adult_idle_frame0}, {sprite_adult_idle_frame1}, {sprite_adult_idle_frame2} };
constexpr AnimFrame frames_elder_idle[] = { {sprite_elder_idle_frame0}, {sprite_elder_idle_frame1} };
constexpr AnimFrame frames_ghost[] = { {sprite_ghost_frame0}, {sprite_ghost_frame1}, {sprite_ghost_frame2} };
constexpr AnimFrame frames_sick[] = { {sprite_sick_frame0}, {sprite_sick_frame1} };
constexpr AnimFrame frames_happy[] = { {sprite_happy_frame0}, {sprite_happy_frame1} };
constexpr AnimFrame frames_sad[] = { {sprite_sad_frame0}, {sprite_sad_frame1} };
constexpr AnimFrame frames_eating[] = { {sprite_eating_frame0}, {sprite_eating_frame1}, {sprite_eating_frame2} };
constexpr AnimFrame frames_playing[] = { {sprite_playing_frame0}, {sprite_playing_frame1}, {sprite_playing_frame2} };
constexpr AnimFrame frames_sleeping[] = { {sprite_sleeping_frame0}, {sprite_sleeping_frame1} };
const AnimatedSprite animatedSprites[PET_SPRITE_COUNT] = {
{frames_egg_idle, 2, 800, true},
{frames_baby_idle, 2, 600, true},
{frames_teen_idle, 2, 500, true},
{frames_adult_idle, 3, 400, true},
{frames_elder_idle, 2, 700, true},
{frames_ghost, 3, 500, true},
{frames_sick, 2, 1000, true},
{frames_happy, 2, 400, true},
{frames_sad, 2, 800, true},
{frames_eating, 3, 300, false},
{frames_playing, 3, 300, false},
{frames_sleeping, 2, 1000, true},
};
+144
View File
@@ -0,0 +1,144 @@
/**
* @file Sprites.h
* @brief Sprite types, enums, and icon data for TamaTac pet
*
* Pet sprites are 24x24 RGB565 with animation support (in SpriteData.h).
* UI icons remain 8x8 monochrome (defined here).
*/
#pragma once
#include <cstdint>
// ── Sprite Dimensions ────────────────────────────────────────────────────────
constexpr int SPRITE_WIDTH = 24;
constexpr int SPRITE_HEIGHT = 24;
constexpr int SPRITE_PIXELS = SPRITE_WIDTH * SPRITE_HEIGHT; // 576
constexpr int ICON_WIDTH = 8;
constexpr int ICON_HEIGHT = 8;
// Transparent color key (magenta in RGB565)
constexpr uint16_t SPRITE_TRANSPARENT = 0xF81F;
// ── Pet Sprite IDs ───────────────────────────────────────────────────────────
enum SpriteId {
SPRITE_EGG_IDLE,
SPRITE_BABY_IDLE,
SPRITE_TEEN_IDLE,
SPRITE_ADULT_IDLE,
SPRITE_ELDER_IDLE,
SPRITE_GHOST,
SPRITE_SICK,
SPRITE_HAPPY,
SPRITE_SAD,
SPRITE_EATING,
SPRITE_PLAYING,
SPRITE_SLEEPING,
PET_SPRITE_COUNT // Number of animated pet sprites
};
// ── Icon IDs ─────────────────────────────────────────────────────────────────
enum IconId {
ICON_POOP,
ICON_HUNGER,
ICON_HAPPINESS,
ICON_HEALTH,
ICON_ENERGY,
ICON_FEED,
ICON_PLAY,
ICON_MEDICINE,
ICON_SLEEP,
ICON_COUNT
};
// ── Animation Structures ─────────────────────────────────────────────────────
struct AnimFrame {
const uint16_t* data; // Pointer to RGB565 pixel array (576 uint16_t)
};
struct AnimatedSprite {
const AnimFrame* frames;
uint8_t frameCount;
uint16_t frameDelayMs;
bool loop;
};
// ── Icon Structure (8x8 monochrome) ─────────────────────────────────────────
struct Icon {
const uint8_t* data;
int width;
int height;
};
// ── Animated Sprite Lookup ───────────────────────────────────────────────────
extern const AnimatedSprite animatedSprites[PET_SPRITE_COUNT];
inline const AnimatedSprite& getAnimSprite(SpriteId id) {
int idx = static_cast<int>(id);
if (idx < 0 || idx >= PET_SPRITE_COUNT) idx = 0;
return animatedSprites[idx];
}
// ── Icon Data (8x8 monochrome, defined inline) ──────────────────────────────
constexpr uint8_t icon_poop[] = {
0x00, 0x18, 0x3C, 0x7E, 0x7E, 0xFF, 0xFF, 0x00,
};
constexpr uint8_t icon_hunger[] = {
0x18, 0x08, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x3C,
};
constexpr uint8_t icon_happiness[] = {
0x00, 0x66, 0x66, 0x00, 0x81, 0x42, 0x3C, 0x00,
};
constexpr uint8_t icon_health[] = {
0x00, 0x66, 0xFF, 0xFF, 0x7E, 0x3C, 0x18, 0x00,
};
constexpr uint8_t icon_energy[] = {
0x18, 0x1C, 0x0E, 0xFF, 0x70, 0x38, 0x18, 0x00,
};
constexpr uint8_t icon_feed[] = {
0x54, 0x54, 0x54, 0x7C, 0x10, 0x10, 0x10, 0x10,
};
constexpr uint8_t icon_play[] = {
0x3C, 0x7E, 0xDB, 0xFF, 0xDB, 0x7E, 0x3C, 0x00,
};
constexpr uint8_t icon_medicine[] = {
0x18, 0x18, 0x7E, 0xFF, 0x7E, 0x18, 0x18, 0x00,
};
constexpr uint8_t icon_sleep[] = {
0x1C, 0x38, 0x70, 0x60, 0x70, 0x38, 0x1C, 0x00,
};
inline const Icon icons[ICON_COUNT] = {
{icon_poop, ICON_WIDTH, ICON_HEIGHT},
{icon_hunger, ICON_WIDTH, ICON_HEIGHT},
{icon_happiness, ICON_WIDTH, ICON_HEIGHT},
{icon_health, ICON_WIDTH, ICON_HEIGHT},
{icon_energy, ICON_WIDTH, ICON_HEIGHT},
{icon_feed, ICON_WIDTH, ICON_HEIGHT},
{icon_play, ICON_WIDTH, ICON_HEIGHT},
{icon_medicine, ICON_WIDTH, ICON_HEIGHT},
{icon_sleep, ICON_WIDTH, ICON_HEIGHT},
};
inline const Icon& getIcon(IconId id) {
int idx = static_cast<int>(id);
if (idx < 0 || idx >= ICON_COUNT) idx = 0;
return icons[idx];
}
+148
View File
@@ -0,0 +1,148 @@
/**
* @file StatsView.cpp
* @brief Stats detail view implementation
*/
#include "StatsView.h"
#include "TamaTac.h"
#include <cstdio>
lv_obj_t* StatsView::createStatRow(lv_obj_t* parentContainer, const char* labelText, lv_color_t color, bool isXLarge) {
lv_obj_t* row = lv_obj_create(parentContainer);
lv_obj_set_size(row, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_set_flex_flow(row, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(row, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START);
lv_obj_set_style_pad_all(row, 0, 0);
lv_obj_set_style_pad_right(row, isXLarge ? 20 : 10, 0);
lv_obj_set_style_border_width(row, 0, 0);
lv_obj_set_style_bg_opa(row, LV_OPA_TRANSP, 0);
lv_obj_t* label = lv_label_create(row);
lv_label_set_text(label, labelText);
lv_obj_set_style_text_color(label, lv_palette_lighten(LV_PALETTE_GREY, 5), 0);
lv_obj_t* value = lv_label_create(row);
lv_label_set_text(value, "--");
lv_obj_set_style_text_color(value, color, 0);
return value;
}
void StatsView::onStart(lv_obj_t* parentWidget, TamaTac* appInstance) {
parent = parentWidget;
app = appInstance;
// Detect screen size for responsive layout
// Use display resolution for reliable sizing (parent may not be laid out yet on first load)
lv_coord_t screenWidth = lv_display_get_horizontal_resolution(nullptr);
lv_coord_t screenHeight = lv_display_get_vertical_resolution(nullptr);
bool isSmall = (screenWidth < 280 || screenHeight < 180);
bool isXLarge = (screenWidth >= 600);
// Scaled dimensions
int padAll = isSmall ? 6 : (isXLarge ? 24 : 12);
int padRowVal = isSmall ? 4 : (isXLarge ? 16 : 8);
// Main content wrapper
mainWrapper = lv_obj_create(parent);
lv_obj_set_size(mainWrapper, LV_PCT(100), LV_PCT(100));
lv_obj_set_style_pad_all(mainWrapper, padAll, 0);
lv_obj_set_style_pad_row(mainWrapper, padRowVal, 0);
lv_obj_set_style_bg_opa(mainWrapper, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(mainWrapper, 0, 0);
lv_obj_set_flex_flow(mainWrapper, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(mainWrapper, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
lv_obj_remove_flag(mainWrapper, LV_OBJ_FLAG_SCROLLABLE);
// Title row (stage/age on left, status on right)
lv_obj_t* titleRow = lv_obj_create(mainWrapper);
lv_obj_set_width(titleRow, LV_PCT(100));
lv_obj_set_height(titleRow, LV_SIZE_CONTENT);
lv_obj_set_style_bg_opa(titleRow, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(titleRow, 0, 0);
lv_obj_set_style_pad_all(titleRow, 0, 0);
lv_obj_set_flex_flow(titleRow, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(titleRow, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
titleLabel = lv_label_create(titleRow);
lv_label_set_text(titleLabel, "Egg | 0d 0h");
lv_obj_set_style_text_color(titleLabel, lv_color_hex(0xFFFFFF), 0);
statusLabel = lv_label_create(titleRow);
lv_label_set_text(statusLabel, "");
lv_obj_set_style_text_color(statusLabel, lv_color_hex(0xFFFFFF), 0);
// Personality row
personalityValue = createStatRow(mainWrapper, "Personality", lv_palette_main(LV_PALETTE_PURPLE), isXLarge);
// Create stat rows with colored values
hungerValue = createStatRow(mainWrapper, "Hunger", lv_color_hex(0xFF9900), isXLarge);
happyValue = createStatRow(mainWrapper, "Happy", lv_color_hex(0xFFCC00), isXLarge);
healthValue = createStatRow(mainWrapper, "Health", lv_color_hex(0x00FF00), isXLarge);
energyValue = createStatRow(mainWrapper, "Energy", lv_color_hex(0x00CCFF), isXLarge);
cleanValue = createStatRow(mainWrapper, "Clean", lv_color_hex(0xFFFFFF), isXLarge);
}
void StatsView::onStop() {
mainWrapper = nullptr;
titleLabel = nullptr;
statusLabel = nullptr;
hungerValue = nullptr;
happyValue = nullptr;
healthValue = nullptr;
energyValue = nullptr;
cleanValue = nullptr;
personalityValue = nullptr;
parent = nullptr;
app = nullptr;
}
void StatsView::updateStats(PetLogic* petLogic) {
if (petLogic == nullptr || titleLabel == nullptr) return;
if (hungerValue == nullptr || happyValue == nullptr ||
healthValue == nullptr || energyValue == nullptr ||
cleanValue == nullptr || statusLabel == nullptr) return;
const PetStats& stats = petLogic->getStats();
// Update title with stage and age
int hours = stats.ageHours;
int days = hours / 24;
hours = hours % 24;
// Update title (stage and age)
char titleText[64];
snprintf(titleText, sizeof(titleText), "%s | %dd %dh", lifeStageToString(stats.stage), days, hours);
lv_label_set_text(titleLabel, titleText);
// Update status label (right-aligned)
const char* status = "";
if (stats.isDead) status = "[DEAD]";
else if (stats.isSick) status = "[SICK]";
else if (stats.isAsleep) status = "[SLEEPING]";
lv_label_set_text(statusLabel, status);
// Update personality
if (personalityValue) {
lv_label_set_text(personalityValue, personalityToString(stats.personality));
}
// Update individual stat values
char valueText[16];
snprintf(valueText, sizeof(valueText), "%d%%", stats.hunger);
lv_label_set_text(hungerValue, valueText);
snprintf(valueText, sizeof(valueText), "%d%%", stats.happiness);
lv_label_set_text(happyValue, valueText);
snprintf(valueText, sizeof(valueText), "%d%%", stats.health);
lv_label_set_text(healthValue, valueText);
snprintf(valueText, sizeof(valueText), "%d%%", stats.energy);
lv_label_set_text(energyValue, valueText);
snprintf(valueText, sizeof(valueText), "%d%%", stats.cleanliness);
lv_label_set_text(cleanValue, valueText);
}
+38
View File
@@ -0,0 +1,38 @@
/**
* @file StatsView.h
* @brief Stats detail view for TamaTac
*/
#pragma once
#include <lvgl.h>
#include "PetLogic.h"
class TamaTac;
class StatsView {
private:
TamaTac* app = nullptr;
lv_obj_t* parent = nullptr;
// UI elements
lv_obj_t* mainWrapper = nullptr;
lv_obj_t* titleLabel = nullptr;
lv_obj_t* statusLabel = nullptr;
// Individual stat value labels
lv_obj_t* hungerValue = nullptr;
lv_obj_t* happyValue = nullptr;
lv_obj_t* healthValue = nullptr;
lv_obj_t* energyValue = nullptr;
lv_obj_t* cleanValue = nullptr;
lv_obj_t* personalityValue = nullptr;
// Helper to create stat row
lv_obj_t* createStatRow(lv_obj_t* parentContainer, const char* labelText, lv_color_t color, bool isXLarge = false);
public:
void onStart(lv_obj_t* parentWidget, TamaTac* appInstance);
void onStop();
void updateStats(PetLogic* petLogic);
};
+527
View File
@@ -0,0 +1,527 @@
/**
* @file TamaTac.cpp
* @brief TamaTac virtual pet app implementation
*/
#include "TamaTac.h"
#include "SpriteData.h"
#include <tt_lvgl_toolbar.h>
#include <tt_app_alertdialog.h>
#include <Tactility/kernel/Kernel.h>
#include <freertos/FreeRTOS.h>
#include <freertos/timers.h>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
// Static member initialization
PetLogic* TamaTac::petLogic = nullptr;
TimerHandle_t TamaTac::updateTimer = nullptr;
SemaphoreHandle_t TamaTac::timerMutex = nullptr;
AppHandle TamaTac::currentApp = nullptr;
AppLaunchId TamaTac::resetDialogId = 0;
LifeStage TamaTac::lastKnownStage = LifeStage::Egg;
SfxEngine* TamaTac::sfxEngine = nullptr;
DecaySpeed TamaTac::decaySpeed = DecaySpeed::Normal;
uint32_t TamaTac::lastPetTime = 0;
bool TamaTac::pendingResetUI = false;
// Canvas buffer definitions (shared by views via extern)
// 72x72 supports 24x24 sprites at 3x scale (medium/large/xlarge screens)
lv_color_t TamaTac_canvasBuffer[72 * 72];
lv_color_t TamaTac_iconBuffers[12][16 * 16];
void TamaTac::onCreate(AppHandle app) {
currentApp = app;
// Seed RNG once so rand() produces different sequences each run
srand(tt::kernel::getMillis());
if (petLogic == nullptr) {
petLogic = new PetLogic();
if (!petLogic->loadState()) {
// No save data - pet starts fresh
}
lastKnownStage = petLogic->getStats().stage;
}
if (timerMutex == nullptr) {
timerMutex = xSemaphoreCreateMutex();
}
}
void TamaTac::onShow(AppHandle context, lv_obj_t* parent) {
// Initialize SfxEngine
if (sfxEngine == nullptr) {
sfxEngine = new SfxEngine();
sfxEngine->start();
sfxEngine->applyVolumePreset(SfxEngine::VolumePreset::Normal);
// Load settings
bool soundEnabled;
SettingsView::loadSettings(&soundEnabled, &decaySpeed);
sfxEngine->setEnabled(soundEnabled);
PetLogic::setDecaySpeed(static_cast<uint8_t>(decaySpeed));
}
if (updateTimer == nullptr) {
updateTimer = xTimerCreate(
"PetUpdate",
pdMS_TO_TICKS(30000),
pdTRUE,
nullptr,
onTimerUpdate
);
if (updateTimer != nullptr) {
xTimerStart(updateTimer, 0);
}
}
currentApp = context;
lv_obj_remove_flag(parent, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
lv_obj_set_style_pad_all(parent, 0, 0);
lv_obj_set_style_pad_row(parent, 0, 0);
toolbar = tt_lvgl_toolbar_create_for_app(parent, context);
menuButton = tt_lvgl_toolbar_add_text_button_action(toolbar, LV_SYMBOL_LIST, onMenuClicked, this);
tt_lvgl_toolbar_add_text_button_action(toolbar, LV_SYMBOL_TRASH, onCleanClicked, this);
tt_lvgl_toolbar_add_text_button_action(toolbar, LV_SYMBOL_REFRESH, onResetClicked, this);
wrapperWidget = lv_obj_create(parent);
lv_obj_set_width(wrapperWidget, LV_PCT(100));
lv_obj_set_flex_grow(wrapperWidget, 1);
lv_obj_set_style_pad_all(wrapperWidget, 0, 0);
lv_obj_set_style_border_width(wrapperWidget, 0, 0);
lv_obj_set_style_bg_opa(wrapperWidget, LV_OPA_TRANSP, 0);
lv_obj_remove_flag(wrapperWidget, LV_OBJ_FLAG_SCROLLABLE);
showMainView();
}
void TamaTac::onHide(AppHandle context) {
if (updateTimer != nullptr) {
xTimerStop(updateTimer, portMAX_DELAY);
xTimerDelete(updateTimer, portMAX_DELAY);
updateTimer = nullptr;
}
if (sfxEngine) {
sfxEngine->stop();
delete sfxEngine;
sfxEngine = nullptr;
}
stopActiveView();
wrapperWidget = nullptr;
toolbar = nullptr;
menuButton = nullptr;
}
void TamaTac::onDestroy(AppHandle app) {
// Acquire mutex to guarantee any in-flight timer callback has completed.
// The callback holds this mutex for its entire duration, so taking it
// here blocks until the callback is done — no arbitrary delay needed.
if (timerMutex != nullptr) {
xSemaphoreTake(timerMutex, portMAX_DELAY);
}
if (petLogic) {
petLogic->saveState();
delete petLogic;
petLogic = nullptr;
}
if (timerMutex != nullptr) {
xSemaphoreGive(timerMutex);
vSemaphoreDelete(timerMutex);
timerMutex = nullptr;
}
currentApp = nullptr;
}
void TamaTac::onResult(AppHandle app, void* data, AppLaunchId launchId, AppResult result, BundleHandle resultData) {
if (launchId == resetDialogId) {
int32_t buttonIndex = tt_app_alertdialog_get_result_index(resultData);
if (buttonIndex == 0) {
// User clicked "Reset" (first button)
if (timerMutex) xSemaphoreTake(timerMutex, portMAX_DELAY);
if (petLogic) {
petLogic->reset();
petLogic->saveState();
lastKnownStage = LifeStage::Egg;
pendingResetUI = true; // Defer UI update to LVGL task
}
if (timerMutex) xSemaphoreGive(timerMutex);
}
resetDialogId = 0;
}
}
//==============================================================================================
// View Management
//==============================================================================================
void TamaTac::stopActiveView() {
switch (activeView) {
case ViewType::Main:
mainView.onStop();
break;
case ViewType::Menu:
menuView.onStop();
break;
case ViewType::Stats:
statsView.onStop();
break;
case ViewType::Settings:
settingsView.onStop();
break;
case ViewType::PatternGameView:
patternGame.onStop();
break;
case ViewType::ReactionGameView:
reactionGame.onStop();
break;
case ViewType::CemeteryViewType:
cemeteryView.onStop();
break;
case ViewType::AchievementsViewType:
achievementsView.onStop();
break;
case ViewType::None:
break;
}
if (wrapperWidget) {
lv_obj_clean(wrapperWidget);
}
activeView = ViewType::None;
}
void TamaTac::showMainView() {
stopActiveView();
activeView = ViewType::Main;
mainView.onStart(wrapperWidget, this);
mainView.updateUI(petLogic, lastKnownStage);
}
void TamaTac::showMenuView() {
stopActiveView();
activeView = ViewType::Menu;
menuView.onStart(wrapperWidget, this);
}
void TamaTac::showStatsView() {
stopActiveView();
activeView = ViewType::Stats;
statsView.onStart(wrapperWidget, this);
statsView.updateStats(petLogic);
}
void TamaTac::showSettingsView() {
stopActiveView();
activeView = ViewType::Settings;
settingsView.onStart(wrapperWidget, this);
}
void TamaTac::showCemeteryView() {
stopActiveView();
activeView = ViewType::CemeteryViewType;
cemeteryView.onStart(wrapperWidget, this);
}
void TamaTac::showAchievementsView() {
stopActiveView();
activeView = ViewType::AchievementsViewType;
achievementsView.onStart(wrapperWidget, this);
}
//==============================================================================================
// Settings Handlers
//==============================================================================================
void TamaTac::setSoundEnabled(bool enabled) {
if (sfxEngine) {
sfxEngine->setEnabled(enabled);
}
}
void TamaTac::setDecaySpeed(DecaySpeed speed) {
decaySpeed = speed;
PetLogic::setDecaySpeed(static_cast<uint8_t>(speed));
}
//==============================================================================================
// Action Handlers (called by MainView)
//==============================================================================================
void TamaTac::handleFeedAction() {
if (timerMutex) xSemaphoreTake(timerMutex, portMAX_DELAY);
if (petLogic) {
petLogic->performAction(PetAction::Feed);
petLogic->saveState();
mainView.updateUI(petLogic, lastKnownStage);
if (sfxEngine) sfxEngine->play(SfxId::Feed);
AchievementsView::unlock(AchievementId::FirstFeed);
char msg[64];
snprintf(msg, sizeof(msg), "Fed! Hunger: %d%%", petLogic->getHunger());
mainView.setStatusText(msg);
}
if (timerMutex) xSemaphoreGive(timerMutex);
}
void TamaTac::handlePlayAction() {
if (timerMutex) xSemaphoreTake(timerMutex, portMAX_DELAY);
bool canPlay = petLogic && !petLogic->isDead();
DayPhase phase = canPlay ? petLogic->getDayPhase() : DayPhase::Day;
if (timerMutex) xSemaphoreGive(timerMutex);
if (canPlay) {
AchievementsView::unlock(AchievementId::FirstPlay);
if (phase == DayPhase::Night) {
AchievementsView::unlock(AchievementId::NightOwl);
}
if (rand() % 2 == 0) {
showPatternGame();
} else {
showReactionGame();
}
}
}
void TamaTac::handlePetTap() {
if (activeView != ViewType::Main) return;
if (timerMutex) xSemaphoreTake(timerMutex, portMAX_DELAY);
if (!petLogic || petLogic->isDead()) {
if (timerMutex) xSemaphoreGive(timerMutex);
return;
}
// 3-second cooldown between pets
uint32_t now = tt::kernel::getMillis();
if (now - lastPetTime < 3000) {
if (timerMutex) xSemaphoreGive(timerMutex);
return;
}
lastPetTime = now;
petLogic->performAction(PetAction::Pet);
petLogic->saveState();
mainView.updateUI(petLogic, lastKnownStage);
if (timerMutex) xSemaphoreGive(timerMutex);
if (sfxEngine) sfxEngine->play(SfxId::Chirp);
}
void TamaTac::showPatternGame() {
stopActiveView();
activeView = ViewType::PatternGameView;
patternGame.onStart(wrapperWidget, this);
}
void TamaTac::showReactionGame() {
stopActiveView();
activeView = ViewType::ReactionGameView;
reactionGame.onStart(wrapperWidget, this);
}
void TamaTac::onReactionGameComplete(int score, bool won) {
if (timerMutex) xSemaphoreTake(timerMutex, portMAX_DELAY);
if (petLogic) {
int clampedScore = std::max(0, std::min(score, ReactionGame::MAX_ROUNDS));
petLogic->applyPlayResult(clampedScore, ReactionGame::MAX_ROUNDS);
petLogic->saveState();
}
if (timerMutex) xSemaphoreGive(timerMutex);
if (won) AchievementsView::unlock(AchievementId::PerfectGame);
if (sfxEngine) sfxEngine->play(SfxId::Play);
showMainView();
}
void TamaTac::onPatternGameComplete(int score, bool won) {
if (timerMutex) xSemaphoreTake(timerMutex, portMAX_DELAY);
if (petLogic) {
int clampedScore = std::max(0, std::min(score, PatternGame::MAX_ROUNDS));
petLogic->applyPlayResult(clampedScore, PatternGame::MAX_ROUNDS);
petLogic->saveState();
}
if (timerMutex) xSemaphoreGive(timerMutex);
if (won) AchievementsView::unlock(AchievementId::PerfectGame);
if (sfxEngine) sfxEngine->play(SfxId::Play);
showMainView();
}
void TamaTac::handleMedicineAction() {
if (timerMutex) xSemaphoreTake(timerMutex, portMAX_DELAY);
if (petLogic) {
bool wasSick = petLogic->isSick();
petLogic->performAction(PetAction::Medicine);
petLogic->saveState();
mainView.updateUI(petLogic, lastKnownStage);
if (sfxEngine) sfxEngine->play(SfxId::Medicine);
if (wasSick && !petLogic->isSick()) {
AchievementsView::unlock(AchievementId::FirstCure);
mainView.setStatusText("Cured!");
} else {
mainView.setStatusText("Medicine given");
}
}
if (timerMutex) xSemaphoreGive(timerMutex);
}
void TamaTac::handleSleepAction() {
if (timerMutex) xSemaphoreTake(timerMutex, portMAX_DELAY);
if (petLogic) {
petLogic->performAction(PetAction::Sleep);
petLogic->saveState();
mainView.updateUI(petLogic, lastKnownStage);
if (sfxEngine) sfxEngine->play(SfxId::Sleep);
char msg[64];
snprintf(msg, sizeof(msg), "Sleeping... Energy: %d%%", petLogic->getEnergy());
mainView.setStatusText(msg);
}
if (timerMutex) xSemaphoreGive(timerMutex);
}
//==============================================================================================
// Timer Callback
//==============================================================================================
void TamaTac::onTimerUpdate(TimerHandle_t timer) {
// Hold mutex for entire callback so onDestroy() can block until we finish
if (timerMutex == nullptr || xSemaphoreTake(timerMutex, 0) != pdTRUE) return;
if (petLogic == nullptr) {
xSemaphoreGive(timerMutex);
return;
}
bool wasAlive = !petLogic->isDead();
// Capture stage before update() — checkHealth() sets stage to Ghost on death
LifeStage stageBeforeDeath = petLogic->getStats().stage;
uint32_t now = tt::kernel::getMillis();
petLogic->update(now);
petLogic->saveState();
// Check achievements
const PetStats& stats = petLogic->getStats();
// Evolution achievements
switch (stats.stage) {
case LifeStage::Baby: AchievementsView::unlock(AchievementId::ReachBaby); break;
case LifeStage::Teen: AchievementsView::unlock(AchievementId::ReachTeen); break;
case LifeStage::Adult: AchievementsView::unlock(AchievementId::ReachAdult); break;
case LifeStage::Elder: AchievementsView::unlock(AchievementId::ReachElder); break;
default: break;
}
// Survival achievement
if (stats.ageHours >= 24 && !stats.isDead) {
AchievementsView::unlock(AchievementId::Survivor24h);
}
// Full stats achievement
if (stats.hunger >= 90 && stats.happiness >= 90 && stats.health >= 90 && stats.energy >= 90) {
AchievementsView::unlock(AchievementId::FullStats);
}
// Record death in cemetery (use pre-death stage, not Ghost)
if (wasAlive && petLogic->isDead()) {
CemeteryView::recordDeath(stats.personality, stageBeforeDeath, stats.ageHours);
}
xSemaphoreGive(timerMutex);
}
//==============================================================================================
// Event Handlers
//==============================================================================================
void TamaTac::onCleanClicked(lv_event_t* e) {
TamaTac* app = static_cast<TamaTac*>(lv_event_get_user_data(e));
if (app == nullptr) return;
if (timerMutex) xSemaphoreTake(timerMutex, portMAX_DELAY);
if (petLogic && app->activeView == ViewType::Main) {
int poopCount = petLogic->getStats().poopCount;
if (poopCount > 0) {
petLogic->performAction(PetAction::Clean);
petLogic->saveState();
app->mainView.updateUI(petLogic, lastKnownStage);
if (sfxEngine) sfxEngine->play(SfxId::Clean);
AchievementsView::incrementCleanCount();
app->mainView.setStatusText("All clean!");
} else {
app->mainView.setStatusText("Nothing to clean!");
}
}
if (timerMutex) xSemaphoreGive(timerMutex);
}
void TamaTac::onMenuClicked(lv_event_t* e) {
TamaTac* app = static_cast<TamaTac*>(lv_event_get_user_data(e));
if (app == nullptr) return;
if (app->activeView == ViewType::Main) {
app->showMenuView();
} else {
app->showMainView();
}
}
void TamaTac::onResetClicked([[maybe_unused]] lv_event_t* e) {
const char* buttons[] = {"Reset", "Cancel"};
resetDialogId = tt_app_alertdialog_start(
"Reset Pet?",
"This will start over with a new pet. Your current pet will be lost forever!",
buttons,
2
);
}
+130
View File
@@ -0,0 +1,130 @@
/**
* @file TamaTac.h
* @brief TamaTac virtual pet app for Tactility
*/
#pragma once
#include <TactilityCpp/App.h>
#include <tt_app.h>
#include <lvgl.h>
#include <freertos/FreeRTOS.h>
#include <freertos/semphr.h>
#include "PetLogic.h"
#include "Sprites.h"
#include "MainView.h"
#include "StatsView.h"
#include "MenuView.h"
#include "SettingsView.h"
#include "PatternGame.h"
#include "ReactionGame.h"
#include "CemeteryView.h"
#include "Achievements.h"
#include "SfxEngine.h"
// Canvas buffers for sprite rendering (shared by views)
extern lv_color_t TamaTac_canvasBuffer[72 * 72];
extern lv_color_t TamaTac_iconBuffers[12][16 * 16];
class TamaTac final : public App {
public:
// Active view type (scoped to TamaTac class)
enum class ViewType {
None,
Main,
Menu,
Stats,
Settings,
PatternGameView,
ReactionGameView,
CemeteryViewType,
AchievementsViewType
};
private:
// UI elements
lv_obj_t* toolbar = nullptr;
lv_obj_t* wrapperWidget = nullptr;
lv_obj_t* menuButton = nullptr;
// Views
MainView mainView;
StatsView statsView;
MenuView menuView;
SettingsView settingsView;
PatternGame patternGame;
ReactionGame reactionGame;
CemeteryView cemeteryView;
AchievementsView achievementsView;
ViewType activeView = ViewType::None;
// Static data (singleton — only one TamaTac instance exists at a time)
static PetLogic* petLogic;
static TimerHandle_t updateTimer;
static SemaphoreHandle_t timerMutex;
static AppHandle currentApp;
static AppLaunchId resetDialogId;
static LifeStage lastKnownStage;
static SfxEngine* sfxEngine;
static DecaySpeed decaySpeed;
static uint32_t lastPetTime;
static bool pendingResetUI;
public:
void onCreate(AppHandle app) override;
void onShow(AppHandle context, lv_obj_t* parent) override;
void onHide(AppHandle context) override;
void onDestroy(AppHandle app) override;
void onResult(AppHandle app, void* data, AppLaunchId launchId, AppResult result, BundleHandle resultData) override;
// Action handlers (called by MainView)
void handleFeedAction();
void handlePlayAction();
void handleMedicineAction();
void handleSleepAction();
void handlePetTap();
// Mini-game callbacks
void onPatternGameComplete(int roundsCompleted, bool won);
void onReactionGameComplete(int score, bool won);
// Settings handlers (called by SettingsView)
void setSoundEnabled(bool enabled);
void setDecaySpeed(DecaySpeed speed);
// View navigation (called by MenuView)
void showMainView();
void showStatsView();
void showSettingsView();
void showCemeteryView();
void showAchievementsView();
// Getters (note: getSfxEngine() may return nullptr before onCreate() or after onDestroy())
static DecaySpeed getDecaySpeed() { return decaySpeed; }
static SfxEngine* getSfxEngine() { return sfxEngine; }
private:
// View management
void stopActiveView();
void showMenuView();
// Timer callback (called every 30 seconds)
static void onTimerUpdate(TimerHandle_t timer);
// Event handlers
static void onCleanClicked(lv_event_t* e);
static void onMenuClicked(lv_event_t* e);
static void onResetClicked(lv_event_t* e);
// View navigation (internal)
void showPatternGame();
void showReactionGame();
friend class MainView;
friend class StatsView;
friend class MenuView;
friend class SettingsView;
friend class PatternGame;
friend class ReactionGame;
friend class CemeteryView;
friend class AchievementsView;
};
+11
View File
@@ -0,0 +1,11 @@
#include "TamaTac.h"
#include <TactilityCpp/App.h>
extern "C" {
int main(int argc, char* argv[]) {
registerApp<TamaTac>();
return 0;
}
}
+11
View File
@@ -0,0 +1,11 @@
[manifest]
version=0.1
[target]
sdk=0.7.0-dev
platforms=esp32,esp32s3,esp32c6,esp32p4
[app]
id=one.tactility.tamatac
versionName=0.1.0
versionCode=1
name=TamaTac
description=Virtual pet inspired by Tamagotchi. Only runs on devices with PSRAM.
Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 B