From cc5fcd4ac2621afcb04965bfe02bcdc9a0ec90b0 Mon Sep 17 00:00:00 2001 From: Nacho Date: Wed, 28 May 2025 03:15:48 +0200 Subject: [PATCH] Cosas, muchas cosas, exageracion de cossas, abundancia de cosas.... - Seleccion de huevo - Scripts de conversion de linea - Carga de sprites - Se produce nacimiento --- scripts/sprite_creator.py | 71 ++++++++++++++++++++++++++ src/animations/animations.h | 6 +++ src/animations/sprite_animation.cpp | 14 +++++ src/buttons/buttons.cpp | 3 +- src/defs/chara_data.h | 9 +++- src/defs/defs.h | 24 ++++++++- src/display/display.cpp | 2 +- src/main.cpp | 57 +++++++++++++++------ src/menu/clock_screen.cpp | 21 ++++---- src/menu/death_screen.cpp | 46 +++++++++++++++++ src/menu/egg_hatch_screen.cpp | 70 +++++++++++++++++++++++++ src/menu/egg_select_screen.cpp | 58 +++++++++++++++++++++ src/menu/food_select_screen.cpp | 2 + src/menu/idle_screen.cpp | 15 ++++-- src/menu/menu.h | 4 ++ src/menu/title_screen.cpp | 3 +- src/vpet/lines/free_lines.cpp | 29 +++++++++++ src/vpet/lines/get_available_lines.cpp | 40 +++------------ src/vpet/lines/get_care_mistakes.cpp | 5 +- src/vpet/lines/get_single_line.cpp | 23 ++++----- src/vpet/lines/init_lines.cpp | 12 +++++ src/vpet/lines/lines.h | 12 +++-- src/vpet/lines/on_hatch_finished.cpp | 37 ++++++++++++++ src/vpet/vpet.cpp | 25 +++++++-- 24 files changed, 494 insertions(+), 94 deletions(-) create mode 100644 scripts/sprite_creator.py create mode 100644 src/menu/death_screen.cpp create mode 100644 src/menu/egg_hatch_screen.cpp create mode 100644 src/menu/egg_select_screen.cpp create mode 100644 src/vpet/lines/free_lines.cpp create mode 100644 src/vpet/lines/init_lines.cpp create mode 100644 src/vpet/lines/on_hatch_finished.cpp diff --git a/scripts/sprite_creator.py b/scripts/sprite_creator.py new file mode 100644 index 0000000..ea68187 --- /dev/null +++ b/scripts/sprite_creator.py @@ -0,0 +1,71 @@ +from PIL import Image +import os +import sys + +def create_new_canvas(width: int, height: int): + new_canvas = Image.new("RGBA", (width, height), color=(0, 0, 0, 0)) + return new_canvas + + +def get_image_files(dir: str): + files = os.listdir(dir) + image_files = [ file for file in files if file.endswith("png") ] + return image_files + + +def check_correct_amount_of_images(image_files: list[str]): + return len(image_files) == 12 + + +def reduce_image(file_name: str): + image = Image.open(file_name) + result_image = Image.new("RGBA", (16, 16), color=(0, 0, 0, 0)) + + width, height = image.size + + if 48 not in (width, height): + print("Invalid again") + return None + + for x in range(width // 3): + for y in range(height // 3): + pixel = image.getpixel((x * 3, y * 3)) + result_image.putpixel((x, y), pixel) + + return result_image + +def append_image(image, canvas, n): + width, height = canvas.size + + n_tiles_x = width // 16 + + x = (n % n_tiles_x) * 16 + y = (n // n_tiles_x) * 16 + + canvas.paste(image, (x, y)) + + return canvas + + +if __name__ == "__main__": + if len(sys.argv) < 3: + print("invalido") + sys.exit(-1) + + new_canvas = create_new_canvas(48, 64) + image_files = get_image_files(sys.argv[1]) + if not check_correct_amount_of_images(image_files): + sys.exit(-1) + + resulting_images = [] + + for i in range(12): + resulting_image = reduce_image(f'{sys.argv[1]}/{i}.png') + new_canvas = append_image(resulting_image, new_canvas, i) + + + new_canvas.save(sys.argv[2]) + + print("Sprite sheet creada!!") + + exit(0) \ No newline at end of file diff --git a/src/animations/animations.h b/src/animations/animations.h index a3b25c6..2ccbedc 100644 --- a/src/animations/animations.h +++ b/src/animations/animations.h @@ -9,6 +9,7 @@ const int numFramesEating = 2; const int numFramesHappy = 2; const int numFramesRefuse = 4; const int numFramesSleepy = 2; +const int numFramesHatching = 4; // TODO: Cambiar a una animación mas atractiva const int animationFrames[numFrames] = { @@ -53,11 +54,16 @@ const int happyAnimationFrames[] = { 3, 7 }; +const int hatchingAnimationPositions[] = { + 72, 66, 72, 78 +}; + void animate_performAnimation(TFT_eSprite &buffer, TFT_eSprite &spr, struct SpriteData* spriteData, uint8_t offsetX); void animate_performAttentionAnimation(TFT_eSprite &buffer, TFT_eSprite &spr, struct SpriteData* spriteData); void animate_performEatingAnimation(TFT_eSprite &buffer, TFT_eSprite &spr, struct SpriteData* spriteData); void animate_performRefuseAnimation(TFT_eSprite &buffer, TFT_eSprite &spr, struct SpriteData* spriteData); void animate_performSleepyAnimation(TFT_eSprite &buffer, TFT_eSprite &spr, struct SpriteData* spriteData); void animate_performHappyAnimation(TFT_eSprite &buffer, TFT_eSprite &spr, struct SpriteData* spriteData); +void animate_performHatchingAnimation(TFT_eSprite &buffer, TFT_eSprite &spr, struct SpriteData* spriteData); #endif \ No newline at end of file diff --git a/src/animations/sprite_animation.cpp b/src/animations/sprite_animation.cpp index 3d7d117..ca4d5a8 100644 --- a/src/animations/sprite_animation.cpp +++ b/src/animations/sprite_animation.cpp @@ -92,4 +92,18 @@ void animate_performHappyAnimation(TFT_eSprite &buffer, TFT_eSprite &spr, struct 6, false ); +} + +void animate_performHatchingAnimation(TFT_eSprite &buffer, TFT_eSprite &spr, struct SpriteData* spriteData) { + currentAnimationFrame = (currentAnimationFrame + 1) % numFramesHappy; + draw_drawSprite( + buffer, + spr, + hatchingAnimationPositions[currentAnimationFrame], + spriteHeightOnScreen, + spriteData, + 0, + 6, + false + ); } \ No newline at end of file diff --git a/src/buttons/buttons.cpp b/src/buttons/buttons.cpp index fd1962d..09783e4 100644 --- a/src/buttons/buttons.cpp +++ b/src/buttons/buttons.cpp @@ -1,4 +1,5 @@ #include "defs/defs.h" +#include "defs/chara_data.h" #include "buttons.h" #include @@ -20,7 +21,7 @@ void buttons_checkInactivity() { screenOff = true; } else if (currentTime - lastPressedButtonTime > LAST_PRESSED_BUTTON_THRESHOLD_TIME_US && !inactive) { - screenKey = IDLE_SCREEN; + screenKey = IDLE_SCREEN; inactive = true; } } diff --git a/src/defs/chara_data.h b/src/defs/chara_data.h index 7b1ac13..801193b 100644 --- a/src/defs/chara_data.h +++ b/src/defs/chara_data.h @@ -5,6 +5,10 @@ struct CharacterData { // Calculated at runtime + bool hatching = false; + bool hatched = false; + uint16_t hatchTimer = 0; + uint8_t hunger; uint8_t strength; uint8_t weight; @@ -37,6 +41,7 @@ struct CharacterData { bool asleep = false; bool injured = false; bool dead = false; + bool traited = true; // Obtained from structure uint8_t idChara; @@ -50,8 +55,8 @@ struct CharacterData { uint8_t stage; uint8_t attribute; - uint32_t sleepTime = 75600; - uint32_t wakeupTime = 25200; + uint32_t sleepTime; + uint32_t wakeupTime; uint32_t evoTime; diff --git a/src/defs/defs.h b/src/defs/defs.h index a1b83f9..b606295 100644 --- a/src/defs/defs.h +++ b/src/defs/defs.h @@ -6,6 +6,7 @@ #include "defs/background_data.h" #include "defs/sprite_data.h" +#include "defs/file_chara.h" #define VERSION "Alpha v0.1" @@ -45,8 +46,8 @@ #define RTC_TIMEOUT_THRESHOLD_TIME_MS 100 // STANDARD BEEP WHEN PRESSING BUTTON -#define BEEP_FREQ_HZ 3000 -#define BEEP_LEN_MS 50 +#define BEEP_FREQ_HZ 4100 +#define BEEP_LEN_MS 35 // MENU ENTRIES #define STATUS_SCREEN_MENU 0 @@ -79,6 +80,7 @@ #define SETTINGS_SCREEN_ICON 7 #define CARE_MISTAKE_CALL_LIGHT 8 #define BED_SPRITE 9 +#define EMPTY_EGG 10 // SCREENS #define OFF_SCREEN -1 @@ -87,6 +89,9 @@ #define CLOCK_SCREEN 2 #define IDLE_SCREEN 3 #define MENU_SCREEN 4 +#define EGG_SELECT_SCREEN 5 +#define EGG_HATCH_SCREEN 6 +#define EGG_EMPTY_SCREEN 7 #define FEEDING_SCREEN 20 #define REFUSING_SCREEN 21 #define SLEEPY_SCREEN 22 @@ -127,6 +132,8 @@ #define K4_PRESSED 1 #define NONE_PRESSED 0 +#define CHARA_COUNT_IN_DEVICE 5 + extern int screenKey; extern int menuKey; extern int submenuKey; @@ -159,4 +166,17 @@ extern uint8_t beepCounter; extern uint16_t stepCounter; +extern bool coldBoot; + +extern uint8_t eggNumber; +extern Egg_t* eggSelection; + +extern uint8_t currentCharacter; + +extern Egg_t* currentEgg; +extern LineCare_t** currentLineCareInstr; +extern Line_t** currentLine; + +extern struct SpriteData mainCharacterSprites; + #endif \ No newline at end of file diff --git a/src/display/display.cpp b/src/display/display.cpp index 4023247..394f40a 100644 --- a/src/display/display.cpp +++ b/src/display/display.cpp @@ -3,7 +3,7 @@ void tft_initDisplay(TFT_eSPI &tft, uint16_t color) { tft.init(); tft.setRotation(0); - tft.fillScreen(TFT_RED); + tft.fillScreen(color); } void tft_initScreenBuffer(TFT_eSprite &buffer, uint16_t color) { diff --git a/src/main.cpp b/src/main.cpp index d01c91b..4312cc6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,29 +14,50 @@ const char* TAG = "[MAIN]"; +// TFT_eSPI stuff, important TFT_eSPI tft = TFT_eSPI(); TFT_eSprite composite = TFT_eSprite(&tft); TFT_eSprite sprite = TFT_eSprite(&tft); TFT_eSprite bg = TFT_eSprite(&tft); +// External devices stuff +MPU6050 mpu; +ESP32Time rtc(0); + +// Sprite data and background data struct BackgroundData backgroundData; struct SpriteData mainCharacterSprites; struct SpriteData menuElementsData; struct SpriteData uiElementsData; +// Active character data +// TODO: Split into CHARA_COUNT_IN_DEVICE times struct CharacterData charaData; +uint8_t currentCharacter = 0; +// Boot flag, tells if the device clock has been initialized +bool coldBoot = true; + +// Screen keys, this tells which screen is being shown the screens state machine int screenKey = TITLE_SCREEN; int menuKey = STATUS_SCREEN_MENU; int submenuKey = -1; -uint32_t dayUnixTime = 0; +// Step counter, counts steps, duh +// TODO: Reset with each day, maybe have a log of steps uint16_t stepCounter = 0; +// Time stuff, timeInfo is the time structure used by everything, updated in loop2 +// dayUnixTime is used to tell the day time, in UNIX seconds struct tm timeInfo; +uint32_t dayUnixTime = 0; -MPU6050 mpu; -ESP32Time rtc(0); +// Egg stuff, initializes it to zero, used by the algorithm to tell if something has +// been malloc'd into memory, +Egg_t* eggSelection = NULL; +uint8_t eggNumber = 0; + +// Tasks TaskHandle_t secondLoop = NULL; void loop2(); @@ -54,7 +75,6 @@ void setup() { storage_init(); - storage_readFile("/sprite.bin", &mainCharacterSprites); storage_readFile("/menu.bin", &menuElementsData); storage_readFile("/ui.bin", &uiElementsData); @@ -65,21 +85,13 @@ void setup() { pinMode(K3_PIN, INPUT_PULLUP); pinMode(K4_PIN, INPUT_PULLUP); - charaData.hunger = 4; - charaData.strength = 4; - charaData.effort = 4; - - charaData.evoLeftTimer = 60; - charaData.hungerCareMistakeTimer = 60; - charaData.strengthCareMistakeTimer = 60; - xTaskCreatePinnedToCore(secondCoreTask, "VPET_EVAL", 4096, NULL, 0, &secondLoop, 0); - + debug_printFreeMemory(); - lines_testLines(); // REMOVE + lines_initLineStorage(); - debug_printFreeMemory(); + vpet_initTimer(); } @@ -152,6 +164,18 @@ void loop() { case HAPPY_SCREEN: menu_drawHappyScreen(composite, bg, sprite, &mainCharacterSprites, &uiElementsData); break; + + case EGG_HATCH_SCREEN: + menu_eggHatchScreen(composite, bg, sprite, &menuElementsData, &uiElementsData); + break; + + case EGG_SELECT_SCREEN: + menu_lineSwitcher(composite, bg, sprite, &uiElementsData); + break; + + case EGG_EMPTY_SCREEN: + menu_drawDeathScreen(composite, bg, sprite, &menuElementsData, &uiElementsData); + break; } } @@ -159,6 +183,9 @@ void loop2() { steps_countSteps(); buttons_checkInactivity(); vpet_runVpetTasks(); + + getLocalTime(&timeInfo, 50); + dayUnixTime = mktime(&timeInfo) % 86400; } void secondCoreTask(void*) { diff --git a/src/menu/clock_screen.cpp b/src/menu/clock_screen.cpp index 5877b8a..e3cb672 100644 --- a/src/menu/clock_screen.cpp +++ b/src/menu/clock_screen.cpp @@ -8,12 +8,12 @@ void menu_drawClock(TFT_eSprite &composite, TFT_eSprite &bg, int menuOption) { uint8_t pressedButtons = buttons_getPressedButtons(); switch (pressedButtons) { - case 4: - screenKey = IDLE_SCREEN; - break; + case K2_PRESSED: + screenKey = IDLE_SCREEN; + break; default: - break; + break; } char hourBuffer[6]; @@ -39,26 +39,25 @@ void menu_drawClockEdit(TFT_eSprite &composite, TFT_eSprite &bg) { static int clockMinuteCount = 0; uint8_t pressedButtons = buttons_getPressedButtons(); - lastPressedButtonTime = esp_timer_get_time(); switch (pressedButtons) { - case 8: + case K1_PRESSED: clockHourCount = (clockHourCount + 1) % 24; break; - case 4: + case K2_PRESSED: clockMinuteCount = (clockMinuteCount + 1) % 60; break; - case 2: + case K3_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); getLocalTime(&timeInfo, 50); dayUnixTime = mktime(&timeInfo) % 86400; - screenKey = CLOCK_SCREEN; - onActionTimerDelta(); - vpet_initTimer(); + coldBoot = false; + screenKey = CLOCK_SCREEN; break; default: diff --git a/src/menu/death_screen.cpp b/src/menu/death_screen.cpp new file mode 100644 index 0000000..44637ab --- /dev/null +++ b/src/menu/death_screen.cpp @@ -0,0 +1,46 @@ +#include "menu.h" +#include "defs/defs.h" +#include "draw/draw.h" +#include "display/display.h" +#include "buttons/buttons.h" +#include "defs/sprite_data.h" +#include "vpet/lines/lines.h" + +void menu_drawDeathScreen(TFT_eSprite &composite, TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* uiBigSprite, struct SpriteData* uiSmallSprite) { + static uint8_t frameCounter = 0; + uint64_t currentTime = esp_timer_get_time(); + + uint8_t pressedButtons = buttons_getPressedButtons(); + switch (pressedButtons) { + case K1_PRESSED: + lines_getAvailableLines(); + screenKey = EGG_SELECT_SCREEN; + return; + break; + + case K2_PRESSED: + screenKey = CLOCK_SCREEN; + return; + break; + + case K3_PRESSED: + lastUpdateTime = currentTime; + frameCounter = 0; + + default: + break; + } + + if (currentTime - lastUpdateTime > ANIMATION_THRESHOLD_TIME_US) { + draw_drawBackground(composite, bg, 90, 90, 3); + draw_drawSprite(composite, sprite, 72 + (6 * (frameCounter == 0)), 72, uiBigSprite, EMPTY_EGG, 6); + tft_clearBuffer(sprite, TFT_TRANSPARENT); + menu_uiOverlay(composite, sprite, uiSmallSprite); + tft_clearBuffer(sprite, TFT_TRANSPARENT); + + frameCounter = (frameCounter + 1) % 32; + lastUpdateTime = currentTime; + } + + tft_drawBuffer(composite); +} \ No newline at end of file diff --git a/src/menu/egg_hatch_screen.cpp b/src/menu/egg_hatch_screen.cpp new file mode 100644 index 0000000..c2d9ba5 --- /dev/null +++ b/src/menu/egg_hatch_screen.cpp @@ -0,0 +1,70 @@ +#include "menu.h" +#include "draw/draw.h" +#include "display/display.h" +#include "buttons/buttons.h" +#include "defs/defs.h" +#include "defs/sprite_data.h" +#include "defs/chara_data.h" +#include "animations/animations.h" +#include "vpet/vpet.h" +#include "vpet/lines/lines.h" + +void menu_eggHatchScreen(TFT_eSprite &composite, TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* uiBigSprite, struct SpriteData* uiSmallSprite) { + static bool eggSpriteFrame = false; + uint8_t frameCounter = 0; + + uint8_t pressedButtons = buttons_getPressedButtons(); + switch (pressedButtons) { + case K3_PRESSED: + case K1_PRESSED: + break; + + case K2_PRESSED: + screenKey = CLOCK_SCREEN; + break; + + default: + break; + } + + uint64_t currentTime = esp_timer_get_time(); + if (currentTime - lastUpdateTime > ANIMATION_THRESHOLD_TIME_US) { + if (charaData.hatchTimer <= currentLine[currentCharacter]->hatchTime) { + draw_drawBackground(composite, bg, 90, 90, 3); + draw_drawSpriteCentered(composite, sprite, ¤tEgg->eggSprite, eggSpriteFrame, 6); + + eggSpriteFrame = !eggSpriteFrame; + lastUpdateTime = currentTime; + + tft_drawBuffer(composite); + + + } else if (charaData.hatchTimer > currentLine[currentCharacter]->hatchTime && !charaData.hatched) { + for (int i = 0; i < 30; i++) { + tone(SPK_PIN, 4100, 35); + tone(SPK_PIN, 3500, 35); + + draw_drawBackground(composite, bg, 90, 90, 3); + animate_performHatchingAnimation(composite, sprite, ¤tEgg->eggSprite); + + tft_drawBuffer(composite); + } + + draw_drawBackground(composite, bg, 90, 90, 3); + draw_drawSpriteCentered(composite, sprite, ¤tEgg->eggSprite, 2, 6); + + tft_drawBuffer(composite); + + delay(2000); + + lines_onHatchComplete(); + + vpet_computeCallLight(); + + interruptKey = CARE_MISTAKE_SCREEN; + screenKey = TIMER_FINISHED_SCREEN; + + return; + } + } +} \ No newline at end of file diff --git a/src/menu/egg_select_screen.cpp b/src/menu/egg_select_screen.cpp new file mode 100644 index 0000000..d71f581 --- /dev/null +++ b/src/menu/egg_select_screen.cpp @@ -0,0 +1,58 @@ +#include "menu.h" +#include "draw/draw.h" +#include "defs/defs.h" +#include "vpet/vpet.h" +#include "display/display.h" +#include "defs/sprite_data.h" +#include "buttons/buttons.h" +#include "vpet/lines/lines.h" +#include "defs/chara_data.h" + + +void menu_lineSwitcher(TFT_eSprite &composite, TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* uiSmallSprite) { + static uint8_t eggCounter = 0; + + uint8_t buttonsPressed = buttons_getPressedButtons(); + switch(buttonsPressed) { + case K1_PRESSED: + eggCounter = (eggCounter + 1) % eggNumber; + break; + + case K2_PRESSED: + menu_reloadEggs(eggCounter); + eggCounter = 0; + screenKey = EGG_HATCH_SCREEN; + return; + break; + + case K3_PRESSED: + screenKey = IDLE_SCREEN; + return; + break; + + default: + break; + } + + draw_drawBackground(composite, bg, 90, 90, 3); + tft_clearBuffer(sprite, TFT_TRANSPARENT); + draw_drawSpriteCentered(composite, sprite, &eggSelection[eggCounter].eggSprite, 0, 6); + tft_clearBuffer(sprite, TFT_TRANSPARENT); + draw_drawSprite(composite, sprite, 194, 96, uiSmallSprite, ARROW_ICON, 6); + + tft_drawBuffer(composite); +} + +void menu_reloadEggs(uint8_t selectedEgg) { + char fileName[strlen(eggSelection[selectedEgg].fileName) + 1]; + strcpy(fileName, eggSelection[selectedEgg].fileName); + + lines_freeEggList(); + + printf("[DEBUG] fileName=%s\n", fileName); + + lines_getSingleLine(fileName); + lines_getLineCareMistakes(fileName); + + charaData.hatching = true; +} \ No newline at end of file diff --git a/src/menu/food_select_screen.cpp b/src/menu/food_select_screen.cpp index 8e3b235..8fce651 100644 --- a/src/menu/food_select_screen.cpp +++ b/src/menu/food_select_screen.cpp @@ -37,6 +37,7 @@ void menu_foodScreen(TFT_eSprite &composite, TFT_eSprite &bg, TFT_eSprite &mainC if (charaData.hunger < 8) { charaData.weight++; charaData.hunger++; + charaData.hungerCareMistakeTimer = charaData.initialStatsReductionTime; screenKey = FEEDING_SCREEN; submenuKey = FOOD_ICON; } else { @@ -48,6 +49,7 @@ void menu_foodScreen(TFT_eSprite &composite, TFT_eSprite &bg, TFT_eSprite &mainC if (charaData.strength < 8) { charaData.strength++; charaData.weight += 2; + charaData.strengthCareMistakeTimer = charaData.initialStatsReductionTime; screenKey = FEEDING_SCREEN; submenuKey = PILL_ICON; } else { diff --git a/src/menu/idle_screen.cpp b/src/menu/idle_screen.cpp index fed8982..bf4a769 100644 --- a/src/menu/idle_screen.cpp +++ b/src/menu/idle_screen.cpp @@ -9,7 +9,16 @@ uint64_t lastUpdateTime = esp_timer_get_time(); void menu_drawIdleScreen(TFT_eSprite &composite, TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* spriteData, struct SpriteData* bigUiElements, struct SpriteData* smallUiElements) { - if (charaData.sleepy && !charaData.asleep) { + if (coldBoot) { + screenKey = TITLE_SCREEN; + return; + } else if (!charaData.hatched && !charaData.hatching) { + screenKey = EGG_EMPTY_SCREEN; + return; + } else if (!charaData.hatched && charaData.hatching) { + screenKey = EGG_HATCH_SCREEN; + return; + } else if (charaData.sleepy && !charaData.asleep) { screenKey = SLEEPY_SCREEN; return; } else if ((charaData.sleepy && charaData.asleep) || charaData.asleep) { @@ -20,12 +29,12 @@ void menu_drawIdleScreen(TFT_eSprite &composite, TFT_eSprite &bg, TFT_eSprite &s uint8_t pressedButtons = buttons_getPressedButtons(); switch (pressedButtons) { - case 8: + case K1_PRESSED: screenKey = MENU_SCREEN; menuKey = 0; break; - case 4: + case K2_PRESSED: screenKey = CLOCK_SCREEN; break; diff --git a/src/menu/menu.h b/src/menu/menu.h index 97d35e2..ef73c3e 100644 --- a/src/menu/menu.h +++ b/src/menu/menu.h @@ -40,5 +40,9 @@ void menu_drawHappyScreen( TFT_eSprite &composite, TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* spriteData, struct SpriteData* smallUiElements ); +void menu_lineSwitcher(TFT_eSprite &composite, TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* uiSmallSprite); +void menu_eggHatchScreen(TFT_eSprite &composite, TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* uiBigSprite, struct SpriteData* uiSmallSprite); +void menu_reloadEggs(uint8_t selectedEgg); +void menu_drawDeathScreen(TFT_eSprite &composite, TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* uiBigSprite, struct SpriteData* uiSmallSprite); #endif \ No newline at end of file diff --git a/src/menu/title_screen.cpp b/src/menu/title_screen.cpp index 6f23fc6..0dbebfd 100644 --- a/src/menu/title_screen.cpp +++ b/src/menu/title_screen.cpp @@ -6,10 +6,9 @@ void menu_drawTitle(TFT_eSprite &composite, TFT_eSprite &bg) { uint8_t pressedButtons = buttons_getPressedButtons(); - lastPressedButtonTime = esp_timer_get_time(); - if (pressedButtons == 8 || pressedButtons == 4) { screenKey = CLOCK_EDIT_SCREEN; + return; } draw_drawBackground(composite, bg, 90, 90, 3); diff --git a/src/vpet/lines/free_lines.cpp b/src/vpet/lines/free_lines.cpp new file mode 100644 index 0000000..4a230a6 --- /dev/null +++ b/src/vpet/lines/free_lines.cpp @@ -0,0 +1,29 @@ +#include "lines.h" +#include "defs/defs.h" +#include "defs/chara_data.h" + +void lines_freeEggList() { + for (int i = 0; i < eggNumber; i++) { + for (int j = 0; j < eggSelection[i].eggSprite.spriteNumber; j++) { + free(eggSelection[i].eggSprite.spriteData[j]); + } + + free(eggSelection[i].eggSprite.spriteData); + } + + free(eggSelection); + + eggSelection = NULL; + eggNumber = 0; +} + +void lines_freeCurrentEgg() { + for (int i = 0; i < currentEgg->eggSprite.spriteNumber; i++) { + free(currentEgg->eggSprite.spriteData[i]); + } + + free(currentEgg->eggSprite.spriteData); + free(currentEgg); + + currentEgg = NULL; +} diff --git a/src/vpet/lines/get_available_lines.cpp b/src/vpet/lines/get_available_lines.cpp index 3907026..c362667 100644 --- a/src/vpet/lines/get_available_lines.cpp +++ b/src/vpet/lines/get_available_lines.cpp @@ -1,12 +1,17 @@ #include "lines.h" #include "memory/memory.h" +#include "defs/defs.h" #include "SPIFFS.h" const char lineHeader[5] = "NPET"; const uint8_t headerSize = 4; -struct Egg_t* lines_getAvailableLines(uint8_t* count) { +void lines_getAvailableLines() { + if (eggSelection != NULL) { + return; + } + File root = SPIFFS.open("/lines"); File lineFile = root.openNextFile(); @@ -28,7 +33,6 @@ struct Egg_t* lines_getAvailableLines(uint8_t* count) { root.close(); - printf("[LINES] Found %i lines.\n", allocCount); allocCount = 0; root = SPIFFS.open("/lines"); @@ -73,34 +77,6 @@ struct Egg_t* lines_getAvailableLines(uint8_t* count) { root.close(); - *count = allocCount; - return availableLines; + eggNumber = allocCount; + eggSelection = availableLines; } - -void lines_testLines() { - uint8_t countedLines; - struct Egg_t* availableLines = lines_getAvailableLines(&countedLines); - - char fullPath[8 + strlen(availableLines[0].fileName)]; - snprintf(fullPath, 20, "/lines/%s", availableLines[0].fileName); - - lines_freeEggList(availableLines, countedLines); - - printf("[DEBUG] fullPath=%s\n", fullPath); - - availableLines = (Egg_t*) malloc(sizeof(Egg_t)); - - struct Line_t* singleLine = lines_getSingleLine(fullPath, availableLines); - - lines_freeEggList(availableLines, 1); - - struct LineCare_t* lineCareData = lines_getLineCareMistakes(availableLines->fileName); - - for (int i = 0; i < lineCareData->numCareMistakesData; i++) { - printf( - "[DEBUG] Chara %d changes into chara %d\n", - lineCareData->careMistakeData[i].currentChara, - lineCareData->careMistakeData[i].nextChara - ); - } -} \ No newline at end of file diff --git a/src/vpet/lines/get_care_mistakes.cpp b/src/vpet/lines/get_care_mistakes.cpp index 940c40b..92e4dd2 100644 --- a/src/vpet/lines/get_care_mistakes.cpp +++ b/src/vpet/lines/get_care_mistakes.cpp @@ -1,9 +1,10 @@ #include "lines.h" #include "defs/file_chara.h" +#include "defs/defs.h" #include "SPIFFS.h" -struct LineCare_t* lines_getLineCareMistakes(const char* fileName) { +void lines_getLineCareMistakes(const char* fileName) { char careMistakesPath[strlen(fileName) + 8]; snprintf(careMistakesPath, strlen(fileName) + 8, "/care/%s", fileName); @@ -26,5 +27,5 @@ struct LineCare_t* lines_getLineCareMistakes(const char* fileName) { bytesRead += careMistakesFile.read((uint8_t*) &careMistakesData->careMistakeData[i], sizeof(CareMistakes_t)); } - return careMistakesData; + currentLineCareInstr[currentCharacter] = careMistakesData; } \ No newline at end of file diff --git a/src/vpet/lines/get_single_line.cpp b/src/vpet/lines/get_single_line.cpp index b828658..0943402 100644 --- a/src/vpet/lines/get_single_line.cpp +++ b/src/vpet/lines/get_single_line.cpp @@ -1,10 +1,14 @@ #include "lines.h" #include "memory/memory.h" +#include "defs/defs.h" #include -struct Line_t* lines_getSingleLine(const char* fileName, Egg_t* selectedEgg) { - File lineFile = SPIFFS.open(fileName); +void lines_getSingleLine(const char* fileName) { + char fullPath[8 + strlen(fileName)]; + snprintf(fullPath, 20, "/lines/%s", fileName); + + File lineFile = SPIFFS.open(fullPath); struct Line_t* selectedLine = (struct Line_t*) malloc(sizeof(struct Line_t)); if (selectedLine == NULL) { @@ -18,6 +22,7 @@ struct Line_t* lines_getSingleLine(const char* fileName, Egg_t* selectedEgg) { uint8_t bytesRead = lineFile.read(&selectedLine->id, 1); bytesRead += lineFile.readBytes(selectedLine->name, 16); + Egg_t* selectedEgg = (Egg_t*) malloc(sizeof(Egg_t)); lines_getSingleEggSprites(lineFile, selectedEgg); bytesRead += lineFile.read(buffer, 2); @@ -33,7 +38,8 @@ struct Line_t* lines_getSingleLine(const char* fileName, Egg_t* selectedEgg) { bytesRead += lineFile.read((uint8_t*) &selectedLine->characters[i], sizeof(LineChara_t)); } - return selectedLine; + currentLine[currentCharacter] = selectedLine; + currentEgg = selectedEgg; } void lines_getSingleEggSprites(File &lineFile, Egg_t* selectedEgg) { @@ -73,14 +79,3 @@ void lines_getSingleEggSprites(File &lineFile, Egg_t* selectedEgg) { // Son las 22:35, que estoy haciendo? // Pues claro -void lines_freeEggList(Egg_t* eggList, uint8_t eggNumber) { - for (int i = 0; i < eggNumber; i++) { - for (int j = 0; j < eggList[i].eggSprite.spriteNumber; j++) { - free(eggList[i].eggSprite.spriteData[j]); - } - - free(eggList[i].eggSprite.spriteData); - } - - free(eggList); -} \ No newline at end of file diff --git a/src/vpet/lines/init_lines.cpp b/src/vpet/lines/init_lines.cpp new file mode 100644 index 0000000..6abe684 --- /dev/null +++ b/src/vpet/lines/init_lines.cpp @@ -0,0 +1,12 @@ +#include "lines.h" +#include "defs/defs.h" +#include "defs/file_chara.h" + +Egg_t* currentEgg = NULL; +LineCare_t** currentLineCareInstr = NULL; +Line_t** currentLine = NULL; + +void lines_initLineStorage() { + currentLineCareInstr = (LineCare_t**) malloc(sizeof(LineCare_t*) * CHARA_COUNT_IN_DEVICE); + currentLine = (Line_t**) malloc(sizeof(Line_t*) * CHARA_COUNT_IN_DEVICE); +} \ No newline at end of file diff --git a/src/vpet/lines/lines.h b/src/vpet/lines/lines.h index 23a7dd9..e754e44 100644 --- a/src/vpet/lines/lines.h +++ b/src/vpet/lines/lines.h @@ -4,11 +4,13 @@ #include "defs/file_chara.h" #include -struct Egg_t* lines_getAvailableLines(uint8_t* count); -struct Line_t* lines_getSingleLine(const char* fileName, Egg_t* eggList); +void lines_getAvailableLines(); +void lines_getSingleLine(const char* fileName); +void lines_getLineCareMistakes(const char* fileName); +void lines_freeEggList(); +void lines_freeCurrentEgg(); +void lines_initLineStorage(); void lines_getSingleEggSprites(fs::File &lineFile, Egg_t* eggList); -void lines_freeEggList(Egg_t* eggList, uint8_t eggNumber); -struct LineCare_t* lines_getLineCareMistakes(const char* fileName); -void lines_testLines(); +void lines_onHatchComplete(); #endif \ No newline at end of file diff --git a/src/vpet/lines/on_hatch_finished.cpp b/src/vpet/lines/on_hatch_finished.cpp new file mode 100644 index 0000000..3b6cca9 --- /dev/null +++ b/src/vpet/lines/on_hatch_finished.cpp @@ -0,0 +1,37 @@ +#include "lines.h" +#include "defs/defs.h" +#include "defs/chara_data.h" +#include "storage/storage.h" +#include "vpet/vpet.h" + +void lines_onHatchComplete() { + // Cuando se nace, lo que se va a hacer es poner el sprite 0, es decir, + // La primera entrada de la linea es el sprite que sale. + lines_freeCurrentEgg(); + + char spriteFileName[30]; + snprintf(spriteFileName, 30, "/chara/%02x.bin", currentLine[currentCharacter]->characters[0].id); + printf("[DEBUG] spriteFileName=%s\n", spriteFileName); + + storage_readFile(spriteFileName, &mainCharacterSprites); + + charaData.hp = currentLine[currentCharacter]->characters[0].hp; + charaData.bp = currentLine[currentCharacter]->characters[0].bp; + charaData.ap = currentLine[currentCharacter]->characters[0].ap; + + charaData.stage = currentLine[currentCharacter]->characters[0].stage; + charaData.attribute = currentLine[currentCharacter]->characters[0].attribute; + + charaData.sleepTime = currentLine[currentCharacter]->characters[0].sleepTime; + charaData.wakeupTime = currentLine[currentCharacter]->characters[0].wakeTime; + charaData.evoLeftTimer = currentLine[currentCharacter]->characters[0].changeTime; + charaData.evoTime = currentLine[currentCharacter]->characters[0].changeTime; + + charaData.hungerCareMistakeTimer = CARE_MISTAKE_COUNTER_MAX; + charaData.strengthCareMistakeTimer = CARE_MISTAKE_COUNTER_MAX; + + charaData.initialStatsReductionTime = currentLine[currentCharacter]->characters[0].depleteTime; + charaData.minWeight = currentLine[currentCharacter]->characters[0].minWeight; + + charaData.hatched = true; +} \ No newline at end of file diff --git a/src/vpet/vpet.cpp b/src/vpet/vpet.cpp index fd86209..35a757d 100644 --- a/src/vpet/vpet.cpp +++ b/src/vpet/vpet.cpp @@ -152,7 +152,11 @@ void vpet_evalTimers() { screenKey = TIMER_FINISHED_SCREEN; interruptKey = POOPING_SCREEN; charaData.poopNumber++; - charaData.hungerCareMistakeTimer = 60; + if (charaData.hunger > 0) { + charaData.hungerCareMistakeTimer = charaData.initialStatsReductionTime; + } else { + charaData.hungerCareMistakeTimer = CARE_MISTAKE_COUNTER_MAX; + } } if (!charaData.hungerCareMistakeObtained) { @@ -172,7 +176,11 @@ void vpet_evalTimers() { if (charaData.strength > 0) { charaData.strength--; - charaData.strengthCareMistakeTimer = 60; + if (charaData.strength > 0) { + charaData.strengthCareMistakeTimer = charaData.initialStatsReductionTime; + } else { + charaData.strengthCareMistakeTimer = CARE_MISTAKE_COUNTER_MAX; + } } if (!charaData.strengthCareMistakeObtained) { @@ -198,7 +206,7 @@ void IRAM_ATTR onActionTimerDelta() { } void vpet_runVpetTasks() { - if (runVpetTasks) { + if (runVpetTasks && charaData.hatched) { vpet_computeCallLight(); if (!vpet_evalSleep()) { vpet_evalTimers(); @@ -212,5 +220,14 @@ void vpet_runVpetTasks() { printf("[MAIN]: Is sleep care mistake tripped? %d\n", charaData.sleepCareMistakeObtained); runVpetTasks = false; - } + } else if (runVpetTasks && !charaData.hatched && charaData.hatching) { + charaData.hatchTimer++; + printf("[DEBUG] hatchTimer=%i out of hatchTimer=%i\n", charaData.hatchTimer, currentLine[currentCharacter]->hatchTime); + if (charaData.hatchTimer > currentLine[currentCharacter]->hatchTime) { + interruptKey = EGG_HATCH_SCREEN; + screenKey = TIMER_FINISHED_SCREEN; + } + + runVpetTasks = false; + } } \ No newline at end of file