mirror of
https://github.com/nacabaro/nacapet.git
synced 2026-10-01 07:31:38 +00:00
Compare commits
16
Commits
0b5c56b5e3
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b869f22f3 | ||
|
|
cde99fc554 | ||
|
|
91e00bea43 | ||
|
|
94c4543b59 | ||
|
|
915c5cd2a7 | ||
|
|
79d60e7201 | ||
|
|
3de6c121a5 | ||
|
|
f15ea8190f | ||
|
|
9c4520e4e0 | ||
|
|
60c1659875 | ||
|
|
e158f50970 | ||
|
|
f8f7c7a9b6 | ||
|
|
24ebd8a5af | ||
|
|
82a7d76b92 | ||
|
|
2ae5bc8bd4 | ||
|
|
dc44a695be |
@@ -9,6 +9,11 @@
|
||||
*.egg
|
||||
*.cm
|
||||
*.png
|
||||
*.jpg
|
||||
*.webp
|
||||
*.adv
|
||||
*.coli
|
||||
ideas/
|
||||
__pycache__/
|
||||
venv/
|
||||
sprites/
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0x9000, 0x7000,
|
||||
app0, app, factory, 0x10000, 0xA0000,
|
||||
spiffs, data, spiffs, 0xB0000, 0x350000,
|
||||
|
+3
-8
@@ -20,20 +20,17 @@ lib_deps =
|
||||
fbiego/ESP32Time@^2.0.6
|
||||
electroniccats/MPU6050@^1.4.3
|
||||
|
||||
; --- Hardware & Memory Topology ---
|
||||
board_build.arduino.psram = enabled
|
||||
board_upload.flash_size = 16MB
|
||||
board_build.partitions = default_16MB.csv
|
||||
|
||||
; FIX 2: Explicitly matches the 'mode:DIO' your ROM is reporting
|
||||
board_build.flash_mode = dio
|
||||
board_build.arduino.memory_type = dio_opi
|
||||
|
||||
build_flags =
|
||||
-DBOARD_HAS_PSRAM
|
||||
; FIX 1: Forces all Serial.print logs to stay on the hardware UART port
|
||||
-DARDUINO_USB_CDC_ON_BOOT=0
|
||||
-DDEV_UNIT
|
||||
-DDISALLOW_SLEEP
|
||||
-DDEBUG
|
||||
|
||||
upload_port = COM8
|
||||
@@ -44,21 +41,19 @@ platform = espressif32
|
||||
board = esp32-s3-devkitc-1
|
||||
framework = arduino
|
||||
|
||||
; Flash and PSRAM settings for 4MB Flash / 2MB PSRAM (Quad SPI)
|
||||
board_upload.flash_size = 4MB
|
||||
board_build.arduino.memory_type = qio_qspi
|
||||
board_build.flash_mode = qio
|
||||
board_build.psram_type = qio
|
||||
|
||||
; Required flag to enable PSRAM in code
|
||||
build_flags =
|
||||
-DBOARD_HAS_PSRAM
|
||||
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||
-DARDUINO_USB_MODE=1
|
||||
-DDISALLOW_SLEEP
|
||||
-DDEV_UNIT
|
||||
|
||||
; Ensure partition table fits 4MB
|
||||
board_build.partitions = default.csv
|
||||
board_build.partitions = partitions_4MB.csv
|
||||
lib_deps = TFT_eSPI, fbiego/ESP32Time@^2.0.6, electroniccats/MPU6050@^1.4.3
|
||||
upload_port = COM5
|
||||
monitor_port = COM5
|
||||
@@ -95,7 +95,7 @@ void animate_performAngryAnimation(TFT_eSprite &spr, struct SpriteData* spriteDa
|
||||
}
|
||||
|
||||
void animate_performHatchingAnimation(TFT_eSprite &spr, struct SpriteData* spriteData) {
|
||||
currentAnimationFrame = (currentAnimationFrame + 1) % numFramesHappy;
|
||||
currentAnimationFrame = (currentAnimationFrame + 1) % numFramesHatching;
|
||||
draw_drawSprite(
|
||||
spr,
|
||||
hatchingAnimationPositions[currentAnimationFrame],
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "defs/defs.h"
|
||||
#include "defs/sounds.h"
|
||||
#include "defs/chara_data.h"
|
||||
#include "defs/screen_defs.h"
|
||||
#include "buttons.h"
|
||||
@@ -16,9 +17,11 @@ bool k4_prev = HIGH;
|
||||
|
||||
void buttons_checkInactivity() {
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
if (currentTime - lastPressedButtonTime > INACTIVITY_THRESHOLD_TIME_US && !screenOff) {
|
||||
if (currentTime - lastPressedButtonTime > INACTIVITY_THRESHOLD_TIME_US && !screenOff && !alwaysOnEnabled) {
|
||||
#ifdef DISALLOW_SLEEP
|
||||
digitalWrite(BL_PIN, LOW);
|
||||
screenKey = OFF_SCREEN;
|
||||
#endif
|
||||
|
||||
} else if (currentTime - lastPressedButtonTime > LAST_PRESSED_BUTTON_THRESHOLD_TIME_US && !inactive) {
|
||||
screenKey = MAIN_SCREEN;
|
||||
@@ -40,7 +43,7 @@ uint8_t buttons_getPressedButtons() {
|
||||
);
|
||||
|
||||
if (retV != 0) {
|
||||
tone(SPK_PIN, BEEP_FREQ_HZ, BEEP_LEN_MS);
|
||||
sound_playMelody(SOUND_BUTTON_BEEP, SOUND_NOTE_COUNT(SOUND_BUTTON_BEEP));
|
||||
lastPressedButtonTime = esp_timer_get_time();
|
||||
inactive = false;
|
||||
screenOff = false;
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern int currentBackground;
|
||||
|
||||
struct BackgroundData {
|
||||
uint8_t backgroundWidth;
|
||||
uint8_t backgroundHeight;
|
||||
|
||||
@@ -125,6 +125,10 @@
|
||||
// TRAINING MODES
|
||||
#define TRAINING_SCREEN_1 30
|
||||
|
||||
// SETTINGS SUBSCREENS
|
||||
#define BACKGROUND_CHANGE_SCREEN 40
|
||||
#define RESET_DATA_SCREEN 41
|
||||
|
||||
// SMALL UI ICONS (UI.BIN)
|
||||
#define POOP_ICON 0
|
||||
#define FOOD_ICON 1
|
||||
@@ -164,6 +168,8 @@
|
||||
|
||||
#define CHARA_COUNT_IN_DEVICE 5
|
||||
|
||||
#define SPRITE_SCALE 6
|
||||
|
||||
extern int screenKey;
|
||||
extern int menuKey;
|
||||
extern int submenuKey;
|
||||
@@ -215,4 +221,8 @@ extern bool isSamplingSteps;
|
||||
extern uint64_t sampleStartTime;
|
||||
extern uint16_t initialSteps;
|
||||
|
||||
// Settings screen options
|
||||
extern bool soundEnabled;
|
||||
extern bool alwaysOnEnabled;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,121 @@
|
||||
#ifndef SOUNDS_H
|
||||
#define SOUNDS_H
|
||||
|
||||
#include "defs/defs.h"
|
||||
#include "sound/sound.h"
|
||||
|
||||
#define SOUND_NOTE_COUNT(melody) (sizeof(melody) / sizeof((melody)[0]))
|
||||
|
||||
static const Note SOUND_BUTTON_BEEP[] = {
|
||||
{BEEP_FREQ_HZ, BEEP_LEN_MS},
|
||||
};
|
||||
|
||||
static const Note SOUND_BOOT[] = {
|
||||
{1800, 55},
|
||||
{0, 20},
|
||||
{2600, 55},
|
||||
{0, 20},
|
||||
{3400, 70},
|
||||
{0, 35},
|
||||
{4600, 95},
|
||||
};
|
||||
|
||||
static const Note SOUND_CARE_ALERT[] = {
|
||||
{1800, 80},
|
||||
{0, 35},
|
||||
{1800, 80},
|
||||
{0, 35},
|
||||
{5200, 120},
|
||||
};
|
||||
|
||||
static const Note SOUND_HAPPY[] = {
|
||||
{2200, 45},
|
||||
{3300, 45},
|
||||
{4400, 55},
|
||||
{6600, 80},
|
||||
{0, 25},
|
||||
{5200, 60},
|
||||
};
|
||||
|
||||
static const Note SOUND_ANGRY[] = {
|
||||
{900, 70},
|
||||
{0, 25},
|
||||
{700, 90},
|
||||
{0, 25},
|
||||
{520, 150},
|
||||
};
|
||||
|
||||
static const Note SOUND_POOP_DROP[] = {
|
||||
{4200, 35},
|
||||
{3200, 35},
|
||||
{2200, 45},
|
||||
{0, 25},
|
||||
{900, 85},
|
||||
};
|
||||
|
||||
static const Note SOUND_REFUSE[] = {
|
||||
{2600, 70},
|
||||
{0, 35},
|
||||
{1500, 80},
|
||||
{0, 30},
|
||||
{900, 120},
|
||||
};
|
||||
|
||||
static const Note SOUND_EVOLUTION_WOBBLE[] = {
|
||||
{3200, 60},
|
||||
{3900, 60},
|
||||
{3000, 60},
|
||||
{4300, 60},
|
||||
{3400, 60},
|
||||
{4700, 70},
|
||||
};
|
||||
|
||||
static const Note SOUND_EVOLUTION_COMPLETE[] = {
|
||||
{1600, 90},
|
||||
{2200, 90},
|
||||
{3000, 100},
|
||||
{4000, 110},
|
||||
{5200, 130},
|
||||
{6400, 220},
|
||||
{0, 60},
|
||||
{5200, 100},
|
||||
{6400, 180},
|
||||
};
|
||||
|
||||
static const Note SOUND_TRAINING_START[] = {
|
||||
{3100, 55},
|
||||
{0, 25},
|
||||
{4100, 85},
|
||||
};
|
||||
|
||||
static const Note SOUND_TRAINING_ATTACK[] = {
|
||||
{5200, 18},
|
||||
{0, 8},
|
||||
{4600, 18},
|
||||
{0, 8},
|
||||
{3900, 22},
|
||||
{0, 12},
|
||||
{3000, 28},
|
||||
};
|
||||
|
||||
static const Note SOUND_HATCH[] = {
|
||||
{2200, 45},
|
||||
{0, 20},
|
||||
{2600, 45},
|
||||
{0, 20},
|
||||
{3000, 45},
|
||||
{0, 20},
|
||||
{3400, 45},
|
||||
{0, 20},
|
||||
{3800, 50},
|
||||
{0, 25},
|
||||
{4300, 55},
|
||||
{0, 30},
|
||||
{5000, 75},
|
||||
{0, 45},
|
||||
{3600, 55},
|
||||
{4300, 55},
|
||||
{5200, 110},
|
||||
};
|
||||
|
||||
#endif
|
||||
+10
-2
@@ -2,6 +2,8 @@
|
||||
#include "defs/screen_defs.h"
|
||||
#include "defs/defs.h"
|
||||
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
int xPos = 0;
|
||||
int yPos = 0;
|
||||
|
||||
@@ -59,9 +61,15 @@ void tft_drawCenteredText(const char* text, int size, int yGlobal) {
|
||||
composite.drawString(text, x, yGlobal);
|
||||
}
|
||||
|
||||
void tft_drawText(const char* text, int size, int x, int y, uint16_t color) {
|
||||
void tft_drawText(const char* text, int size, int x, int y, uint16_t color, uint16_t bgColor) {
|
||||
composite.setTextSize(size);
|
||||
composite.setTextColor(color);
|
||||
|
||||
if (bgColor != TFT_TRANSPARENT) {
|
||||
composite.setTextColor(color, bgColor);
|
||||
} else {
|
||||
composite.setTextColor(color);
|
||||
}
|
||||
|
||||
composite.drawString(text, x, y);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ void tft_drawBuffer();
|
||||
void tft_clearBuffer(TFT_eSprite &buffer, uint16_t color = TFT_WHITE);
|
||||
void tft_clearBuffer(uint16_t color = TFT_WHITE);
|
||||
void tft_drawCenteredText(const char* text, int factor, int y);
|
||||
void tft_drawText(const char* text, int size, int x, int y, uint16_t color = TFT_BLACK);
|
||||
void tft_drawText(const char* text, int size, int x, int y, uint16_t color = TFT_BLACK, uint16_t bgColor = TFT_TRANSPARENT);
|
||||
void tft_drawRectangle(int x, int y, int w, int h, uint16_t color = TFT_BLACK);
|
||||
|
||||
#endif
|
||||
+31
-2
@@ -15,6 +15,8 @@
|
||||
#include "driver/rtc_io.h"
|
||||
#include "loop/loop.h"
|
||||
#include "menu/training/training_screens.h"
|
||||
#include "defs/sounds.h"
|
||||
#include "sound/sound.h"
|
||||
|
||||
const char* TAG = "[MAIN]";
|
||||
|
||||
@@ -61,9 +63,17 @@ uint32_t dayUnixTime = 0;
|
||||
Egg_t* eggSelection = NULL;
|
||||
uint8_t eggNumber = 0;
|
||||
|
||||
// Background stuff
|
||||
int currentBackground = 0;
|
||||
|
||||
// Tasks
|
||||
TaskHandle_t secondLoop = NULL;
|
||||
|
||||
// Settings
|
||||
bool soundEnabled = true;
|
||||
bool alwaysOnEnabled = false;
|
||||
|
||||
// Background step counting
|
||||
bool isSamplingSteps = false;
|
||||
uint64_t sampleStartTime = 0;
|
||||
uint16_t initialSteps = 0;
|
||||
@@ -87,12 +97,16 @@ void setup() {
|
||||
tft_initDisplay(tft, TFT_BLACK);
|
||||
tft_initScreenBuffer(TFT_TRANSPARENT);
|
||||
|
||||
tft.setRotation(2);
|
||||
|
||||
sound_init();
|
||||
|
||||
storage_init();
|
||||
|
||||
storage_readFile("/menu.bin", &menuElementsData);
|
||||
storage_readFile("/ui.bin", &uiElementsData);
|
||||
|
||||
storage_initBackground("/bg2.bin", bg);
|
||||
storage_initBackground(currentBackground, bg);
|
||||
|
||||
pinMode(K1_PIN, BUTTON_MODE);
|
||||
pinMode(K2_PIN, BUTTON_MODE);
|
||||
@@ -101,6 +115,8 @@ void setup() {
|
||||
|
||||
xTaskCreatePinnedToCore(secondCoreTask, "VPET_EVAL", 4096, NULL, 0, &secondLoop, 0);
|
||||
|
||||
sound_playMelody(SOUND_BOOT, SOUND_NOTE_COUNT(SOUND_BOOT));
|
||||
|
||||
lines_initLineStorage();
|
||||
|
||||
storage_loadState();
|
||||
@@ -213,6 +229,18 @@ void loop() {
|
||||
case FROZEN_SCREEN:
|
||||
menu_drawFridgeScreen(bg, sprite, &mainCharacterSprites, &menuElementsData);
|
||||
break;
|
||||
|
||||
case SETTINGS_SCREEN:
|
||||
menu_settingsScreen(bg, sprite, &uiElementsData);
|
||||
break;
|
||||
|
||||
case BACKGROUND_CHANGE_SCREEN:
|
||||
menu_changeBackgroundScreen(bg, sprite, &uiElementsData);
|
||||
break;
|
||||
|
||||
case RESET_DATA_SCREEN:
|
||||
menu_resetDataScreen(bg);
|
||||
break;
|
||||
}
|
||||
|
||||
if (screenKey == IDLE_SCREEN || screenKey == OFF_SCREEN) {
|
||||
@@ -241,7 +269,6 @@ void loop2() {
|
||||
stepCounter += approximatedSteps;
|
||||
|
||||
printf("[STEPS] Sampled %d steps in 10s, added %d approximated steps for sleep period.\n", sampledSteps, approximatedSteps);
|
||||
|
||||
energy_startLightSleep();
|
||||
}
|
||||
} else {
|
||||
@@ -250,6 +277,8 @@ void loop2() {
|
||||
} else {
|
||||
isSamplingSteps = false;
|
||||
}
|
||||
|
||||
sound_update();
|
||||
}
|
||||
|
||||
void secondCoreTask(void*) {
|
||||
|
||||
+24
-28
@@ -4,43 +4,39 @@
|
||||
#include "display/display.h"
|
||||
#include "draw/draw.h"
|
||||
#include "animations/animations.h"
|
||||
#include "defs/sounds.h"
|
||||
|
||||
void menu_drawAngryScreen(
|
||||
TFT_eSprite& bg, TFT_eSprite &sprite,
|
||||
struct SpriteData* spriteData, struct SpriteData* smallUiElements
|
||||
) {
|
||||
uint8_t frameCounter = 0;
|
||||
static uint8_t frameCounter = 0;
|
||||
|
||||
while (true) {
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
if (currentTime - lastUpdateTime > ANIMATION_THRESHOLD_TIME_US) {
|
||||
if (frameCounter > 3) {
|
||||
screenKey = MAIN_SCREEN; // TODO: Change for while battling
|
||||
menuKey = STATUS_SCREEN;
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
if (currentTime - lastUpdateTime > ANIMATION_THRESHOLD_TIME_US) {
|
||||
if (frameCounter > 3) {
|
||||
frameCounter = 0;
|
||||
screenKey = MAIN_SCREEN; // TODO: Change for while battling
|
||||
menuKey = STATUS_SCREEN;
|
||||
|
||||
vTaskResume(secondLoop);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
animate_performAngryAnimation(sprite, spriteData);
|
||||
|
||||
if (frameCounter % 2 == 0) {
|
||||
tone(SPK_PIN, 1000, 100);
|
||||
tone(SPK_PIN, 1000, 200);
|
||||
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
draw_drawSprite(sprite, 18, 72, smallUiElements, FIREWORKS_ICON);
|
||||
draw_drawSprite(sprite, 174, 72, smallUiElements, FIREWORKS_ICON);
|
||||
}
|
||||
|
||||
frameCounter++;
|
||||
lastUpdateTime = currentTime;
|
||||
return;
|
||||
}
|
||||
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
animate_performAngryAnimation(sprite, spriteData);
|
||||
|
||||
if (frameCounter % 2 == 0) {
|
||||
sound_playMelody(SOUND_ANGRY, SOUND_NOTE_COUNT(SOUND_ANGRY));
|
||||
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
draw_drawSprite(sprite, 18, 72, smallUiElements, FIREWORKS_ICON);
|
||||
draw_drawSprite(sprite, 174, 72, smallUiElements, FIREWORKS_ICON);
|
||||
}
|
||||
|
||||
frameCounter++;
|
||||
lastUpdateTime = currentTime;
|
||||
tft_drawBuffer();
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "animations/animations.h"
|
||||
#include "display/display.h"
|
||||
#include "defs/chara_data.h"
|
||||
#include "defs/sounds.h"
|
||||
#include "draw/draw.h"
|
||||
|
||||
uint64_t lastBeepTime = esp_timer_get_time();
|
||||
@@ -13,8 +14,7 @@ void menu_careMistakeScreen(TFT_eSprite& bg, TFT_eSprite &sprite, struct SpriteD
|
||||
uint8_t pressedButtons = buttons_getPressedButtons();
|
||||
|
||||
if (currentTime - lastBeepTime > ANIMATION_THRESHOLD_TIME_US * 2 && beepCounter < 10) {
|
||||
tone(SPK_PIN, 2500, 100);
|
||||
tone(SPK_PIN, 5000, 100);
|
||||
sound_playMelody(SOUND_CARE_ALERT, SOUND_NOTE_COUNT(SOUND_CARE_ALERT));
|
||||
|
||||
lastBeepTime = currentTime;
|
||||
|
||||
|
||||
@@ -2,17 +2,22 @@
|
||||
#include "draw/draw.h"
|
||||
#include "display/display.h"
|
||||
#include "defs/screen_defs.h"
|
||||
#include "defs/sounds.h"
|
||||
#include "vpet/evolution/evolution.h"
|
||||
#include "loop/loop.h"
|
||||
|
||||
struct SpriteData* checkerboardPattern;
|
||||
|
||||
void menu_createCheckerboard() {
|
||||
if (checkerboardPattern != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t SCALE = 6;
|
||||
const uint8_t logicalW = 34;
|
||||
const uint8_t logicalH = 1;
|
||||
const uint16_t scaledW = logicalW * SCALE; // 204
|
||||
const uint16_t scaledH = logicalH * SCALE; // 6
|
||||
const uint16_t scaledW = logicalW * SCALE;
|
||||
const uint16_t scaledH = logicalH * SCALE;
|
||||
const uint32_t bufferSize = scaledW * scaledH;
|
||||
|
||||
checkerboardPattern = (SpriteData*) malloc(sizeof(SpriteData));
|
||||
@@ -36,126 +41,178 @@ void menu_createCheckerboard() {
|
||||
}
|
||||
|
||||
void menu_freeCheckerboard() {
|
||||
if (checkerboardPattern == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
free(checkerboardPattern->spriteData[0]);
|
||||
free(checkerboardPattern->spriteData);
|
||||
free(checkerboardPattern);
|
||||
|
||||
checkerboardPattern = NULL;
|
||||
}
|
||||
|
||||
// Don't worry, I hate this too
|
||||
void menu_evolutionScreen(TFT_eSprite& bg, TFT_eSprite &sprite, struct SpriteData* mainCharacterSprites) {
|
||||
menu_createCheckerboard();
|
||||
TFT_eSprite checkerboard = TFT_eSprite(&tft);
|
||||
enum EvolutionPhase {
|
||||
EVOLUTION_INIT,
|
||||
EVOLUTION_WOBBLE,
|
||||
EVOLUTION_RED_FILL,
|
||||
EVOLUTION_BLACK_FILL,
|
||||
EVOLUTION_APPLY_CHANGE,
|
||||
EVOLUTION_GREEN_REVEAL,
|
||||
EVOLUTION_FINAL_REVEAL,
|
||||
EVOLUTION_DONE
|
||||
};
|
||||
|
||||
bool checkerboardShift = false;
|
||||
static EvolutionPhase phase = EVOLUTION_INIT;
|
||||
static TFT_eSprite checkerboard = TFT_eSprite(&tft);
|
||||
static bool checkerboardShift = false;
|
||||
static int frameIndex = 0;
|
||||
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
sound_update();
|
||||
|
||||
for (int i = 0; i < 5;) {
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
|
||||
if (phase == EVOLUTION_INIT) {
|
||||
menu_createCheckerboard();
|
||||
checkerboardShift = false;
|
||||
frameIndex = 0;
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
lastUpdateTime = 0;
|
||||
phase = EVOLUTION_WOBBLE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (phase == EVOLUTION_WOBBLE) {
|
||||
if (frameIndex >= 5) {
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
draw_drawSprite(sprite, 72, 72, mainCharacterSprites, 7);
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
frameIndex = 0;
|
||||
lastUpdateTime = 0;
|
||||
phase = EVOLUTION_RED_FILL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentTime - lastUpdateTime > 500000) {
|
||||
tone(SPK_PIN, 4100, 50);
|
||||
tone(SPK_PIN, 3500, 50);
|
||||
sound_playMelody(SOUND_EVOLUTION_WOBBLE, SOUND_NOTE_COUNT(SOUND_EVOLUTION_WOBBLE));
|
||||
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
draw_drawSprite(sprite, 72 + ((i % 2 == 0) * 6), 72, mainCharacterSprites, 6);
|
||||
draw_drawSprite(sprite, 72 + ((frameIndex % 2 == 0) * 6), 72, mainCharacterSprites, 6);
|
||||
|
||||
tft_drawBuffer();
|
||||
|
||||
i++;
|
||||
frameIndex++;
|
||||
lastUpdateTime = currentTime;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
draw_drawSprite(sprite, 72, 72, mainCharacterSprites, 7);
|
||||
if (phase == EVOLUTION_RED_FILL) {
|
||||
if (frameIndex >= 16) {
|
||||
frameIndex = 0;
|
||||
lastUpdateTime = 0;
|
||||
phase = EVOLUTION_BLACK_FILL;
|
||||
return;
|
||||
}
|
||||
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
|
||||
for (int i = 0; i < 16;) {
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
if (currentTime - lastUpdateTime > 100000) {
|
||||
uint8_t startYPos = 72 + (i * 6);
|
||||
uint8_t startYPos = 72 + (frameIndex * 6);
|
||||
|
||||
tft_drawRectangle(18, startYPos, 204, 6, TFT_RED);
|
||||
|
||||
draw_drawSprite(checkerboard, 18, startYPos, checkerboardPattern, 0, checkerboardShift);
|
||||
|
||||
tft_drawBuffer();
|
||||
|
||||
checkerboardShift = !checkerboardShift;
|
||||
|
||||
i++;
|
||||
frameIndex++;
|
||||
lastUpdateTime = currentTime;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 16;) {
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
if (phase == EVOLUTION_BLACK_FILL) {
|
||||
if (frameIndex >= 16) {
|
||||
frameIndex = 15;
|
||||
lastUpdateTime = 0;
|
||||
phase = EVOLUTION_APPLY_CHANGE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentTime - lastUpdateTime > 100000) {
|
||||
uint8_t startYPos = 72 + (i * 6);
|
||||
uint8_t startYPos = 72 + (frameIndex * 6);
|
||||
|
||||
tft_drawRectangle(18, startYPos, 204, 6, TFT_BLACK);
|
||||
|
||||
tft_drawBuffer();
|
||||
|
||||
checkerboardShift = !checkerboardShift;
|
||||
|
||||
i++;
|
||||
frameIndex++;
|
||||
lastUpdateTime = currentTime;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
change_onChangeComplete();
|
||||
if (phase == EVOLUTION_APPLY_CHANGE) {
|
||||
change_onChangeComplete();
|
||||
lastUpdateTime = 0;
|
||||
phase = EVOLUTION_GREEN_REVEAL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (phase == EVOLUTION_GREEN_REVEAL) {
|
||||
if (frameIndex < 0) {
|
||||
frameIndex = 15;
|
||||
lastUpdateTime = 0;
|
||||
phase = EVOLUTION_FINAL_REVEAL;
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 15; i >= 0;) {
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
if (currentTime - lastUpdateTime > 100000) {
|
||||
uint8_t startYPos = 72 + (i * 6);
|
||||
uint8_t startYPos = 72 + (frameIndex * 6);
|
||||
|
||||
tft_drawRectangle(18, startYPos, 204, 6, TFT_GREEN);
|
||||
draw_drawSprite(checkerboard, 18, startYPos, checkerboardPattern, 0, checkerboardShift);
|
||||
|
||||
tft_drawBuffer();
|
||||
|
||||
checkerboardShift = !checkerboardShift;
|
||||
|
||||
i--;
|
||||
frameIndex--;
|
||||
lastUpdateTime = currentTime;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 15; i >= 0;) {
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
if (phase == EVOLUTION_FINAL_REVEAL) {
|
||||
if (frameIndex < 0) {
|
||||
phase = EVOLUTION_DONE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentTime - lastUpdateTime > 100000) {
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
draw_drawSprite(sprite, 72, 72, mainCharacterSprites, 7);
|
||||
|
||||
uint8_t rectHeight = (6 * i);
|
||||
uint8_t rectHeight = 6 * frameIndex;
|
||||
|
||||
tft_drawRectangle(18, 72, 204, rectHeight, TFT_GREEN);
|
||||
|
||||
for (int j = 0; j < i; j++) {
|
||||
for (int j = 0; j < frameIndex; j++) {
|
||||
uint8_t rectYPos = 72 + (6 * j);
|
||||
|
||||
draw_drawSprite(checkerboard, 18, rectYPos, checkerboardPattern, 0, checkerboardShift);
|
||||
|
||||
checkerboardShift = !checkerboardShift;
|
||||
}
|
||||
|
||||
tft_drawBuffer();
|
||||
i--;
|
||||
frameIndex--;
|
||||
lastUpdateTime = currentTime;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
tone(SPK_PIN, 2100, 100);
|
||||
tone(SPK_PIN, 3500, 100);
|
||||
tone(SPK_PIN, 4100, 100);
|
||||
tone(SPK_PIN, 4650, 200);
|
||||
|
||||
sound_playMelody(SOUND_EVOLUTION_COMPLETE, SOUND_NOTE_COUNT(SOUND_EVOLUTION_COMPLETE));
|
||||
|
||||
lastPressedButtonTime = esp_timer_get_time();
|
||||
|
||||
@@ -163,7 +220,8 @@ void menu_evolutionScreen(TFT_eSprite& bg, TFT_eSprite &sprite, struct SpriteDat
|
||||
|
||||
vTaskResume(secondLoop);
|
||||
|
||||
phase = EVOLUTION_INIT;
|
||||
screenKey = MAIN_SCREEN;
|
||||
|
||||
lastUpdateTime = 0; // Un pequeño empujoncito
|
||||
lastUpdateTime = 0;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
#include "menu.h"
|
||||
#include "defs/sprite_data.h"
|
||||
#include "buttons/buttons.h"
|
||||
#include "draw/draw.h"
|
||||
#include "storage/storage.h"
|
||||
#include "display/display.h"
|
||||
#include "defs/screen_defs.h"
|
||||
|
||||
void menu_changeBackgroundScreen(
|
||||
TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* uiSpriteData
|
||||
) {
|
||||
static bool initialized = false;
|
||||
static int8_t selectedBackground = 0;
|
||||
static int8_t selectedPreviousBackground = -1;
|
||||
static uint8_t backgrounds = 0;
|
||||
static uint64_t screenLastActionTime = 0;
|
||||
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
|
||||
if (!initialized) {
|
||||
fs::File bgFolder = SPIFFS.open("/bg");
|
||||
fs::File background = bgFolder.openNextFile();
|
||||
|
||||
backgrounds = 0;
|
||||
while (background) {
|
||||
if (!background.isDirectory()) {
|
||||
backgrounds++;
|
||||
}
|
||||
|
||||
background = bgFolder.openNextFile();
|
||||
}
|
||||
|
||||
selectedBackground = currentBackground;
|
||||
selectedPreviousBackground = -1;
|
||||
screenLastActionTime = currentTime;
|
||||
initialized = true;
|
||||
|
||||
printf("[BACKGROUNDS] numBackgrounds=%i\n", backgrounds);
|
||||
}
|
||||
|
||||
uint8_t buttonsPressed = buttons_getPressedButtons();
|
||||
|
||||
switch (buttonsPressed) {
|
||||
case K1_PRESSED:
|
||||
selectedBackground--;
|
||||
if (selectedBackground < 0) {
|
||||
selectedBackground = backgrounds - 1;
|
||||
}
|
||||
storage_initBackground(selectedBackground, bg);
|
||||
screenLastActionTime = currentTime;
|
||||
break;
|
||||
|
||||
case K2_PRESSED:
|
||||
selectedBackground++;
|
||||
if (selectedBackground >= backgrounds) {
|
||||
selectedBackground = 0;
|
||||
}
|
||||
storage_initBackground(selectedBackground, bg);
|
||||
screenLastActionTime = currentTime;
|
||||
break;
|
||||
|
||||
case K3_PRESSED:
|
||||
currentBackground = selectedBackground;
|
||||
initialized = false;
|
||||
screenKey = MAIN_SCREEN;
|
||||
return;
|
||||
|
||||
case K4_PRESSED:
|
||||
storage_initBackground(currentBackground, bg);
|
||||
initialized = false;
|
||||
screenKey = MAIN_SCREEN;
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (selectedPreviousBackground != selectedBackground) {
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
draw_drawSprite(sprite, 174, 96, uiSpriteData, ARROW_ICON);
|
||||
tft_drawBuffer();
|
||||
selectedPreviousBackground = selectedBackground;
|
||||
}
|
||||
|
||||
if (currentTime - screenLastActionTime > INACTIVITY_THRESHOLD_TIME_US) {
|
||||
printf("[BACKGROUND] Returning home cuz yes\n");
|
||||
storage_initBackground(currentBackground, bg);
|
||||
initialized = false;
|
||||
screenKey = MAIN_SCREEN;
|
||||
}
|
||||
}
|
||||
@@ -9,83 +9,89 @@
|
||||
|
||||
|
||||
void menu_changeCharaScreen(TFT_eSprite& bg, TFT_eSprite &sprite, struct SpriteData* mainSpriteData, struct SpriteData* uiSpriteData) {
|
||||
vTaskSuspend(secondLoop);
|
||||
static bool initialized = false;
|
||||
static uint8_t selectedChara = 0;
|
||||
static CharacterData* selectedCharaData = NULL;
|
||||
static bool updateScreen = true;
|
||||
|
||||
uint8_t selectedChara = currentCharacter;
|
||||
CharacterData* selectedCharaData = &charaData[selectedChara];
|
||||
if (!initialized) {
|
||||
selectedChara = currentCharacter;
|
||||
selectedCharaData = &charaData[selectedChara];
|
||||
updateScreen = true;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
bool updateScreen = true;
|
||||
|
||||
for (;;) {
|
||||
uint8_t pressedButtons = buttons_getPressedButtons();
|
||||
switch (pressedButtons) {
|
||||
case K1_PRESSED:
|
||||
selectedChara++;
|
||||
if (selectedChara >= CHARA_COUNT_IN_DEVICE) {
|
||||
selectedChara = 0;
|
||||
}
|
||||
selectedCharaData = &charaData[selectedChara];
|
||||
updateScreen = true;
|
||||
break;
|
||||
|
||||
case K2_PRESSED:
|
||||
currentCharacter = selectedChara;
|
||||
vTaskResume(secondLoop);
|
||||
|
||||
screenKey = MAIN_SCREEN;
|
||||
menuKey = STATUS_SCREEN;
|
||||
return;
|
||||
break;
|
||||
|
||||
case K3_PRESSED:
|
||||
char fileName[20];
|
||||
sprintf(fileName, "/chara/%02x.bin", charaData[currentCharacter].idChara);
|
||||
|
||||
storage_readFile(fileName, mainSpriteData);
|
||||
vTaskResume(secondLoop);
|
||||
|
||||
screenKey = MAIN_SCREEN;
|
||||
menuKey = STATUS_SCREEN;
|
||||
return;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
delay(15);
|
||||
|
||||
if (updateScreen) {
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
|
||||
if (selectedCharaData->hatched) {
|
||||
char fileName[20];
|
||||
sprintf(fileName, "/chara/%02x.bin", selectedCharaData->idChara);
|
||||
|
||||
storage_readFile(fileName, mainSpriteData);
|
||||
draw_drawSprite(sprite, 18, 72, mainSpriteData, 0);
|
||||
|
||||
} else {
|
||||
tft_drawCenteredText("EMPTY", 4, 120);
|
||||
uint8_t pressedButtons = buttons_getPressedButtons();
|
||||
switch (pressedButtons) {
|
||||
case K1_PRESSED:
|
||||
selectedChara--;
|
||||
if (selectedChara < 0) {
|
||||
selectedChara = CHARA_COUNT_IN_DEVICE - 1;
|
||||
}
|
||||
selectedCharaData = &charaData[selectedChara];
|
||||
updateScreen = true;
|
||||
break;
|
||||
|
||||
draw_drawSprite(sprite, 174, 96, uiSpriteData, ARROW_ICON);
|
||||
case K2_PRESSED:
|
||||
selectedChara++;
|
||||
if (selectedChara >= CHARA_COUNT_IN_DEVICE) {
|
||||
selectedChara = 0;
|
||||
}
|
||||
selectedCharaData = &charaData[selectedChara];
|
||||
updateScreen = true;
|
||||
break;
|
||||
|
||||
tft_drawBuffer();
|
||||
case K3_PRESSED:
|
||||
currentCharacter = selectedChara;
|
||||
initialized = false;
|
||||
screenKey = MAIN_SCREEN;
|
||||
menuKey = STATUS_SCREEN;
|
||||
return;
|
||||
|
||||
updateScreen = false;
|
||||
}
|
||||
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
if (currentTime - lastPressedButtonTime > INACTIVITY_THRESHOLD_TIME_US) {
|
||||
case K4_PRESSED: {
|
||||
char fileName[20];
|
||||
sprintf(fileName, "/chara/%02x.bin", charaData[currentCharacter].idChara);
|
||||
|
||||
storage_readFile(fileName, mainSpriteData);
|
||||
vTaskResume(secondLoop);
|
||||
|
||||
initialized = false;
|
||||
screenKey = MAIN_SCREEN;
|
||||
menuKey = STATUS_SCREEN;
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (updateScreen) {
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
|
||||
if (selectedCharaData->hatched) {
|
||||
char fileName[20];
|
||||
sprintf(fileName, "/chara/%02x.bin", selectedCharaData->idChara);
|
||||
|
||||
storage_readFile(fileName, mainSpriteData);
|
||||
draw_drawSprite(sprite, 18, 72, mainSpriteData, 0);
|
||||
|
||||
} else {
|
||||
tft_drawCenteredText("EMPTY", 4, 120);
|
||||
}
|
||||
|
||||
draw_drawSprite(sprite, 174, 96, uiSpriteData, ARROW_ICON);
|
||||
|
||||
tft_drawBuffer();
|
||||
|
||||
updateScreen = false;
|
||||
}
|
||||
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
if (currentTime - lastPressedButtonTime > INACTIVITY_THRESHOLD_TIME_US) {
|
||||
char fileName[20];
|
||||
sprintf(fileName, "/chara/%02x.bin", charaData[currentCharacter].idChara);
|
||||
|
||||
storage_readFile(fileName, mainSpriteData);
|
||||
initialized = false;
|
||||
screenKey = MAIN_SCREEN;
|
||||
menuKey = STATUS_SCREEN;
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,14 @@
|
||||
void menu_drawClock(TFT_eSprite& bg) {
|
||||
uint8_t pressedButtons = buttons_getPressedButtons();
|
||||
switch (pressedButtons) {
|
||||
case K2_PRESSED | K3_PRESSED:
|
||||
screenKey = CLOCK_EDIT_SCREEN;
|
||||
break;
|
||||
|
||||
case K1_PRESSED:
|
||||
case K2_PRESSED:
|
||||
case K3_PRESSED:
|
||||
case K4_PRESSED:
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
screenKey = MAIN_SCREEN;
|
||||
break;
|
||||
@@ -48,7 +55,7 @@ void menu_drawClockEdit(TFT_eSprite& bg) {
|
||||
clockMinuteCount = (clockMinuteCount + 1) % 60;
|
||||
break;
|
||||
|
||||
case K3_PRESSED:
|
||||
case K4_PRESSED:
|
||||
// Es un dia random, nada significativo, ya pondre mas adelante que tenga dia del año
|
||||
rtc.setTime(0, clockMinuteCount, clockHourCount, 1, 11, 2024);
|
||||
srand(time(NULL));
|
||||
|
||||
@@ -12,18 +12,19 @@ void menu_drawDeathScreen(TFT_eSprite& bg, TFT_eSprite &sprite, struct SpriteDat
|
||||
|
||||
uint8_t pressedButtons = buttons_getPressedButtons();
|
||||
switch (pressedButtons) {
|
||||
case K1_PRESSED:
|
||||
case K4_PRESSED:
|
||||
lines_getAvailableLines();
|
||||
screenKey = EGG_SELECT_SCREEN;
|
||||
return;
|
||||
break;
|
||||
|
||||
case K2_PRESSED:
|
||||
case K3_PRESSED:
|
||||
screenKey = CLOCK_SCREEN;
|
||||
return;
|
||||
break;
|
||||
|
||||
case K3_PRESSED:
|
||||
case K1_PRESSED:
|
||||
case K2_PRESSED:
|
||||
lastUpdateTime = currentTime;
|
||||
frameCounter = 0;
|
||||
|
||||
|
||||
@@ -8,14 +8,28 @@
|
||||
#include "animations/animations.h"
|
||||
#include "vpet/vpet/vpet.h"
|
||||
#include "vpet/lines/lines.h"
|
||||
#include "defs/sounds.h"
|
||||
|
||||
const uint64_t HATCH_ANIMATION_FRAME_TIME_US = 100000;
|
||||
const uint64_t HATCH_COMPLETE_HOLD_TIME_US = 2000000;
|
||||
|
||||
void menu_eggHatchScreen(TFT_eSprite& bg, TFT_eSprite &sprite, struct SpriteData* uiBigSprite, struct SpriteData* uiSmallSprite) {
|
||||
static bool eggSpriteFrame = false;
|
||||
static bool hatchSoundStarted = false;
|
||||
static uint8_t hatchingFrame = 0;
|
||||
static uint64_t hatchHoldStartTime = 0;
|
||||
static uint64_t hatchAnimationLastFrameTime = 0;
|
||||
|
||||
sound_update();
|
||||
|
||||
uint8_t pressedButtons = buttons_getPressedButtons();
|
||||
switch (pressedButtons) {
|
||||
case K2_PRESSED:
|
||||
screenKey = CLOCK_SCREEN;
|
||||
hatchSoundStarted = false;
|
||||
hatchingFrame = 0;
|
||||
hatchHoldStartTime = 0;
|
||||
hatchAnimationLastFrameTime = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -23,39 +37,58 @@ void menu_eggHatchScreen(TFT_eSprite& bg, TFT_eSprite &sprite, struct SpriteData
|
||||
}
|
||||
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
if (currentTime - lastUpdateTime > ANIMATION_THRESHOLD_TIME_US) {
|
||||
if (charaData[currentCharacter].hatchTimer <= currentLine[currentCharacter]->hatchTime) {
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
draw_drawSpriteCentered(sprite, ¤tEgg->eggSprite, eggSpriteFrame);
|
||||
|
||||
eggSpriteFrame = !eggSpriteFrame;
|
||||
lastUpdateTime = currentTime;
|
||||
|
||||
tft_drawBuffer();
|
||||
|
||||
|
||||
} else if (charaData[currentCharacter].hatchTimer > currentLine[currentCharacter]->hatchTime && !charaData[currentCharacter].hatched) {
|
||||
for (int i = 0; i < 30; i++) {
|
||||
tone(SPK_PIN, 4100, 35);
|
||||
tone(SPK_PIN, 3500, 35);
|
||||
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
animate_performHatchingAnimation(sprite, ¤tEgg->eggSprite);
|
||||
|
||||
tft_drawBuffer();
|
||||
}
|
||||
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
|
||||
draw_drawSpriteCentered(sprite, ¤tEgg->eggSprite, 2);
|
||||
|
||||
tft_drawBuffer();
|
||||
|
||||
delay(2000);
|
||||
|
||||
if (hatchHoldStartTime > 0) {
|
||||
if (currentTime - hatchHoldStartTime > HATCH_COMPLETE_HOLD_TIME_US) {
|
||||
hatchHoldStartTime = 0;
|
||||
hatchSoundStarted = false;
|
||||
hatchingFrame = 0;
|
||||
hatchAnimationLastFrameTime = 0;
|
||||
lines_onHatchComplete();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (charaData[currentCharacter].hatchTimer > currentLine[currentCharacter]->hatchTime && !charaData[currentCharacter].hatched) {
|
||||
if (!hatchSoundStarted) {
|
||||
sound_playMelody(SOUND_HATCH, SOUND_NOTE_COUNT(SOUND_HATCH));
|
||||
hatchSoundStarted = true;
|
||||
hatchAnimationLastFrameTime = 0;
|
||||
}
|
||||
|
||||
if (hatchingFrame < 30 && currentTime - hatchAnimationLastFrameTime > HATCH_ANIMATION_FRAME_TIME_US) {
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
animate_performHatchingAnimation(sprite, ¤tEgg->eggSprite);
|
||||
|
||||
tft_drawBuffer();
|
||||
|
||||
hatchingFrame++;
|
||||
hatchAnimationLastFrameTime = currentTime;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (hatchingFrame < 30) {
|
||||
return;
|
||||
}
|
||||
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
|
||||
draw_drawSpriteCentered(sprite, ¤tEgg->eggSprite, 2);
|
||||
|
||||
tft_drawBuffer();
|
||||
hatchHoldStartTime = currentTime;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentTime - lastUpdateTime > ANIMATION_THRESHOLD_TIME_US) {
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
draw_drawSpriteCentered(sprite, ¤tEgg->eggSprite, eggSpriteFrame);
|
||||
|
||||
eggSpriteFrame = !eggSpriteFrame;
|
||||
lastUpdateTime = currentTime;
|
||||
|
||||
tft_drawBuffer();
|
||||
}
|
||||
}
|
||||
@@ -15,10 +15,14 @@ void menu_lineSwitcher(TFT_eSprite& bg, TFT_eSprite &sprite, struct SpriteData*
|
||||
uint8_t buttonsPressed = buttons_getPressedButtons();
|
||||
switch(buttonsPressed) {
|
||||
case K1_PRESSED:
|
||||
eggCounter = (eggCounter + 1) % eggNumber;
|
||||
eggCounter = (eggCounter - 1) % eggNumber;
|
||||
break;
|
||||
|
||||
case K2_PRESSED:
|
||||
eggCounter = (eggCounter + 1) % eggNumber;
|
||||
break;
|
||||
|
||||
case K4_PRESSED:
|
||||
menu_reloadEggs(eggCounter);
|
||||
eggCounter = 0;
|
||||
screenKey = EGG_HATCH_SCREEN;
|
||||
|
||||
@@ -3,36 +3,48 @@
|
||||
#include "display/display.h"
|
||||
#include "draw/draw.h"
|
||||
#include "menu.h"
|
||||
#include "defs/sounds.h"
|
||||
#include "vpet/vpet/vpet.h"
|
||||
|
||||
void menu_foodScreen(TFT_eSprite &bg, TFT_eSprite &mainChara,
|
||||
struct SpriteData *spriteData) {
|
||||
if (charaData[currentCharacter].sleepy) {
|
||||
tone(SPK_PIN, BEEP_FREQ_HZ, BEEP_LEN_MS);
|
||||
delay(100);
|
||||
tone(SPK_PIN, BEEP_FREQ_HZ, BEEP_LEN_MS);
|
||||
sound_playMelody(SOUND_BUTTON_BEEP, SOUND_NOTE_COUNT(SOUND_BUTTON_BEEP));
|
||||
screenKey = MENU_SCREEN;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static uint8_t arrowPosition = 0;
|
||||
static int8_t arrowPosition = 0;
|
||||
const int numItems = 2;
|
||||
|
||||
uint8_t pressedButtons = buttons_getPressedButtons();
|
||||
switch (pressedButtons) {
|
||||
case 8:
|
||||
arrowPosition = (arrowPosition + 1) % 2;
|
||||
break;
|
||||
case K1_PRESSED:
|
||||
printf("[FOOD] arrowPosition=%i\n", arrowPosition);
|
||||
arrowPosition--;
|
||||
if (arrowPosition < 0) {
|
||||
arrowPosition = numItems - 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
screenKey = MENU_SCREEN;
|
||||
break;
|
||||
case K2_PRESSED:
|
||||
printf("[FOOD] arrowPosition=%i\n", arrowPosition);
|
||||
arrowPosition++;
|
||||
if (arrowPosition >= numItems) {
|
||||
arrowPosition = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
case K3_PRESSED:
|
||||
screenKey = MENU_SCREEN;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (pressedButtons == 4) {
|
||||
if (pressedButtons == K4_PRESSED) {
|
||||
lastUpdateTime = 0;
|
||||
switch (arrowPosition) {
|
||||
case 0:
|
||||
|
||||
@@ -7,11 +7,12 @@ void menu_drawFridgeScreen(TFT_eSprite &bg, TFT_eSprite& sprite, struct SpriteDa
|
||||
uint8_t pressedButtons = buttons_getPressedButtons();
|
||||
switch (pressedButtons) {
|
||||
case K1_PRESSED:
|
||||
case K2_PRESSED:
|
||||
screenKey = MENU_SCREEN;
|
||||
menuKey = STATUS_SCREEN_MENU;
|
||||
break;
|
||||
|
||||
case K2_PRESSED:
|
||||
case K4_PRESSED:
|
||||
screenKey = CLOCK_SCREEN;
|
||||
break;
|
||||
|
||||
|
||||
+24
-28
@@ -4,43 +4,39 @@
|
||||
#include "display/display.h"
|
||||
#include "draw/draw.h"
|
||||
#include "animations/animations.h"
|
||||
#include "defs/sounds.h"
|
||||
|
||||
void menu_drawHappyScreen(
|
||||
TFT_eSprite& bg, TFT_eSprite &sprite,
|
||||
struct SpriteData* spriteData, struct SpriteData* smallUiElements, const int returnScreen
|
||||
) {
|
||||
uint8_t frameCounter = 0;
|
||||
static uint8_t frameCounter = 0;
|
||||
|
||||
while (true) {
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
if (currentTime - lastUpdateTime > ANIMATION_THRESHOLD_TIME_US) {
|
||||
if (frameCounter > 3) {
|
||||
screenKey = returnScreen; // TODO: Change for while battling
|
||||
menuKey = STATUS_SCREEN;
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
if (currentTime - lastUpdateTime > ANIMATION_THRESHOLD_TIME_US) {
|
||||
if (frameCounter > 3) {
|
||||
frameCounter = 0;
|
||||
screenKey = returnScreen; // TODO: Change for while battling
|
||||
menuKey = STATUS_SCREEN;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
animate_performHappyAnimation(sprite, spriteData);
|
||||
|
||||
if (frameCounter % 2 == 0) {
|
||||
tone(SPK_PIN, 7500, 50);
|
||||
tone(SPK_PIN, 5000, 50);
|
||||
tone(SPK_PIN, 2500, 50);
|
||||
tone(SPK_PIN, 1000, 50);
|
||||
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
draw_drawSprite(sprite, 18, 72, smallUiElements, FIREWORKS_ICON);
|
||||
draw_drawSprite(sprite, 174, 72, smallUiElements, FIREWORKS_ICON);
|
||||
}
|
||||
|
||||
frameCounter++;
|
||||
lastUpdateTime = currentTime;
|
||||
return;
|
||||
}
|
||||
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
animate_performHappyAnimation(sprite, spriteData);
|
||||
|
||||
if (frameCounter % 2 == 0) {
|
||||
sound_playMelody(SOUND_HAPPY, SOUND_NOTE_COUNT(SOUND_HAPPY));
|
||||
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
draw_drawSprite(sprite, 18, 72, smallUiElements, FIREWORKS_ICON);
|
||||
draw_drawSprite(sprite, 174, 72, smallUiElements, FIREWORKS_ICON);
|
||||
}
|
||||
|
||||
frameCounter++;
|
||||
lastUpdateTime = currentTime;
|
||||
tft_drawBuffer();
|
||||
}
|
||||
}
|
||||
@@ -12,11 +12,12 @@ void menu_drawIdleScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData
|
||||
uint8_t pressedButtons = buttons_getPressedButtons();
|
||||
switch (pressedButtons) {
|
||||
case K1_PRESSED:
|
||||
case K2_PRESSED:
|
||||
screenKey = MENU_SCREEN;
|
||||
menuKey = STATUS_SCREEN_MENU;
|
||||
break;
|
||||
|
||||
case K2_PRESSED:
|
||||
case K4_PRESSED:
|
||||
screenKey = CLOCK_SCREEN;
|
||||
break;
|
||||
|
||||
|
||||
+6
-1
@@ -53,11 +53,16 @@ void menu_drawAngryScreen(
|
||||
struct SpriteData* spriteData, struct SpriteData* smallUiElements
|
||||
);
|
||||
void menu_drawFridgeScreen(TFT_eSprite &bg, TFT_eSprite& sprite, struct SpriteData* smallUiElements, struct SpriteData* bigUiElements);
|
||||
|
||||
void training_screenTraining2(
|
||||
TFT_eSprite &bg, TFT_eSprite &sprite,
|
||||
struct SpriteData* mainCharaData, struct SpriteData* attackSprites
|
||||
);
|
||||
void menu_changeBackgroundScreen(
|
||||
TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* uiSpriteData
|
||||
);
|
||||
void menu_settingsScreen(TFT_eSprite &bg, TFT_eSprite &mainChara, struct SpriteData *spriteData);
|
||||
void menu_settingsScreen_drawEntry(uint8_t entryId, const char *textEntry);
|
||||
void menu_resetDataScreen(TFT_eSprite &bg);
|
||||
|
||||
void menu_sleepScreen_sleepAction();
|
||||
void menu_sleepScreen_recalculateSleep();
|
||||
|
||||
@@ -22,6 +22,13 @@ void menu_drawCurrentMenuOption(TFT_eSprite& bg, TFT_eSprite &icon, struct Sprit
|
||||
menuKey++;
|
||||
break;
|
||||
|
||||
case K2_PRESSED:
|
||||
menuKey--;
|
||||
if (menuKey < 0) {
|
||||
menuKey = FREEZE_SCREEN_MENU;
|
||||
}
|
||||
break;
|
||||
|
||||
case K3_PRESSED:
|
||||
screenKey = MAIN_SCREEN;
|
||||
menuKey = STATUS_SCREEN_MENU;
|
||||
@@ -33,7 +40,10 @@ void menu_drawCurrentMenuOption(TFT_eSprite& bg, TFT_eSprite &icon, struct Sprit
|
||||
}
|
||||
|
||||
// Separaíto mas guapito
|
||||
if (pressedButtons == K2_PRESSED) {
|
||||
if (pressedButtons == K4_PRESSED) {
|
||||
const uint64_t currentTime = esp_timer_get_time();
|
||||
lastUpdateTime = currentTime;
|
||||
|
||||
switch (menuKey) {
|
||||
case STATUS_SCREEN_MENU:
|
||||
screenKey = STATUS_SCREEN;
|
||||
@@ -73,6 +83,12 @@ void menu_drawCurrentMenuOption(TFT_eSprite& bg, TFT_eSprite &icon, struct Sprit
|
||||
return;
|
||||
break;
|
||||
|
||||
case SETTINGS_SCREEN_MENU:
|
||||
menuKey = STATUS_SCREEN;
|
||||
screenKey = SETTINGS_SCREEN;
|
||||
return;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
+22
-29
@@ -9,34 +9,34 @@
|
||||
void menu_clearPoopScreen(
|
||||
TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* spriteData, struct SpriteData* bigUiElements, struct SpriteData* smallUiElements
|
||||
) {
|
||||
printf("[AAAAAAA] pausing loop...\n");
|
||||
static bool initialized = false;
|
||||
static int cleanerXPos = 174;
|
||||
|
||||
vTaskSuspend(secondLoop);
|
||||
if (!initialized) {
|
||||
cleanerXPos = 174;
|
||||
lastUpdateTime = 0;
|
||||
|
||||
printf("[AAAAAAA] loop paused...\n");
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
uint8_t offsetX = menu_poopOverlay(bg, sprite, smallUiElements);
|
||||
|
||||
int cleanerXPos = 174;
|
||||
animate_performAnimation(sprite, spriteData, offsetX);
|
||||
menu_uiOverlay(sprite, bigUiElements);
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
|
||||
lastUpdateTime = 0;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
printf("[AAAAAAA] drawing idle screen...\n");
|
||||
if (cleanerXPos <= 18 - 48) {
|
||||
screenKey = HAPPY_SCREEN;
|
||||
menuKey = -1;
|
||||
charaData[currentCharacter].poopNumber = 0;
|
||||
initialized = false;
|
||||
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
uint8_t offsetX = menu_poopOverlay(bg, sprite, smallUiElements);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("[AAAAAAA] drawing animation...\n");
|
||||
|
||||
animate_performAnimation(sprite, spriteData, offsetX);
|
||||
|
||||
printf("[AAAAAAA] drawing overlay...\n");
|
||||
|
||||
menu_uiOverlay(sprite, bigUiElements);
|
||||
|
||||
printf("[AAAAAAA] idle screen down...\n");
|
||||
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
|
||||
while (cleanerXPos > 18 - 48) {
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
if (currentTime - lastUpdateTime > 50000) {
|
||||
draw_drawBackgroundSection(bg, cleanerXPos + 6, 72, 48, 96);
|
||||
|
||||
draw_drawSprite(sprite, cleanerXPos, 72, smallUiElements, CLEANER_ICON);
|
||||
@@ -47,13 +47,6 @@ void menu_clearPoopScreen(
|
||||
tft_drawBuffer();
|
||||
|
||||
cleanerXPos -= 6;
|
||||
lastUpdateTime = currentTime;
|
||||
}
|
||||
|
||||
screenKey = HAPPY_SCREEN;
|
||||
menuKey = -1;
|
||||
charaData[currentCharacter].poopNumber = 0;
|
||||
|
||||
vTaskResume(secondLoop);
|
||||
|
||||
return;
|
||||
}
|
||||
+50
-56
@@ -4,78 +4,72 @@
|
||||
#include "display/display.h"
|
||||
#include "defs/defs.h"
|
||||
#include "defs/chara_data.h"
|
||||
#include "defs/sounds.h"
|
||||
#include "defs/sprite_data.h"
|
||||
|
||||
void menu_poopScreen(
|
||||
TFT_eSprite &bg, TFT_eSprite &sprite,
|
||||
struct SpriteData* spriteData, struct SpriteData* smallUiElements, struct SpriteData* bigUiElements
|
||||
) {
|
||||
uint8_t animationFrame = 0;
|
||||
bool animationPosition = 0;
|
||||
static uint8_t animationFrame = 0;
|
||||
static bool animationPosition = 0;
|
||||
static bool beepedAlready = false;
|
||||
|
||||
bool beepedAlready = false;
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
|
||||
while (1) {
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
if (currentTime - lastUpdateTime > ANIMATION_THRESHOLD_TIME_US && animationFrame < 4) {
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
|
||||
if (currentTime - lastUpdateTime > ANIMATION_THRESHOLD_TIME_US && animationFrame < 4) {
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
draw_drawSprite(sprite, 72 + (animationPosition * 6), 72, spriteData, 6);
|
||||
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
draw_drawSprite(sprite, 72 + (animationPosition * 6), 72, spriteData, 6);
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
menu_uiOverlay(sprite, bigUiElements);
|
||||
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
menu_uiOverlay(sprite, bigUiElements);
|
||||
animationFrame++;
|
||||
animationPosition = !animationPosition;
|
||||
|
||||
animationFrame++;
|
||||
animationPosition = !animationPosition;
|
||||
lastUpdateTime = currentTime;
|
||||
tft_drawBuffer();
|
||||
|
||||
lastUpdateTime = currentTime;
|
||||
} else if (currentTime - lastUpdateTime > ANIMATION_THRESHOLD_TIME_US && animationFrame < 6) {
|
||||
if (!beepedAlready) {
|
||||
sound_playMelody(SOUND_POOP_DROP, SOUND_NOTE_COUNT(SOUND_POOP_DROP));
|
||||
|
||||
} else if (currentTime - lastUpdateTime > ANIMATION_THRESHOLD_TIME_US && animationFrame < 6) {
|
||||
if (!beepedAlready) {
|
||||
tone(SPK_PIN, 2500, 50);
|
||||
tone(SPK_PIN, 5000, 50);
|
||||
tone(SPK_PIN, 2500, 50);
|
||||
tone(SPK_PIN, 5000, 50);
|
||||
|
||||
beepedAlready = true;
|
||||
}
|
||||
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
draw_drawSprite(sprite, 174, 120, smallUiElements, POOP_ICON);
|
||||
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
menu_uiOverlay(sprite, bigUiElements);
|
||||
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
draw_drawSprite(sprite, 72, 72, spriteData, 7);
|
||||
|
||||
animationFrame++;
|
||||
animationPosition = !animationPosition;
|
||||
|
||||
lastUpdateTime = currentTime;
|
||||
|
||||
} else if (animationFrame >= 6) {
|
||||
if (
|
||||
(charaData[currentCharacter].hunger == 0 && !charaData[currentCharacter].hungerCareMistakeObtained) ||
|
||||
(charaData[currentCharacter].strength == 0 && !charaData[currentCharacter].strengthCareMistakeObtained) ||
|
||||
(charaData[currentCharacter].sleepy && !charaData[currentCharacter].asleep && !charaData[currentCharacter].sleepCareMistakeObtained)
|
||||
) {
|
||||
screenKey = CARE_MISTAKE_SCREEN;
|
||||
} else {
|
||||
screenKey = MAIN_SCREEN;
|
||||
}
|
||||
|
||||
menuKey = -1;
|
||||
animationFrame = 0;
|
||||
animationPosition = 0;
|
||||
|
||||
break;
|
||||
beepedAlready = true;
|
||||
}
|
||||
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
draw_drawSprite(sprite, 174, 120, smallUiElements, POOP_ICON);
|
||||
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
menu_uiOverlay(sprite, bigUiElements);
|
||||
|
||||
tft_clearBuffer(sprite, TFT_TRANSPARENT);
|
||||
draw_drawSprite(sprite, 72, 72, spriteData, 7);
|
||||
|
||||
animationFrame++;
|
||||
animationPosition = !animationPosition;
|
||||
|
||||
lastUpdateTime = currentTime;
|
||||
tft_drawBuffer();
|
||||
|
||||
} else if (animationFrame >= 6) {
|
||||
if (
|
||||
(charaData[currentCharacter].hunger == 0 && !charaData[currentCharacter].hungerCareMistakeObtained) ||
|
||||
(charaData[currentCharacter].strength == 0 && !charaData[currentCharacter].strengthCareMistakeObtained) ||
|
||||
(charaData[currentCharacter].sleepy && !charaData[currentCharacter].asleep && !charaData[currentCharacter].sleepCareMistakeObtained)
|
||||
) {
|
||||
screenKey = CARE_MISTAKE_SCREEN;
|
||||
} else {
|
||||
screenKey = MAIN_SCREEN;
|
||||
}
|
||||
|
||||
menuKey = -1;
|
||||
animationFrame = 0;
|
||||
animationPosition = 0;
|
||||
beepedAlready = false;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "draw/draw.h"
|
||||
#include "display/display.h"
|
||||
#include "defs/defs.h"
|
||||
#include "defs/sounds.h"
|
||||
#include "defs/sprite_data.h"
|
||||
#include "animations/animations.h"
|
||||
|
||||
@@ -13,8 +14,10 @@ void menu_refuseScreen(TFT_eSprite &bg, TFT_eSprite &mainChara, struct SpriteDat
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
uint8_t pressedButtons = buttons_getPressedButtons();
|
||||
switch (pressedButtons) {
|
||||
case 8:
|
||||
case 4:
|
||||
case K1_PRESSED:
|
||||
case K2_PRESSED:
|
||||
case K3_PRESSED:
|
||||
case K4_PRESSED:
|
||||
currentAnimationFrame = 0;
|
||||
screenKey = FOOD_SCREEN;
|
||||
soundPlayed = false;
|
||||
@@ -34,8 +37,7 @@ void menu_refuseScreen(TFT_eSprite &bg, TFT_eSprite &mainChara, struct SpriteDat
|
||||
}
|
||||
|
||||
if (!soundPlayed) {
|
||||
tone(SPK_PIN, 3000, 100);
|
||||
tone(SPK_PIN, 1000, 100);
|
||||
sound_playMelody(SOUND_REFUSE, SOUND_NOTE_COUNT(SOUND_REFUSE));
|
||||
|
||||
soundPlayed = true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "buttons/buttons.h"
|
||||
#include "defs/defs.h"
|
||||
#include "display/display.h"
|
||||
#include "draw/draw.h"
|
||||
#include "menu.h"
|
||||
#include "storage/storage.h"
|
||||
|
||||
void menu_resetDataScreen(TFT_eSprite &bg) {
|
||||
static uint8_t selectedOption = 0;
|
||||
|
||||
uint8_t pressedButtons = buttons_getPressedButtons();
|
||||
switch (pressedButtons) {
|
||||
case K1_PRESSED:
|
||||
selectedOption = (selectedOption - 1) % 2;
|
||||
break;
|
||||
|
||||
case K2_PRESSED:
|
||||
selectedOption = (selectedOption + 1) % 2;
|
||||
break;
|
||||
|
||||
case K4_PRESSED:
|
||||
if (selectedOption == 1) {
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
tft_drawCenteredText("RESETTING", 3, 104);
|
||||
tft_drawBuffer();
|
||||
|
||||
if (storage_deleteState()) {
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
tft_drawCenteredText("FAILED", 4, 95);
|
||||
tft_drawBuffer();
|
||||
return;
|
||||
}
|
||||
|
||||
selectedOption = 0;
|
||||
screenKey = SETTINGS_SCREEN;
|
||||
return;
|
||||
|
||||
case K3_PRESSED:
|
||||
selectedOption = 0;
|
||||
screenKey = SETTINGS_SCREEN;
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
|
||||
tft_drawCenteredText("RESET DATA?", 3, 35);
|
||||
|
||||
const char* labels[] = { "NO", "YES" };
|
||||
const int startX = 72;
|
||||
const int startY = 95;
|
||||
const int spacingY = 42;
|
||||
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
bool selected = (i == selectedOption);
|
||||
int y = startY + (i * spacingY);
|
||||
|
||||
tft_drawText(labels[i], 4, startX, y, selected ? TFT_BLACK : TFT_WHITE, selected ? TFT_WHITE : TFT_TRANSPARENT);
|
||||
}
|
||||
|
||||
tft_drawBuffer();
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
#include "buttons/buttons.h"
|
||||
#include "defs/chara_data.h"
|
||||
#include "defs/defs.h"
|
||||
#include "display/display.h"
|
||||
#include "draw/draw.h"
|
||||
#include "menu.h"
|
||||
#include "vpet/vpet/vpet.h"
|
||||
|
||||
enum SettingsItemType {
|
||||
SETTINGS_SUBMENU,
|
||||
SETTINGS_ACTION
|
||||
};
|
||||
|
||||
struct SettingsMenuItem {
|
||||
const char* label;
|
||||
SettingsItemType type;
|
||||
uint8_t targetScreen;
|
||||
void (*actionFunction)();
|
||||
bool* stateValue;
|
||||
};
|
||||
|
||||
void switchSoundState() {
|
||||
if (soundEnabled) {
|
||||
pinMode(SPK_PIN, INPUT);
|
||||
} else {
|
||||
pinMode(SPK_PIN, OUTPUT);
|
||||
}
|
||||
|
||||
soundEnabled = !soundEnabled;
|
||||
printf("[SETTINGS] soundEnabled=%i\n", soundEnabled);
|
||||
}
|
||||
|
||||
|
||||
void switchScreenState() {
|
||||
alwaysOnEnabled = !alwaysOnEnabled;
|
||||
printf("[SETTINGS] alwaysOnEnabled=%i\n", alwaysOnEnabled);
|
||||
}
|
||||
|
||||
void menu_settingsScreen(TFT_eSprite &bg, TFT_eSprite &mainChara, struct SpriteData *spriteData)
|
||||
{
|
||||
static int8_t arrowPosition = 0;
|
||||
|
||||
static SettingsMenuItem menuItems[] = {
|
||||
{ "BG", SETTINGS_SUBMENU, BACKGROUND_CHANGE_SCREEN, nullptr, nullptr },
|
||||
{ "SOUND", SETTINGS_ACTION, 0, switchSoundState, &soundEnabled },
|
||||
{ "AOD", SETTINGS_ACTION, 0, switchScreenState, &alwaysOnEnabled },
|
||||
{ "RESET", SETTINGS_SUBMENU, RESET_DATA_SCREEN, nullptr, nullptr }
|
||||
};
|
||||
|
||||
const uint8_t numItems = sizeof(menuItems) / sizeof(menuItems[0]);
|
||||
|
||||
uint8_t pressedButtons = buttons_getPressedButtons();
|
||||
switch (pressedButtons) {
|
||||
case K1_PRESSED:
|
||||
printf("[FOOD] arrowPosition=%i\n", arrowPosition);
|
||||
arrowPosition--;
|
||||
if (arrowPosition < 0) {
|
||||
arrowPosition = numItems - 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case K2_PRESSED:
|
||||
printf("[FOOD] arrowPosition=%i\n", arrowPosition);
|
||||
arrowPosition++;
|
||||
if (arrowPosition >= numItems) {
|
||||
arrowPosition = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case K3_PRESSED:
|
||||
screenKey = MENU_SCREEN;
|
||||
return;
|
||||
|
||||
case K4_PRESSED:
|
||||
lastUpdateTime = 0;
|
||||
|
||||
if (menuItems[arrowPosition].type == SETTINGS_ACTION) {
|
||||
if (menuItems[arrowPosition].actionFunction != nullptr) {
|
||||
menuItems[arrowPosition].actionFunction();
|
||||
}
|
||||
} else if (menuItems[arrowPosition].type == SETTINGS_SUBMENU) {
|
||||
screenKey = menuItems[arrowPosition].targetScreen;
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
|
||||
const int startX = 20;
|
||||
const int startY = 10;
|
||||
const int spacingY = 40;
|
||||
|
||||
for (uint8_t i = 0; i < numItems; i++) {
|
||||
bool selected = (i == arrowPosition);
|
||||
int y = startY + (i * spacingY);
|
||||
|
||||
tft_drawText(menuItems[i].label, 4, startX, y, selected ? TFT_BLACK : TFT_WHITE, selected ? TFT_WHITE : TFT_TRANSPARENT);
|
||||
|
||||
if (menuItems[i].stateValue != nullptr) {
|
||||
const char* stateText = (*menuItems[i].stateValue) ? "ON" : "OFF";
|
||||
|
||||
tft_drawText(stateText, 4, 150, y, selected ? TFT_BLACK : TFT_WHITE, selected ? TFT_WHITE : TFT_TRANSPARENT);
|
||||
}
|
||||
}
|
||||
|
||||
tft_drawBuffer();
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "buttons/buttons.h"
|
||||
#include "animations/animations.h"
|
||||
#include "defs/chara_data.h"
|
||||
#include "defs/sounds.h"
|
||||
|
||||
void menu_sleepyScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* charaSprites, struct SpriteData* uiSprites) {
|
||||
if (!charaData[currentCharacter].asleep && !charaData[currentCharacter].sleepy) {
|
||||
@@ -18,10 +19,12 @@ void menu_sleepyScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData*
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
uint8_t pressedButtons = buttons_getPressedButtons();
|
||||
switch (pressedButtons) {
|
||||
case 8:
|
||||
case K1_PRESSED:
|
||||
case K2_PRESSED:
|
||||
screenKey = MENU_SCREEN;
|
||||
break;
|
||||
case 4:
|
||||
|
||||
case K4_PRESSED:
|
||||
screenKey = CLOCK_SCREEN;
|
||||
break;
|
||||
|
||||
@@ -45,8 +48,7 @@ void menu_sleepyScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData*
|
||||
}
|
||||
|
||||
if (currentTime - lastBeepTime > ANIMATION_THRESHOLD_TIME_US * 2 && beepCounter < 10) {
|
||||
tone(SPK_PIN, 2500, 100);
|
||||
tone(SPK_PIN, 5000, 100);
|
||||
sound_playMelody(SOUND_CARE_ALERT, SOUND_NOTE_COUNT(SOUND_CARE_ALERT));
|
||||
|
||||
lastBeepTime = currentTime;
|
||||
|
||||
|
||||
@@ -23,11 +23,12 @@ void menu_sleepingScreen(
|
||||
|
||||
uint8_t buttonsPressed = buttons_getPressedButtons();
|
||||
switch (buttonsPressed) {
|
||||
case 8:
|
||||
case K1_PRESSED:
|
||||
case K2_PRESSED:
|
||||
screenKey = MENU_SCREEN;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
case K4_PRESSED:
|
||||
screenKey = CLOCK_SCREEN;
|
||||
break;
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ void menu_statusScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData*
|
||||
|
||||
uint8_t pressedButtons = buttons_getPressedButtons();
|
||||
switch (pressedButtons) {
|
||||
case 2:
|
||||
case K3_PRESSED:
|
||||
screenKey = MENU_SCREEN;
|
||||
break;
|
||||
|
||||
@@ -41,7 +41,7 @@ void menu_statusScreen_drawStat(TFT_eSprite &sprite, struct SpriteData* spriteDa
|
||||
|
||||
draw_drawSprite(
|
||||
sprite,
|
||||
15 + (i * 32),
|
||||
15 + (i * 48),
|
||||
y + 30,
|
||||
spriteData,
|
||||
icon,
|
||||
|
||||
@@ -6,11 +6,16 @@
|
||||
|
||||
void menu_drawTitle(TFT_eSprite &bg, TFT_eSprite &composite) {
|
||||
uint8_t pressedButtons = buttons_getPressedButtons();
|
||||
if (pressedButtons == 8 || pressedButtons == 4) {
|
||||
if (pressedButtons != 0) {
|
||||
screenKey = CLOCK_EDIT_SCREEN;
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
if (currentTime - lastUpdateTime < 200000) {
|
||||
return;
|
||||
}
|
||||
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
|
||||
tft_drawCenteredText("NacaPet", 4, 40);
|
||||
@@ -18,6 +23,5 @@ void menu_drawTitle(TFT_eSprite &bg, TFT_eSprite &composite) {
|
||||
tft_drawCenteredText(VERSION, 2, 80);
|
||||
|
||||
tft_drawBuffer();
|
||||
|
||||
delay(200);
|
||||
lastUpdateTime = currentTime;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "vpet/training/training.h"
|
||||
#include "defs/defs.h"
|
||||
#include "defs/chara_data.h"
|
||||
#include "defs/sounds.h"
|
||||
#include "defs/sprite_data.h"
|
||||
#include "buttons/buttons.h"
|
||||
#include "display/display.h"
|
||||
@@ -16,8 +17,7 @@ void training_screenTraining1(
|
||||
draw_drawBackground(bg, 90, 90, 3);
|
||||
draw_drawSpriteCentered(sprite, mainCharaData, 11);
|
||||
|
||||
tone(SPK_PIN, 4100, 100);
|
||||
tone(SPK_PIN, 3500, 100);
|
||||
sound_playMelody(SOUND_TRAINING_START, SOUND_NOTE_COUNT(SOUND_TRAINING_START));
|
||||
|
||||
tft_drawBuffer();
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "vpet/training/training.h"
|
||||
#include "defs/defs.h"
|
||||
#include "defs/chara_data.h"
|
||||
#include "defs/sounds.h"
|
||||
#include "draw/draw.h"
|
||||
#include "display/display.h"
|
||||
#include "buttons/buttons.h"
|
||||
@@ -10,56 +11,59 @@ void training_screenTraining2(
|
||||
TFT_eSprite &bg, TFT_eSprite &sprite,
|
||||
struct SpriteData* mainCharaData, struct SpriteData* attackSprites
|
||||
) {
|
||||
vTaskSuspend(secondLoop);
|
||||
enum TrainingState {
|
||||
TRAINING_INIT,
|
||||
TRAINING_WAIT_INPUT,
|
||||
TRAINING_SHOW_BOTH,
|
||||
TRAINING_SHOW_HIT
|
||||
};
|
||||
|
||||
draw_drawBackground(bg, 90, 90 ,3);
|
||||
static TrainingState state = TRAINING_INIT;
|
||||
static uint64_t inactivityTimer = 0;
|
||||
static uint64_t stageStartTime = 0;
|
||||
static uint8_t randomPosition = 0;
|
||||
static uint8_t projectilePosition = 0;
|
||||
|
||||
// Player
|
||||
draw_drawSprite(sprite, 174, 72, mainCharaData, 0, false);
|
||||
draw_drawBackgroundSection(bg, 222, 72, 18, 96);
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
|
||||
// Opponent
|
||||
draw_drawSprite(sprite, -30, 72, mainCharaData, 0, true);
|
||||
draw_drawBackgroundSection(bg, 0, 72, 18, 96);
|
||||
if (state == TRAINING_INIT) {
|
||||
draw_drawBackground(bg, 90, 90 ,3);
|
||||
|
||||
tft_drawBuffer();
|
||||
// Player
|
||||
draw_drawSprite(sprite, 174, 72, mainCharaData, 0, false);
|
||||
draw_drawBackgroundSection(bg, 222, 72, 18, 96);
|
||||
|
||||
uint64_t inactivityTimer = esp_timer_get_time();
|
||||
while (true) {
|
||||
uint64_t currentTime = esp_timer_get_time();
|
||||
if (currentTime - lastUpdateTime > 500000) {
|
||||
tone(SPK_PIN, BEEP_FREQ_HZ, BEEP_LEN_MS);
|
||||
lastUpdateTime = currentTime;
|
||||
}
|
||||
// Opponent
|
||||
draw_drawSprite(sprite, -30, 72, mainCharaData, 0, true);
|
||||
draw_drawBackgroundSection(bg, 0, 72, 18, 96);
|
||||
|
||||
tft_drawBuffer();
|
||||
|
||||
inactivityTimer = currentTime;
|
||||
state = TRAINING_WAIT_INPUT;
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentTime - lastUpdateTime > 500000) {
|
||||
sound_playMelody(SOUND_BUTTON_BEEP, SOUND_NOTE_COUNT(SOUND_BUTTON_BEEP));
|
||||
lastUpdateTime = currentTime;
|
||||
}
|
||||
|
||||
if (state == TRAINING_WAIT_INPUT) {
|
||||
if (currentTime - inactivityTimer > 3000000) {
|
||||
screenKey = MAIN_SCREEN;
|
||||
submenuKey = STATUS_SCREEN_MENU;
|
||||
|
||||
vTaskResume(secondLoop);
|
||||
|
||||
state = TRAINING_INIT;
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t randomPosition = rand() % 2;
|
||||
uint8_t projectilePosition = 0;
|
||||
|
||||
uint8_t pressedButtons = buttons_getPressedButtons();
|
||||
if (pressedButtons == K1_PRESSED || pressedButtons == K2_PRESSED) {
|
||||
projectilePosition = pressedButtons >> 3; // pressedButtons >> 4 == 1 => K1; != 1 => K2
|
||||
if (pressedButtons == K3_PRESSED || pressedButtons == K4_PRESSED) {
|
||||
randomPosition = rand() % 2;
|
||||
projectilePosition = pressedButtons >> 1; // pressedButtons >> 4 == 1 => K1; != 1 => K2
|
||||
printf("[TRAIN] projectilePosition=%i\n", projectilePosition);
|
||||
|
||||
} else if (pressedButtons == K3_PRESSED) {
|
||||
screenKey = MAIN_SCREEN;
|
||||
submenuKey = STATUS_SCREEN_MENU;
|
||||
|
||||
vTaskResume(secondLoop);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (pressedButtons != 0) {
|
||||
inactivityTimer = esp_timer_get_time();
|
||||
inactivityTimer = currentTime;
|
||||
|
||||
// Player attack
|
||||
draw_drawSprite(sprite, 126, 72 + 48 * projectilePosition, attackSprites, POOP_ICON);
|
||||
@@ -69,28 +73,36 @@ void training_screenTraining2(
|
||||
|
||||
tft_drawBuffer();
|
||||
|
||||
if (projectilePosition != randomPosition) {
|
||||
delay(500);
|
||||
stageStartTime = currentTime;
|
||||
state = TRAINING_SHOW_BOTH;
|
||||
|
||||
draw_drawBackgroundSection(bg, 126, 72 + 48 * projectilePosition, 48, 48);
|
||||
draw_drawSprite(sprite, 66, 72 + 48 * projectilePosition, attackSprites, POOP_ICON);
|
||||
|
||||
tft_drawBuffer();
|
||||
|
||||
delay(500);
|
||||
} else {
|
||||
delay(500);
|
||||
}
|
||||
|
||||
draw_drawBackgroundSection(bg, 66, 72, 108, 96);
|
||||
|
||||
if (projectilePosition != randomPosition) {
|
||||
charaData[currentCharacter].strength++;
|
||||
menu_drawHappyScreen(bg, sprite, mainCharaData, attackSprites);
|
||||
} else {
|
||||
printf("[TRAIN] Train failed\n");
|
||||
menu_drawAngryScreen(bg, sprite, mainCharaData, attackSprites);
|
||||
}
|
||||
} else if (pressedButtons == K3_PRESSED) {
|
||||
screenKey = MAIN_SCREEN;
|
||||
submenuKey = STATUS_SCREEN_MENU;
|
||||
state = TRAINING_INIT;
|
||||
return;
|
||||
}
|
||||
} else if (state == TRAINING_SHOW_BOTH && currentTime - stageStartTime > 500000) {
|
||||
if (projectilePosition != randomPosition) {
|
||||
draw_drawBackgroundSection(bg, 126, 72 + 48 * projectilePosition, 48, 48);
|
||||
draw_drawSprite(sprite, 66, 72 + 48 * projectilePosition, attackSprites, POOP_ICON);
|
||||
|
||||
tft_drawBuffer();
|
||||
|
||||
stageStartTime = currentTime;
|
||||
state = TRAINING_SHOW_HIT;
|
||||
} else {
|
||||
draw_drawBackgroundSection(bg, 66, 72, 108, 96);
|
||||
tft_drawBuffer();
|
||||
printf("[TRAIN] Train failed\n");
|
||||
screenKey = ANGRY_SCREEN;
|
||||
state = TRAINING_INIT;
|
||||
}
|
||||
} else if (state == TRAINING_SHOW_HIT && currentTime - stageStartTime > 500000) {
|
||||
draw_drawBackgroundSection(bg, 66, 72, 108, 96);
|
||||
tft_drawBuffer();
|
||||
charaData[currentCharacter].strength++;
|
||||
screenKey = HAPPY_SCREEN;
|
||||
state = TRAINING_INIT;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
#include "sound.h"
|
||||
#include "defs/defs.h"
|
||||
|
||||
static const Note* currentMelody = nullptr;
|
||||
|
||||
static uint16_t melodyLength = 0;
|
||||
static uint16_t currentNote = 0;
|
||||
|
||||
static bool playing = false;
|
||||
|
||||
static unsigned long nextNoteTime = 0;
|
||||
|
||||
void sound_init() {
|
||||
pinMode(SPK_PIN, OUTPUT);
|
||||
}
|
||||
|
||||
void sound_playTone(uint16_t frequency, uint16_t duration) {
|
||||
if (!soundEnabled) { return; }
|
||||
|
||||
currentMelody = nullptr;
|
||||
melodyLength = 0;
|
||||
currentNote = 0;
|
||||
|
||||
if (frequency == 0) {
|
||||
noTone(SPK_PIN);
|
||||
} else {
|
||||
tone(SPK_PIN, frequency, duration);
|
||||
}
|
||||
|
||||
playing = true;
|
||||
nextNoteTime = millis() + duration;
|
||||
}
|
||||
|
||||
void sound_playMelody(const Note* melody, uint16_t noteCount) {
|
||||
if (!soundEnabled) { return; }
|
||||
|
||||
if (melody == nullptr || noteCount == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentMelody = melody;
|
||||
melodyLength = noteCount;
|
||||
currentNote = 0;
|
||||
playing = true;
|
||||
nextNoteTime = 0;
|
||||
}
|
||||
|
||||
void sound_stop() {
|
||||
noTone(SPK_PIN);
|
||||
playing = false;
|
||||
currentMelody = nullptr;
|
||||
melodyLength = 0;
|
||||
currentNote = 0;
|
||||
}
|
||||
|
||||
bool sound_isPlaying() {
|
||||
return playing;
|
||||
}
|
||||
|
||||
void sound_update() {
|
||||
if (!soundEnabled) {
|
||||
sound_stop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!playing) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentMelody == nullptr) {
|
||||
if (millis() >= nextNoteTime) {
|
||||
sound_stop();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (millis() < nextNoteTime) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentNote >= melodyLength) {
|
||||
sound_stop();
|
||||
return;
|
||||
}
|
||||
|
||||
const Note& note = currentMelody[currentNote];
|
||||
|
||||
if (note.frequency == 0) {
|
||||
noTone(SPK_PIN);
|
||||
} else {
|
||||
tone(SPK_PIN, note.frequency, note.duration);
|
||||
}
|
||||
|
||||
nextNoteTime = millis() + note.duration;
|
||||
|
||||
currentNote++;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
struct Note {
|
||||
uint16_t frequency;
|
||||
uint16_t duration;
|
||||
};
|
||||
|
||||
void sound_init();
|
||||
void sound_update();
|
||||
void sound_playTone(uint16_t frequency, uint16_t duration);
|
||||
void sound_playMelody(const Note* melody, uint16_t noteCount);
|
||||
void sound_stop();
|
||||
bool sound_isPlaying();
|
||||
@@ -0,0 +1,124 @@
|
||||
#include "storage.h"
|
||||
#include "memory/memory.h"
|
||||
#include "defs/defs.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
|
||||
const char* TAG_SR = "[STORAGE]";
|
||||
|
||||
|
||||
void storage_readFile(const char* path, struct SpriteData* spriteData) {
|
||||
File file = SPIFFS.open(path, "r");
|
||||
if (!file) {
|
||||
printf("%s Failed to open file for reading\n", TAG_SR);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t width, height, spriteNumber;
|
||||
|
||||
file.read(&width, 1);
|
||||
file.read(&height, 1);
|
||||
file.read(&spriteNumber, 1);
|
||||
|
||||
if (spriteData->spriteData != NULL) {
|
||||
memory_free(spriteData);
|
||||
}
|
||||
|
||||
const uint8_t scaledW = width * SPRITE_SCALE;
|
||||
const uint8_t scaledH = height * SPRITE_SCALE;
|
||||
|
||||
uint16_t** scaled =
|
||||
(uint16_t**) ps_malloc(spriteNumber * sizeof(uint16_t*));
|
||||
|
||||
if (!scaled) {
|
||||
printf("%s PSRAM alloc failed for pointer table\n", TAG_SR);
|
||||
file.close();
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < spriteNumber; i++) {
|
||||
|
||||
scaled[i] =
|
||||
(uint16_t*) ps_malloc(scaledW * scaledH * sizeof(uint16_t));
|
||||
|
||||
if (!scaled[i]) {
|
||||
printf("%s PSRAM alloc failed for sprite %d\n", TAG_SR, i);
|
||||
|
||||
for (uint8_t j = 0; j < i; j++) {
|
||||
free(scaled[j]);
|
||||
}
|
||||
|
||||
free(scaled);
|
||||
file.close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t* spriteBuf =
|
||||
(uint16_t*) malloc(width * height * sizeof(uint16_t));
|
||||
|
||||
if (!spriteBuf) {
|
||||
printf("%s scratch alloc failed\n", TAG_SR);
|
||||
|
||||
for (uint8_t i = 0; i < spriteNumber; i++) {
|
||||
free(scaled[i]);
|
||||
}
|
||||
|
||||
free(scaled);
|
||||
file.close();
|
||||
return;
|
||||
}
|
||||
|
||||
printf(
|
||||
"%s Read header: width=%d, height=%d, numSprites=%d -> scaled to %dx%d\n",
|
||||
TAG_SR,
|
||||
width,
|
||||
height,
|
||||
spriteNumber,
|
||||
scaledW,
|
||||
scaledH
|
||||
);
|
||||
|
||||
for (int sprN = 0; sprN < spriteNumber; sprN++) {
|
||||
|
||||
// Read original sprite into temporary buffer
|
||||
for (int y = 0; y < height; y++) {
|
||||
|
||||
for (int x = 0; x < width; x++) {
|
||||
|
||||
uint8_t hi, lo;
|
||||
|
||||
file.read(&hi, 1);
|
||||
file.read(&lo, 1);
|
||||
|
||||
spriteBuf[y * width + x] =
|
||||
(lo << 8) | hi;
|
||||
}
|
||||
}
|
||||
|
||||
// Upscale sprite
|
||||
utils_upscaleSprite(
|
||||
spriteBuf,
|
||||
width,
|
||||
height,
|
||||
scaled[sprN]
|
||||
);
|
||||
}
|
||||
|
||||
free(spriteBuf);
|
||||
file.close();
|
||||
|
||||
spriteData->spriteWidth = scaledW;
|
||||
spriteData->spriteHeight = scaledH;
|
||||
spriteData->spriteNumber = spriteNumber;
|
||||
spriteData->spriteData = scaled;
|
||||
|
||||
printf(
|
||||
"%s Loaded & upscaled %s (%d sprites, each %dx%d px)\n",
|
||||
TAG_SR,
|
||||
path,
|
||||
spriteNumber,
|
||||
scaledW,
|
||||
scaledH
|
||||
);
|
||||
}
|
||||
+20
-89
@@ -8,8 +8,6 @@
|
||||
|
||||
const char* TAG_S = "[STORAGE]";
|
||||
|
||||
#define SPRITE_SCALE 6
|
||||
|
||||
void storage_init() {
|
||||
if (!SPIFFS.begin(true)) {
|
||||
printf("%s Failed to mount file system\n", TAG_S);
|
||||
@@ -19,95 +17,11 @@ void storage_init() {
|
||||
}
|
||||
|
||||
|
||||
void storage_readFile(const char* path, struct SpriteData* spriteData) {
|
||||
File file = SPIFFS.open(path, "r");
|
||||
if (!file) {
|
||||
printf("%s Failed to open file for reading\n", TAG_S);
|
||||
return;
|
||||
}
|
||||
void storage_initBackground(const int id, TFT_eSprite& bg) {
|
||||
char path[15];
|
||||
|
||||
uint8_t width, height, spriteNumber;
|
||||
snprintf(path, 15, "/bg/%i.bin", id);
|
||||
|
||||
file.read(&width, 1);
|
||||
file.read(&height, 1);
|
||||
file.read(&spriteNumber, 1);
|
||||
|
||||
if (spriteData->spriteData != NULL) {
|
||||
memory_free(spriteData);
|
||||
}
|
||||
|
||||
const uint8_t scaledW = width * SPRITE_SCALE;
|
||||
const uint8_t scaledH = height * SPRITE_SCALE;
|
||||
|
||||
uint16_t** scaled = (uint16_t**) ps_malloc(spriteNumber * sizeof(uint16_t*));
|
||||
if (!scaled) {
|
||||
printf("%s PSRAM alloc failed for pointer table\n", TAG_S);
|
||||
file.close();
|
||||
return;
|
||||
}
|
||||
for (uint8_t i = 0; i < spriteNumber; i++) {
|
||||
scaled[i] = (uint16_t*) ps_malloc(scaledW * scaledH * sizeof(uint16_t));
|
||||
if (!scaled[i]) {
|
||||
printf("%s PSRAM alloc failed for sprite %d\n", TAG_S, i);
|
||||
for (uint8_t j = 0; j < i; j++) free(scaled[j]);
|
||||
free(scaled);
|
||||
file.close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t* rowBuf = (uint16_t*) malloc(width * sizeof(uint16_t));
|
||||
if (!rowBuf) {
|
||||
printf("%s scratch alloc failed\n", TAG_S);
|
||||
for (uint8_t i = 0; i < spriteNumber; i++) free(scaled[i]);
|
||||
free(scaled);
|
||||
file.close();
|
||||
return;
|
||||
}
|
||||
|
||||
printf(
|
||||
"%s Read header: width=%d, height=%d, numSprites=%d -> scaled to %dx%d\n",
|
||||
TAG_S, width, height, spriteNumber, scaledW, scaledH
|
||||
);
|
||||
|
||||
for (int sprN = 0; sprN < spriteNumber; sprN++) {
|
||||
uint16_t* dst = scaled[sprN];
|
||||
|
||||
for (int srcY = 0; srcY < height; srcY++) {
|
||||
for (int srcX = 0; srcX < width; srcX++) {
|
||||
uint8_t hi, lo;
|
||||
file.read(&hi, 1);
|
||||
file.read(&lo, 1);
|
||||
rowBuf[srcX] = (lo << 8) | hi;
|
||||
}
|
||||
|
||||
for (int dy = 0; dy < SPRITE_SCALE; dy++) {
|
||||
uint16_t* dstRow = dst + (srcY * SPRITE_SCALE + dy) * scaledW;
|
||||
|
||||
for (int srcX = 0; srcX < width; srcX++) {
|
||||
uint16_t color = rowBuf[srcX];
|
||||
uint16_t* dstPixel = dstRow + srcX * SPRITE_SCALE;
|
||||
for (int dx = 0; dx < SPRITE_SCALE; dx++) {
|
||||
dstPixel[dx] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(rowBuf);
|
||||
file.close();
|
||||
|
||||
spriteData->spriteWidth = scaledW;
|
||||
spriteData->spriteHeight = scaledH;
|
||||
spriteData->spriteNumber = spriteNumber;
|
||||
spriteData->spriteData = scaled;
|
||||
|
||||
printf("%s Loaded & upscaled %s (%d sprites, each %dx%d px)\n",
|
||||
TAG_S, path, spriteNumber, scaledW, scaledH);
|
||||
}
|
||||
|
||||
void storage_initBackground(const char* path, TFT_eSprite& bg) {
|
||||
File file = SPIFFS.open(path, "r");
|
||||
if (!file) {
|
||||
printf("%s Failed to open file for reading\n", TAG_S);
|
||||
@@ -305,3 +219,20 @@ void storage_loadState() {
|
||||
|
||||
printf("%s Load completed!\n", TAG_S);
|
||||
}
|
||||
|
||||
bool storage_deleteState() {
|
||||
const char* savePath = "/save.bin";
|
||||
|
||||
if (!SPIFFS.exists(savePath)) {
|
||||
printf("%s Save file already deleted.\n", TAG_S);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!SPIFFS.remove(savePath)) {
|
||||
printf("%s Failed to delete save file.\n", TAG_S);
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("%s Save file deleted.\n", TAG_S);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -9,9 +9,10 @@
|
||||
|
||||
void storage_init();
|
||||
void storage_readFile(const char* path, struct SpriteData* spriteData);
|
||||
void storage_initBackground(const char* path, TFT_eSprite &bg);
|
||||
void storage_initBackground(const int id, TFT_eSprite &bg);
|
||||
|
||||
void storage_saveState();
|
||||
void storage_loadState();
|
||||
bool storage_deleteState();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "utils.h"
|
||||
#include "defs/defs.h"
|
||||
|
||||
|
||||
/**
|
||||
* Upscale a sprite using nearest-neighbor scaling.
|
||||
*
|
||||
* @param src Pointer to source sprite pixels
|
||||
* @param srcWidth Original sprite width
|
||||
* @param srcHeight Original sprite height
|
||||
* @param dst Destination buffer for upscaled sprite
|
||||
*/
|
||||
void utils_upscaleSprite(
|
||||
const uint16_t* src,
|
||||
uint8_t srcWidth,
|
||||
uint8_t srcHeight,
|
||||
uint16_t* dst
|
||||
) {
|
||||
const uint8_t scaledW = srcWidth * SPRITE_SCALE;
|
||||
|
||||
for (int srcY = 0; srcY < srcHeight; srcY++) {
|
||||
|
||||
for (int dy = 0; dy < SPRITE_SCALE; dy++) {
|
||||
|
||||
uint16_t* dstRow =
|
||||
dst + ((srcY * SPRITE_SCALE + dy) * scaledW);
|
||||
|
||||
for (int srcX = 0; srcX < srcWidth; srcX++) {
|
||||
|
||||
uint16_t color = src[srcY * srcWidth + srcX];
|
||||
|
||||
uint16_t* dstPixel =
|
||||
dstRow + (srcX * SPRITE_SCALE);
|
||||
|
||||
for (int dx = 0; dx < SPRITE_SCALE; dx++) {
|
||||
dstPixel[dx] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
|
||||
void utils_upscaleSprite(
|
||||
const uint16_t* src,
|
||||
uint8_t srcWidth,
|
||||
uint8_t srcHeight,
|
||||
uint16_t* dst
|
||||
);
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "lines.h"
|
||||
#include "memory/memory.h"
|
||||
#include "defs/defs.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
#include <FS.h>
|
||||
#include <SPIFFS.h>
|
||||
@@ -40,39 +41,69 @@ void lines_getAvailableLines() {
|
||||
lineFile = root.openNextFile("r");
|
||||
|
||||
while (lineFile) {
|
||||
uint16_t bytesRead = lineFile.readBytes(header, headerSize);
|
||||
uint16_t bytesRead = 0;
|
||||
|
||||
bytesRead += lineFile.readBytes(header, headerSize);
|
||||
bytesRead += lineFile.read(&availableLines[allocCount].id, 1);
|
||||
bytesRead += lineFile.readBytes(availableLines[allocCount].name, 16);
|
||||
|
||||
bytesRead += lineFile.read(&availableLines[allocCount].eggSprite.spriteWidth, 1);
|
||||
bytesRead += lineFile.read(&availableLines[allocCount].eggSprite.spriteHeight, 1);
|
||||
bytesRead += lineFile.read(&availableLines[allocCount].eggSprite.spriteNumber, 1); // Se coloca el cursor al principio de los datos de sprite
|
||||
uint8_t originalWidth;
|
||||
uint8_t originalHeight;
|
||||
uint8_t spriteCount;
|
||||
|
||||
availableLines[allocCount].eggSprite.spriteNumber = 1; // Inutil, pero es que necesito hacer la lectura
|
||||
bytesRead += lineFile.read(&originalWidth, 1);
|
||||
bytesRead += lineFile.read(&originalHeight, 1);
|
||||
bytesRead += lineFile.read(&spriteCount, 1);
|
||||
|
||||
availableLines[allocCount].eggSprite.spriteData = memory_allocate(
|
||||
availableLines[allocCount].eggSprite.spriteNumber,
|
||||
availableLines[allocCount].eggSprite.spriteWidth,
|
||||
availableLines[allocCount].eggSprite.spriteHeight
|
||||
);
|
||||
const uint8_t scaledWidth = originalWidth * SPRITE_SCALE;
|
||||
const uint8_t scaledHeight = originalHeight * SPRITE_SCALE;
|
||||
|
||||
availableLines[allocCount].eggSprite.spriteWidth = scaledWidth;
|
||||
availableLines[allocCount].eggSprite.spriteHeight = scaledHeight;
|
||||
availableLines[allocCount].eggSprite.spriteNumber = 1;
|
||||
availableLines[allocCount].eggSprite.spriteData = memory_allocate(1, scaledWidth, scaledHeight);
|
||||
|
||||
uint16_t* spriteBuffer =
|
||||
(uint16_t*) malloc(
|
||||
originalWidth *
|
||||
originalHeight *
|
||||
sizeof(uint16_t)
|
||||
);
|
||||
|
||||
if (!spriteBuffer) {
|
||||
printf("[LINES] Failed to allocate sprite buffer\n");
|
||||
|
||||
lineFile.close();
|
||||
lineFile = root.openNextFile();
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8_t highByte;
|
||||
uint8_t lowByte;
|
||||
|
||||
for (int i = 0; i < availableLines[allocCount].eggSprite.spriteWidth * availableLines[allocCount].eggSprite.spriteHeight; i++) {
|
||||
bytesRead += lineFile.read(&highByte, 1);
|
||||
for (int i = 0; i < originalWidth * originalHeight; i++) {
|
||||
bytesRead += lineFile.read(&lowByte, 1);
|
||||
bytesRead += lineFile.read(&highByte, 1);
|
||||
|
||||
uint16_t pixel = (highByte << 8) | lowByte;
|
||||
|
||||
availableLines[allocCount].eggSprite.spriteData[0][i] = pixel;
|
||||
spriteBuffer[i] = (highByte << 8) | lowByte;
|
||||
}
|
||||
|
||||
utils_upscaleSprite(
|
||||
spriteBuffer,
|
||||
originalWidth,
|
||||
originalHeight,
|
||||
availableLines[allocCount].eggSprite.spriteData[0]
|
||||
);
|
||||
|
||||
free(spriteBuffer);
|
||||
|
||||
strcpy(availableLines[allocCount].fileName, lineFile.name());
|
||||
|
||||
lineFile.close();
|
||||
|
||||
allocCount++;
|
||||
|
||||
lineFile = root.openNextFile();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "lines.h"
|
||||
#include "memory/memory.h"
|
||||
#include "defs/defs.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
#include <FS.h>
|
||||
#include <SPIFFS.h>
|
||||
@@ -40,37 +41,76 @@ void lines_getSingleLine(const char* fileName) {
|
||||
currentLine[currentCharacter] = selectedLine;
|
||||
currentEgg = selectedEgg;
|
||||
}
|
||||
|
||||
void lines_getSingleEggSprites(fs::File &lineFile, Egg_t* selectedEgg) {
|
||||
|
||||
// Importante tener el nombre de archivo del huevo en todo momento
|
||||
strcpy(selectedEgg->fileName, lineFile.name());
|
||||
|
||||
// Ahora se lee los datos
|
||||
lineFile.read(&(selectedEgg->eggSprite.spriteWidth), 1);
|
||||
lineFile.read(&(selectedEgg->eggSprite.spriteHeight), 1);
|
||||
// Leer dimensiones originales
|
||||
uint8_t originalWidth;
|
||||
uint8_t originalHeight;
|
||||
|
||||
lineFile.read(&originalWidth, 1);
|
||||
lineFile.read(&originalHeight, 1);
|
||||
lineFile.read(&(selectedEgg->eggSprite.spriteNumber), 1);
|
||||
|
||||
const uint8_t scaledWidth = originalWidth * SPRITE_SCALE;
|
||||
const uint8_t scaledHeight = originalHeight * SPRITE_SCALE;
|
||||
|
||||
// Guardar dimensiones escaladas
|
||||
selectedEgg->eggSprite.spriteWidth = scaledWidth;
|
||||
selectedEgg->eggSprite.spriteHeight = scaledHeight;
|
||||
|
||||
// Reservar memoria para sprites escalados
|
||||
selectedEgg->eggSprite.spriteData = memory_allocate(
|
||||
selectedEgg->eggSprite.spriteNumber,
|
||||
selectedEgg->eggSprite.spriteWidth,
|
||||
selectedEgg->eggSprite.spriteHeight
|
||||
scaledWidth,
|
||||
scaledHeight
|
||||
);
|
||||
|
||||
uint16_t size = selectedEgg->eggSprite.spriteWidth * selectedEgg->eggSprite.spriteHeight;
|
||||
const uint16_t originalSize =
|
||||
originalWidth * originalHeight;
|
||||
|
||||
// Buffer temporal en SRAM
|
||||
uint16_t* spriteBuffer =
|
||||
(uint16_t*) malloc(
|
||||
originalSize * sizeof(uint16_t)
|
||||
);
|
||||
|
||||
if (!spriteBuffer) {
|
||||
printf("[LINES] Failed to allocate sprite buffer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t highByte;
|
||||
uint8_t lowByte;
|
||||
|
||||
for (int spr = 0; spr < selectedEgg->eggSprite.spriteNumber; spr++) {
|
||||
for (int i= 0; i < size; i++) {
|
||||
lineFile.read(&highByte, 1);
|
||||
for (
|
||||
int spr = 0;
|
||||
spr < selectedEgg->eggSprite.spriteNumber;
|
||||
spr++
|
||||
) {
|
||||
|
||||
// Leer sprite original
|
||||
for (int i = 0; i < originalSize; i++) {
|
||||
|
||||
lineFile.read(&lowByte, 1);
|
||||
lineFile.read(&highByte, 1);
|
||||
|
||||
uint16_t pixel = (highByte << 8) | lowByte;
|
||||
|
||||
selectedEgg->eggSprite.spriteData[spr][i] = pixel;
|
||||
spriteBuffer[i] =
|
||||
(highByte << 8) | lowByte;
|
||||
}
|
||||
|
||||
// Escalar sprite
|
||||
utils_upscaleSprite(
|
||||
spriteBuffer,
|
||||
originalWidth,
|
||||
originalHeight,
|
||||
selectedEgg->eggSprite.spriteData[spr]
|
||||
);
|
||||
}
|
||||
|
||||
free(spriteBuffer);
|
||||
}
|
||||
|
||||
// Son las 22:35, que estoy haciendo?
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "draw/draw.h"
|
||||
#include "defs/defs.h"
|
||||
#include "defs/chara_data.h"
|
||||
#include "defs/sounds.h"
|
||||
#include "defs/sprite_data.h"
|
||||
#include "display/display.h"
|
||||
|
||||
@@ -100,20 +101,5 @@ void training_displayTrainingResult(
|
||||
|
||||
// nOT FANCY
|
||||
void training_trainingAttackSounds() {
|
||||
tone(SPK_PIN, 4100, 25);
|
||||
tone(SPK_PIN, 3700, 25);
|
||||
tone(SPK_PIN, 4100, 25);
|
||||
tone(SPK_PIN, 3700, 25);
|
||||
tone(SPK_PIN, 4100, 25);
|
||||
tone(SPK_PIN, 3700, 25);
|
||||
tone(SPK_PIN, 4100, 25);
|
||||
tone(SPK_PIN, 3700, 25);
|
||||
tone(SPK_PIN, 3700, 25);
|
||||
tone(SPK_PIN, 3100, 25);
|
||||
tone(SPK_PIN, 3700, 25);
|
||||
tone(SPK_PIN, 3100, 25);
|
||||
tone(SPK_PIN, 3700, 25);
|
||||
tone(SPK_PIN, 3100, 25);
|
||||
tone(SPK_PIN, 3700, 25);
|
||||
tone(SPK_PIN, 3100, 25);
|
||||
sound_playMelody(SOUND_TRAINING_ATTACK, SOUND_NOTE_COUNT(SOUND_TRAINING_ATTACK));
|
||||
}
|
||||
Reference in New Issue
Block a user