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