TamaTac & SfxEngine + Sprite tools (#24)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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]);
|
||||
};
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
};
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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},
|
||||
};
|
||||
@@ -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];
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "TamaTac.h"
|
||||
#include <TactilityCpp/App.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
registerApp<TamaTac>();
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user