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
+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;
}
}