From 570d7f8bc46062c7ab136da73af535808459cb54 Mon Sep 17 00:00:00 2001 From: Nacho Date: Wed, 27 May 2026 14:30:33 +0200 Subject: [PATCH] Let's get this up to date, i'll update the readme later on --- .gitignore | 1 + User_Setup.h | 378 +------------------- platformio.ini | 40 ++- src/animations/sprite_animation.cpp | 25 +- src/buttons/buttons.cpp | 8 +- src/buttons/buttons.h | 2 + src/defs/chara_data.h | 3 +- src/defs/defs.h | 49 ++- src/defs/screen_defs.h | 3 +- src/display/display.cpp | 76 ++-- src/draw/draw.h | 14 +- src/draw/draw_attacks.cpp | 14 +- src/draw/draw_background.cpp | 87 +---- src/draw/draw_sprites.cpp | 102 ++---- src/energy/light_sleep.cpp | 73 +++- src/main.cpp | 45 +-- src/menu/angry_screen.cpp | 6 +- src/menu/care_mistake_screen.cpp | 2 +- src/menu/change_animation_screen.cpp | 49 ++- src/menu/change_chara_screen.cpp | 6 +- src/menu/clock_screen.cpp | 13 +- src/menu/death_screen.cpp | 4 +- src/menu/egg_hatch_screen.cpp | 6 +- src/menu/egg_select_screen.cpp | 6 +- src/menu/feeding_screen.cpp | 4 +- src/menu/food_select_screen.cpp | 154 ++++---- src/menu/freeze_screen.cpp | 34 ++ src/menu/happy_screen.cpp | 12 +- src/menu/idle_screen.cpp | 2 +- src/menu/main_screen.cpp | 6 +- src/menu/menu.h | 12 +- src/menu/menu_screen.cpp | 34 +- src/menu/poop_clean.cpp | 14 +- src/menu/poop_overlay.cpp | 2 +- src/menu/poop_screen.cpp | 8 +- src/menu/sleeping_screen.cpp | 4 +- src/menu/status_screen.cpp | 5 +- src/menu/title_screen.cpp | 4 +- src/menu/training/training_screen1.cpp | 4 +- src/menu/training/training_screens.h | 5 + src/menu/training_screen2.cpp | 96 +++++ src/menu/ui_overlay.cpp | 33 +- src/storage/storage.cpp | 315 +++++++++++++--- src/storage/storage.h | 5 +- src/vpet/evolution/evolution.cpp | 2 + src/vpet/lines/get_available_lines.cpp | 7 +- src/vpet/lines/get_care_mistakes.cpp | 7 +- src/vpet/lines/get_single_line.cpp | 7 +- src/vpet/lines/init_lines.cpp | 6 +- src/vpet/training/training.h | 1 + src/vpet/training/training_resultScreen.cpp | 13 +- src/vpet/vpet/vpet.cpp | 16 +- test/README | 11 - 53 files changed, 938 insertions(+), 897 deletions(-) create mode 100644 src/menu/freeze_screen.cpp create mode 100644 src/menu/training_screen2.cpp delete mode 100644 test/README diff --git a/.gitignore b/.gitignore index 049d9a5..8923cf0 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ *.line *.egg *.cm +*.png __pycache__/ venv/ sprites/ diff --git a/User_Setup.h b/User_Setup.h index dd3145d..14b450d 100644 --- a/User_Setup.h +++ b/User_Setup.h @@ -1,311 +1,26 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc. -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is edited correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! -// Note that some sketches are designed for a particular TFT pixel width/height - -// User defined information reported by "Read_User_Setup" test & diagnostics example #define USER_SETUP_INFO "User_Setup" +#define USE_HSPI_PORT -// Define to disable all #warnings in library (can be put in User_Setup_Select.h) -//#define DISABLE_ALL_LIBRARY_WARNINGS - -// ################################################################################## -// -// Section 1. Call up the right driver file and any options for it -// -// ################################################################################## - -// Define STM32 to invoke optimised processor support (only for STM32) -//#define STM32 - -// Defining the STM32 board allows the library to optimise the performance -// for UNO compatible "MCUfriend" style shields -//#define NUCLEO_64_TFT -//#define NUCLEO_144_TFT - -// STM32 8-bit parallel only: -// If STN32 Port A or B pins 0-7 are used for 8-bit parallel data bus bits 0-7 -// then this will improve rendering performance by a factor of ~8x -//#define STM_PORTA_DATA_BUS -//#define STM_PORTB_DATA_BUS - -// Tell the library to use parallel mode (otherwise SPI is assumed) -//#define TFT_PARALLEL_8_BIT -//#defined TFT_PARALLEL_16_BIT // **** 16-bit parallel ONLY for RP2040 processor **** - -// Display type - only define if RPi display -//#define RPI_DISPLAY_TYPE // 20MHz maximum SPI - -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER // Generic driver for common displays -//#define ILI9341_2_DRIVER // Alternative ILI9341 driver, see https://github.com/Bodmer/TFT_eSPI/issues/1172 -//#define ST7735_DRIVER // Define additional parameters below for this display -//#define ILI9163_DRIVER // Define additional parameters below for this display -//#define S6D02A1_DRIVER -//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI -//#define HX8357D_DRIVER -//#define ILI9481_DRIVER -//#define ILI9486_DRIVER -//#define ILI9488_DRIVER // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high) #define ST7789_DRIVER // Full configuration option, define additional parameters below for this display -//#define ST7789_2_DRIVER // Minimal configuration option, define additional parameters below for this display -//#define R61581_DRIVER -//#define RM68140_DRIVER -//#define ST7796_DRIVER -//#define SSD1351_DRIVER -//#define SSD1963_480_DRIVER -//#define SSD1963_800_DRIVER -//#define SSD1963_800ALT_DRIVER -//#define ILI9225_DRIVER -//#define GC9A01_DRIVER - -// Some displays support SPI reads via the MISO pin, other displays have a single -// bi-directional SDA pin and the library will try to read this via the MOSI line. -// To use the SDA line for reading data from the TFT uncomment the following line: - -// #define TFT_SDA_READ // This option is for ESP32 ONLY, tested with ST7789 and GC9A01 display only - -// For ST7735, ST7789 and ILI9341 ONLY, define the colour order IF the blue and red are swapped on your display -// Try ONE option at a time to find the correct colour order for your display - -//#define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue - #define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red - -// For M5Stack ESP32 module with integrated ILI9341 display ONLY, remove // in line below - -// #define M5STACK - -// For ST7789, ST7735, ILI9163 and GC9A01 ONLY, define the pixel width and height in portrait orientation -// #define TFT_WIDTH 80 -//#define TFT_WIDTH 128 -// #define TFT_WIDTH 172 // ST7789 172 x 320 -// #define TFT_WIDTH 170 // ST7789 170 x 320 +#define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue #define TFT_WIDTH 240 // ST7789 240 x 240 and 240 x 320 -///#define TFT_HEIGHT 160 -// #define TFT_HEIGHT 128 #define TFT_HEIGHT 240 // ST7789 240 x 240 -// #define TFT_HEIGHT 320 // ST7789 240 x 320 -// #define TFT_HEIGHT 240 // GC9A01 240 x 240 - -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or stray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: - -// #define ST7735_INITB -// #define ST7735_GREENTAB -// #define ST7735_GREENTAB2 -// #define ST7735_GREENTAB3 -// #define ST7735_GREENTAB128 // For 128 x 128 display -// #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset) -// #define ST7735_ROBOTLCD // For some RobotLCD Arduino shields (128x160, BGR, https://docs.arduino.cc/retired/getting-started-guides/TFT) -//#define ST7735_REDTAB -// #define ST7735_BLACKTAB -// #define ST7735_REDTAB160x80 // For 160 x 80 display with 24 pixel offset - -// If colours are inverted (white shows as black) then uncomment one of the next -// 2 lines try both options, one of the options should correct the inversion. - -// #define TFT_INVERSION_ON -// #define TFT_INVERSION_OFF - - -// ################################################################################## -// -// Section 2. Define the pins that are used to interface with the display here -// -// ################################################################################## - -// If a backlight control signal is available then define the TFT_BL pin in Section 2 -// below. The backlight will be turned ON when tft.begin() is called, but the library -// needs to know if the LEDs are ON with the pin HIGH or LOW. If the LEDs are to be -// driven with a PWM signal or turned OFF/ON then this must be handled by the user -// sketch. e.g. with digitalWrite(TFT_BL, LOW); - -#define TFT_BL 25 // LED back-light control pin +#define TFT_BL 1 // LED back-light control pin #define TFT_BACKLIGHT_ON HIGH // Level to turn ON back-light (HIGH or LOW) +#define TFT_MOSI 1 +#define TFT_MISO -1 +#define TFT_SCLK 2 +#define TFT_DC 4 +#define TFT_RST 3 +#define TOUCH_CS -1 -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for ESP8266 NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (RS/AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// The DC (Data Command) pin may be labelled AO or RS (Register Select) -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. +#define TFT_SPI_PORT SPI2_HOST +#define SPI_FREQUENCY 27000000 -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### - -// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation -//#define TFT_MISO PIN_D6 // Automatically assigned with ESP8266 if not defined -#define TFT_MOSI 23 // Automatically assigned with ESP8266 if not defined -#define TFT_SCLK 18 // Automatically assigned with ESP8266 if not defined - -#define TFT_CS 15 // Chip select control pin D8 -#define TFT_DC 17 // Data Command control pin -#define TFT_RST 19 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - - -//#define TFT_BL PIN_D1 // LED back-light (only for ST7789 with backlight control pin) - -#define TOUCH_CS -1 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only - - -// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### - -// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact -// but saves pins for other functions. It is best not to connect MISO as some displays -// do not tristate that line when chip select is high! -// Note: Only one SPI device can share the FLASH SPI lines, so a SPI touch controller -// cannot be connected as well to the same SPI signals. -// On NodeMCU 1.0 SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode -// On NodeMCU V3 S0 =MISO, S1 =MOSI, S2 =SCLK -// In ESP8266 overlap mode the following must be defined - -//#define TFT_SPI_OVERLAP - -// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 -//#define TFT_CS PIN_D3 -//#define TFT_DC PIN_D5 // Data Command control pin -//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### - -// For ESP32 Dev board (only tested with ILI9341 display) -// The hardware SPI can be mapped to any pins - -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 15 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to RST pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -// For ESP32 Dev board (only tested with GC9A01 display) -// The hardware SPI can be mapped to any pins - -//#define TFT_MOSI 15 // In some display driver board, it might be written as "SDA" and so on. -//#define TFT_SCLK 14 -//#define TFT_CS 5 // Chip select control pin -//#define TFT_DC 27 // Data Command control pin -//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 22 // LED back-light - -//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only - -// For the M5Stack module use these #define lines -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 14 // Chip select control pin -//#define TFT_DC 27 // Data Command control pin -//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 32 // LED back-light (required for M5Stack) - -// ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ###### - -// The library supports 8-bit parallel TFTs with the ESP32, the pin -// selection below is compatible with ESP32 boards in UNO format. -// Wemos D32 boards need to be modified, see diagram in Tools folder. -// Only ILI9481 and ILI9341 based displays have been tested! - -// Parallel bus is only supported for the STM32 and ESP32 -// Example below is for ESP32 Parallel interface with UNO displays - -// Tell the library to use 8-bit parallel mode (otherwise SPI is assumed) -//#define TFT_PARALLEL_8_BIT - -// The ESP32 and TFT the pins used for testing are: -//#define TFT_CS 33 // Chip select control pin (library pulls permanently low -//#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31 -//#define TFT_RST 32 // Reset pin, toggles on startup - -//#define TFT_WR 4 // Write strobe control pin - must use a pin in the range 0-31 -//#define TFT_RD 2 // Read strobe control pin - -//#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus -//#define TFT_D1 13 // so a single register write sets/clears all bits. -//#define TFT_D2 26 // Pins can be randomly assigned, this does not affect -//#define TFT_D3 25 // TFT screen update performance. -//#define TFT_D4 17 -//#define TFT_D5 16 -//#define TFT_D6 27 -//#define TFT_D7 14 - -// ###### EDIT THE PINs BELOW TO SUIT YOUR STM32 SPI TFT SETUP ###### - -// The TFT can be connected to SPI port 1 or 2 -//#define TFT_SPI_PORT 1 // SPI port 1 maximum clock rate is 55MHz -//#define TFT_MOSI PA7 -//#define TFT_MISO PA6 -//#define TFT_SCLK PA5 - -//#define TFT_SPI_PORT 2 // SPI port 2 maximum clock rate is 27MHz -//#define TFT_MOSI PB15 -//#define TFT_MISO PB14 -//#define TFT_SCLK PB13 - -// Can use Ardiuno pin references, arbitrary allocation, TFT_eSPI controls chip select -//#define TFT_CS D5 // Chip select control pin to TFT CS -//#define TFT_DC D6 // Data Command control pin to TFT DC (may be labelled RS = Register Select) -//#define TFT_RST D7 // Reset pin to TFT RST (or RESET) -// OR alternatively, we can use STM32 port reference names PXnn -//#define TFT_CS PE11 // Nucleo-F767ZI equivalent of D5 -//#define TFT_DC PE9 // Nucleo-F767ZI equivalent of D6 -//#define TFT_RST PF13 // Nucleo-F767ZI equivalent of D7 - -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to processor reset - // Use an Arduino pin for initial testing as connecting to processor reset - // may not work (pulse too short at power up?) - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not -// normally necessary. If all fonts are loaded the extra FLASH space required is -// about 17Kbytes. To save FLASH space only enable the fonts you need! +#define TFT_USE_DMA false #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -316,77 +31,10 @@ //#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded -// this will save ~20kbytes of FLASH #define SMOOTH_FONT +#define SPI_FREQUENCY 27000000 -// ################################################################################## -// -// Section 4. Other options -// -// ################################################################################## - -// For RP2040 processor and SPI displays, uncomment the following line to use the PIO interface. -//#define RP2040_PIO_SPI // Leave commented out to use standard RP2040 SPI port interface - -// For RP2040 processor and 8 or 16-bit parallel displays: -// The parallel interface write cycle period is derived from a division of the CPU clock -// speed so scales with the processor clock. This means that the divider ratio may need -// to be increased when overclocking. It may also need to be adjusted dependant on the -// display controller type (ILI94341, HX8357C etc.). If RP2040_PIO_CLK_DIV is not defined -// the library will set default values which may not suit your display. -// The display controller data sheet will specify the minimum write cycle period. The -// controllers often work reliably for shorter periods, however if the period is too short -// the display may not initialise or graphics will become corrupted. -// PIO write cycle frequency = (CPU clock/(4 * RP2040_PIO_CLK_DIV)) -//#define RP2040_PIO_CLK_DIV 1 // 32ns write cycle at 125MHz CPU clock -//#define RP2040_PIO_CLK_DIV 2 // 64ns write cycle at 125MHz CPU clock -//#define RP2040_PIO_CLK_DIV 3 // 96ns write cycle at 125MHz CPU clock - -// For the RP2040 processor define the SPI port channel used (default 0 if undefined) -//#define TFT_SPI_PORT 1 // Set to 0 if SPI0 pins are used, or 1 if spi1 pins used - -// For the STM32 processor define the SPI port channel used (default 1 if undefined) -//#define TFT_SPI_PORT 2 // Set to 1 for SPI port 1, or 2 for SPI port 2 - -// Define the SPI clock frequency, this affects the graphics rendering speed. Too -// fast and the TFT driver will not keep up and display corruption appears. -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display 27 MHz works OK. - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 -// #define SPI_FREQUENCY 20000000 -// #define SPI_FREQUENCY 27000000 -#define SPI_FREQUENCY 40000000 -// #define SPI_FREQUENCY 55000000 // STM32 SPI1 only (SPI2 maximum is 27MHz) -// #define SPI_FREQUENCY 80000000 - -// Optional reduced SPI frequency for reading TFT #define SPI_READ_FREQUENCY 20000000 -// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: #define SPI_TOUCH_FREQUENCY 2500000 - -// The ESP32 has 2 free SPI ports i.e. VSPI and HSPI, the VSPI is the default. -// If the VSPI port is in use and pins are not accessible (e.g. TTGO T-Beam) -// then uncomment the following line: -//#define USE_HSPI_PORT - -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! - -// Transaction support is needed to work with SD library but not needed with TFT_SdFat -// Transaction support is required if other SPI devices are connected. - -// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) -// so changing it here has no effect - -// #define SUPPORT_TRANSACTIONS - - -#define USE_DMA_TO_TFT diff --git a/platformio.ini b/platformio.ini index 99c6537..478e917 100644 --- a/platformio.ini +++ b/platformio.ini @@ -8,12 +8,40 @@ ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html -[env:esp32dev] +;[env:alt] +;platform = espressif32 +;board = 4d_systems_esp32s3_gen4_r8n16 +;framework = arduino +;lib_deps = TFT_eSPI, fbiego/ESP32Time@^2.0.6, electroniccats/MPU6050@^1.4.3 +;monitor_filters = esp32_exception_decoder +;monitor_speed = 115200 +; +;build_flags = +; -DBOARD_HAS_PSRAM +; -mfix-esp32-psram-cache-issue +; ; These ensure the N16R8 uses the fast Octal (OPI) mode +; -DARDUINO_USB_CDC_ON_BOOT=1 +; -DDEV_UNIT +; -DDEBUG + +[env:alt] platform = espressif32 -board = esp32dev +board = esp32-s3-devkitc-1 framework = arduino -monitor_speed = 115200 -monitor_port = /dev/ttyUSB0 -monitor_filters = esp32_exception_decoder + +; 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 + -DDEV_UNIT + +; Ensure partition table fits 4MB +board_build.partitions = default.csv lib_deps = TFT_eSPI, fbiego/ESP32Time@^2.0.6, electroniccats/MPU6050@^1.4.3 -build_flags = -Wl,-Map,output.map diff --git a/src/animations/sprite_animation.cpp b/src/animations/sprite_animation.cpp index a510147..3bcaf2c 100644 --- a/src/animations/sprite_animation.cpp +++ b/src/animations/sprite_animation.cpp @@ -11,11 +11,10 @@ int currentAnimationFrame = 0; void animate_performAnimation(TFT_eSprite &spr, struct SpriteData* spriteData, uint8_t offsetX) { draw_drawSprite( spr, - animationPositions[currentAnimationFrame] - offsetX, - spriteHeightOnScreen, - spriteData, - animationFrames[currentAnimationFrame], - 6, + animationPositions[currentAnimationFrame] - offsetX, + spriteHeightOnScreen, + spriteData, + animationFrames[currentAnimationFrame], animationFlipSprites[currentAnimationFrame] ); @@ -26,14 +25,12 @@ void animate_performAttentionAnimation(TFT_eSprite &spr, struct SpriteData* spri currentAnimationFrame = (currentAnimationFrame + 1) % numFramesAngry; draw_drawSprite( spr, - spriteHeightOnScreen, - spriteHeightOnScreen, - spriteData, - angryAnimationFrames[currentAnimationFrame], - 6, + spriteHeightOnScreen, + spriteHeightOnScreen, + spriteData, + angryAnimationFrames[currentAnimationFrame], animationFlipSprites[currentAnimationFrame] ); - } void animate_performEatingAnimation(TFT_eSprite &spr, struct SpriteData* spriteData) { @@ -44,7 +41,6 @@ void animate_performEatingAnimation(TFT_eSprite &spr, struct SpriteData* spriteD spriteHeightOnScreen, spriteData, eatingAnimationFrames[currentAnimationFrame], - 6, false ); } @@ -57,7 +53,6 @@ void animate_performRefuseAnimation(TFT_eSprite &spr, struct SpriteData* spriteD spriteHeightOnScreen, spriteData, refuseAnimationFrames[currentAnimationFrame], - 6, refuseAnimationFlips[currentAnimationFrame] ); } @@ -70,7 +65,6 @@ void animate_performSleepyAnimation(TFT_eSprite &spr, struct SpriteData* spriteD spriteHeightOnScreen, spriteData, sleepyAnimationFrames[currentAnimationFrame], - 6, false ); } @@ -83,7 +77,6 @@ void animate_performHappyAnimation(TFT_eSprite &spr, struct SpriteData* spriteDa spriteHeightOnScreen, spriteData, happyAnimationFrames[currentAnimationFrame], - 6, false ); } @@ -97,7 +90,6 @@ void animate_performAngryAnimation(TFT_eSprite &spr, struct SpriteData* spriteDa spriteHeightOnScreen, spriteData, angryAnimationFrames[currentAnimationFrame], - 6, false ); } @@ -110,7 +102,6 @@ void animate_performHatchingAnimation(TFT_eSprite &spr, struct SpriteData* sprit spriteHeightOnScreen, spriteData, 0, - 6, false ); } \ No newline at end of file diff --git a/src/buttons/buttons.cpp b/src/buttons/buttons.cpp index c7b142d..8bf32d8 100644 --- a/src/buttons/buttons.cpp +++ b/src/buttons/buttons.cpp @@ -33,10 +33,10 @@ uint8_t buttons_getPressedButtons() { bool k4_current = digitalRead(K4_PIN); uint8_t retV = ( - (k1_prev == HIGH && k1_current == LOW) << 3 | - (k2_prev == HIGH && k2_current == LOW) << 2 | - (k3_prev == HIGH && k3_current == LOW) << 1 | - (k4_prev == HIGH && k4_current == LOW) + (k1_prev == LOW && k1_current == HIGH) << 3 | + (k2_prev == LOW && k2_current == HIGH) << 2 | + (k3_prev == LOW && k3_current == HIGH) << 1 | + (k4_prev == LOW && k4_current == HIGH) ); if (retV != 0) { diff --git a/src/buttons/buttons.h b/src/buttons/buttons.h index d1882d7..9360fb9 100644 --- a/src/buttons/buttons.h +++ b/src/buttons/buttons.h @@ -1,6 +1,8 @@ #ifndef BUTTONS_H #define BUTTONS_H +#include + uint8_t buttons_getPressedButtons(); void buttons_checkInactivity(); diff --git a/src/defs/chara_data.h b/src/defs/chara_data.h index 06ab7e4..b07f90d 100644 --- a/src/defs/chara_data.h +++ b/src/defs/chara_data.h @@ -46,7 +46,8 @@ struct CharacterData { bool asleep = false; bool injured = false; bool dead = false; - bool traited = true; + bool traited = false; + bool frozen = false; // Usado para recalcular cuantos dias van a tardar en recuperarse, max 5 pls uint8_t dynamicSleepDists; diff --git a/src/defs/defs.h b/src/defs/defs.h index 4fee5a3..ce9e527 100644 --- a/src/defs/defs.h +++ b/src/defs/defs.h @@ -11,24 +11,38 @@ #define VERSION "Alpha v0.1" // SCREEN PINOUT -#define SCL_PIN 34 -#define SDA_PIN 35 -#define RST_PIN 32 -#define BL_PIN 25 // BUTTONS PINOUT -#define K1_PIN 35 -#define K2_PIN 13 -#define K3_PIN 33 -#define K4_PIN 14 +#ifdef DEV_UNIT + +#define K1_PIN 1 +#define K2_PIN 2 +#define K3_PIN 3 +#define K4_PIN 4 +#define BUTTON_MODE INPUT_PULLDOWN + +#define BL_PIN 10 + +#endif + +#ifdef ANDREW_UNIT + +#define K1_PIN 39 +#define K2_PIN 8 +#define K3_PIN 9 +#define K4_PIN 38 +#define BUTTON_MODE INPUT_PULLUP + +#define BL_PIN 42 + +#endif // SPEAKER PINOUT -#define SPK_PIN 21 +#define SPK_PIN 7 // MPU6050 PINOUT -#define MPU_SCL_PIN 4 -#define MPU_SDA_PIN 16 -#define MPU_INT_PIN 12 +#define MPU_SCL_PIN 9 +#define MPU_SDA_PIN 8 // SPECIAL SCREEN THAT OPENS WHEN TIMERS ARE DONE // RECEIVES AN EXTRA PARAMETER (INTERRUPTKEY) @@ -59,6 +73,7 @@ #define SLEEP_SCREEN_MENU 6 #define CHANGE_SCREEN_MENU 7 #define SETTINGS_SCREEN_MENU 8 +#define FREEZE_SCREEN_MENU 9 // SCREENS THAT OPEN AFTER CLICKING ON A MENU ENTRY #define STATUS_SCREEN 10 @@ -80,9 +95,11 @@ #define MEDICAL_SCREEN_ICON 5 #define SLEEP_SCREEN_ICON 6 #define SETTINGS_SCREEN_ICON 8 -#define CARE_MISTAKE_CALL_LIGHT 9 +#define FRIDGE_DOOR 9 #define BED_SPRITE 10 #define EMPTY_EGG 11 +#define CARE_MISTAKE_CALL_LIGHT 12 + // SCREENS #define OFF_SCREEN -1 @@ -98,6 +115,7 @@ #define FEEDING_SCREEN 20 #define REFUSING_SCREEN 21 #define SLEEPY_SCREEN 22 +#define FROZEN_SCREEN 28 #define CARE_MISTAKE_SCREEN 23 #define POOPING_SCREEN 24 #define HAPPY_SCREEN 25 @@ -163,7 +181,6 @@ extern uint64_t lastPressedButtonTime; extern uint64_t lastUpdateTime; extern uint64_t lastBeepTime; -extern struct CharacterData* charaData; extern struct tm timeInfo; extern uint32_t dayUnixTime; @@ -179,16 +196,18 @@ extern uint8_t beepCounter; extern uint16_t stepCounter; -extern bool coldBoot; +extern bool timeSet; extern uint8_t eggNumber; extern Egg_t* eggSelection; extern uint8_t currentCharacter; +// Rescatar extern Egg_t* currentEgg; extern LineCare_t** currentLineCareInstr; extern Line_t** currentLine; +extern struct CharacterData* charaData; extern struct SpriteData mainCharacterSprites; diff --git a/src/defs/screen_defs.h b/src/defs/screen_defs.h index 82e8a02..5e12740 100644 --- a/src/defs/screen_defs.h +++ b/src/defs/screen_defs.h @@ -4,8 +4,7 @@ #include extern TFT_eSPI tft; -extern TFT_eSprite composite1; -extern TFT_eSprite composite2; +extern TFT_eSprite composite; // ALTAMENTE TEMPORAL extern int xPos; diff --git a/src/display/display.cpp b/src/display/display.cpp index 0939f89..b01f651 100644 --- a/src/display/display.cpp +++ b/src/display/display.cpp @@ -10,75 +10,63 @@ static const int BUF_H = 120; void tft_initDisplay(TFT_eSPI &tft, uint16_t color) { - tft.begin(); - tft.initDMA(); + #ifdef ANDREW_UNIT + pinMode(BL_PIN, OUTPUT); + digitalWrite(BL_PIN, HIGH); + #endif + + tft.init(); tft.setRotation(0); - tft.fillScreen(TFT_RED); + tft.fillScreen(color); } void tft_initScreenBuffer(uint16_t color) { - bool status = composite1.createSprite(240, 120); - composite1.fillSprite(TFT_BLUE); - composite1.setTextColor(TFT_BLACK); - composite1.setTextSize(4); - composite1.pushSprite(0, 0); + composite.setAttribute(PSRAM_ENABLE, true); - status = composite2.createSprite(240, 120); - composite2.fillSprite(TFT_BLUE); - composite2.setTextColor(TFT_BLACK); - composite2.setTextSize(4); - composite2.pushSprite(0, 120); + + // 2. Try to create the sprite + if (composite.createSprite(240, 240)) { + printf("SUCCESS: Composite sprite created.\n"); + composite.fillSprite(TFT_RED); // If this works, screen should turn RED + } else { + printf("FATAL: Composite sprite failed! No RAM/PSRAM.\n"); + return; // Stop here so we don't draw "lines" + } + + composite.setFreeFont(NULL); // Reset to default GLCD font + composite.setTextFont(1); // Use the standard small font (scaled by size 4) + composite.setTextColor(TFT_BLUE); + composite.setTextSize(4); + composite.pushSprite(0, 0); } void tft_drawBuffer() { - tft.startWrite(); - composite1.pushSprite(0, 0); - composite2.pushSprite(0, 0 + BUF_H); - tft.endWrite(); + composite.pushSprite(0, 0, TFT_TRANSPARENT); } -/*void tft_drawBuffer() { - tft.startWrite(); - tft.pushImageDMA(0, 0, 240, 120, (uint16_t*) composite1.getPointer()); - tft.pushImageDMA(0, 120, 240, 120, (uint16_t*) composite2.getPointer()); - tft.endWrite(); -}*/ - void tft_clearBuffer(TFT_eSprite &composite, uint16_t color) { composite.fillSprite(color); } void tft_clearBuffer(uint16_t color) { - composite1.fillSprite(color); - composite2.fillSprite(color); + composite.fillSprite(color); } void tft_drawCenteredText(const char* text, int size, int yGlobal) { int textW = strlen(text) * size * 6; int x = (SCREEN_WIDTH - textW) / 2; - composite1.setTextSize(size); - composite1.setTextColor(TFT_BLACK); - composite1.drawString(text, x, yGlobal); - - // only bottom half, adjust local Y - int yLocal = yGlobal - BUF_H; - composite2.setTextSize(size); - composite2.setTextColor(TFT_BLACK); - composite2.drawString(text, x, yLocal); + composite.setTextSize(size); + composite.setTextColor(TFT_BLACK); + composite.drawString(text, x, yGlobal); } void tft_drawText(const char* text, int size, int x, int y, uint16_t color) { - composite1.setTextSize(size); - composite1.setTextColor(color); - composite1.drawString(text, x, y); - - composite2.setTextSize(size); - composite2.setTextColor(color); - composite2.drawString(text, x, y - BUF_H); + composite.setTextSize(size); + composite.setTextColor(color); + composite.drawString(text, x, y); } void tft_drawRectangle(int x, int y, int w, int h, uint16_t color) { - composite1.fillRect(x, y, w, h, color); - composite2.fillRect(x, y - BUF_H, w, h, color); + composite.fillRect(x, y, w, h, color); } \ No newline at end of file diff --git a/src/draw/draw.h b/src/draw/draw.h index 23416b0..76c5b28 100644 --- a/src/draw/draw.h +++ b/src/draw/draw.h @@ -2,17 +2,19 @@ #define DRAW_H #include +#include "defs/sprite_data.h" void draw_drawSprite( - TFT_eSprite &tft, int x, int y, + TFT_eSprite &tft, int x, int y, struct SpriteData* spriteData, uint8_t spriteNumber, - uint8_t factor, bool flipHorizontal = false + bool flipHorizontal = false ); -void draw_drawBackground(TFT_eSprite &bg, int spr_w, int spr_h, int factor); -void draw_drawBackgroundSection(TFT_eSprite &bg, int spr_w, int spr_h, int tft_x, int tft_y, int tft_w, int tft_h, int factor); +void draw_drawBackground(TFT_eSprite& bg, int spr_w, int spr_h, int factor); +void draw_drawBackgroundSection(TFT_eSprite& bg, int x, int y, int w, int h); void draw_drawSpriteCentered( - TFT_eSprite &spr, struct SpriteData* spriteData, uint8_t spriteNumber, uint8_t factor, bool flipped = false, int y = -1 + TFT_eSprite &spr, struct SpriteData* spriteData, uint8_t spriteNumber, + bool flipped = false, int y = -1 ); -void draw_drawAttacks(TFT_eSprite &sprite, struct SpriteData* attackSpriteData, int x, int y, uint8_t attackType, uint8_t attackSprite, uint8_t factor, bool flipped = false); +void draw_drawAttacks(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* attackSpriteData, int x, int y, uint8_t attackType, uint8_t attackSprite, bool flipped = false); #endif \ No newline at end of file diff --git a/src/draw/draw_attacks.cpp b/src/draw/draw_attacks.cpp index 1e3f8ef..262640e 100644 --- a/src/draw/draw_attacks.cpp +++ b/src/draw/draw_attacks.cpp @@ -2,16 +2,20 @@ #include "defs/sprite_data.h" -void draw_drawAttacks(TFT_eSprite &sprite, struct SpriteData* attackSpriteData, int x, int y, uint8_t attackType, uint8_t attackSprite, uint8_t factor, bool flipped) { +void draw_drawAttacks(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* attackSpriteData, int x, int y, uint8_t attackType, uint8_t attackSprite, bool flipped) { + // spriteWidth/Height are already pre-scaled at load time + int cleanWidth = attackSpriteData->spriteWidth + 6; // +4 to be safe + draw_drawBackgroundSection(bg, x, y, cleanWidth, attackSpriteData->spriteHeight * 2); + switch(attackType) { case 1: - draw_drawSprite(sprite, x, y, attackSpriteData, attackSprite, factor, flipped); - draw_drawSprite(sprite, x, y + 48, attackSpriteData, attackSprite, factor, flipped); + draw_drawSprite(sprite, x, y, attackSpriteData, attackSprite, flipped); + draw_drawSprite(sprite, x, y + 48, attackSpriteData, attackSprite, flipped); break; - + case 0: default: - draw_drawSprite(sprite, x, y, attackSpriteData, attackSprite, factor, flipped); + draw_drawSprite(sprite, x, y, attackSpriteData, attackSprite, flipped); break; } } \ No newline at end of file diff --git a/src/draw/draw_background.cpp b/src/draw/draw_background.cpp index 658ddfc..bec50b5 100644 --- a/src/draw/draw_background.cpp +++ b/src/draw/draw_background.cpp @@ -1,83 +1,24 @@ #include "draw.h" +#include "defs/sprite_data.h" #include "defs/screen_defs.h" const char* TAG_DB = "[DRAW BG]"; -void draw_drawBackground(TFT_eSprite &bg, int spr_w, int spr_h, int factor) { - // spr_w, spr_h = dimensions of the source sprite “bg” - // factor = integer scale factor - - for (int srcY = 0; srcY < spr_h; srcY++) { - // Compute the top row in the scaled image that corresponds to srcY - int destRowBase = srcY * factor; - - // For each “vertical tile” row within [0 .. factor-1]: - for (int dy = 0; dy < factor; dy++) { - int outY1 = destRowBase + dy; // Y in composite1 - int outY2 = outY1 - 120; // Y in composite2 - - // Now loop over each source column - for (int srcX = 0; srcX < spr_w; srcX++) { - // Fetch the color exactly once for this source pixel - uint16_t color = bg.readPixel(srcX, srcY); - - // Compute the leftmost column in the scaled image that corresponds to srcX - int destColBase = srcX * factor; - - // For each “horizontal tile” column within [0 .. factor-1]: - for (int dx = 0; dx < factor; dx++) { - int outX = destColBase + dx; - composite1.drawPixel(outX, outY1, color); - composite2.drawPixel(outX, outY2, color); - } - } - } - } +void draw_drawBackground(TFT_eSprite& bg, int spr_w, int spr_h, int factor) { + bg.pushToSprite(&composite, 0, 0, TFT_TRANSPARENT); } -// USO FUTURO -void draw_drawBackgroundSection(TFT_eSprite &bg, int spr_w, int spr_h, int tft_x, int tft_y, int tft_w, int tft_h, int factor) { - int srcX_start = tft_x / factor; - int srcX_end = (tft_x + tft_w - 1) / factor; - int srcY_start = tft_y / factor; - int srcY_end = (tft_y + tft_h - 1) / factor; +void draw_drawBackgroundSection(TFT_eSprite& bg, int x, int y, int w, int h) { + // Get the raw 16-bit pixel buffer from the background sprite + uint16_t* bgPtr = (uint16_t*)bg.getPointer(); + int bgStride = bg.width(); // Full row width — needed to advance between rows - if (srcX_start < 0) srcX_start = 0; - if (srcY_start < 0) srcY_start = 0; - if (srcX_end >= spr_w) srcX_end = spr_w - 1; - if (srcY_end >= spr_h) srcY_end = spr_h - 1; - - if (srcX_start > srcX_end || srcY_start > srcY_end) return; - - for (int srcY = srcY_start; srcY <= srcY_end; srcY++) { - int destY_base = srcY * factor; - int blockY0 = destY_base; - int blockY1 = destY_base + (factor - 1); - - int y0 = (blockY0 < tft_y) ? tft_y : blockY0; - int y1 = (blockY1 > (tft_y + tft_h - 1)) ? (tft_y + tft_h - 1) : blockY1; - - if (y0 > y1) continue; - - for (int srcX = srcX_start; srcX <= srcX_end; srcX++) { - int destX_base = srcX * factor; - int blockX0 = destX_base; - int blockX1 = destX_base + (factor - 1); - - int x0 = (blockX0 < tft_x) ? tft_x : blockX0; - int x1 = (blockX1 > (tft_x + tft_w - 1)) ? (tft_x + tft_w - 1) : blockX1; - - if (x0 > x1) continue; - - uint16_t color = bg.readPixel(srcX, srcY); - - for (int y = y0; y <= y1; y++) { - for (int x = x0; x <= x1; x++) { - composite1.drawPixel(x, y, color); - composite2.drawPixel(x, y - 120, color); - } - } - } + // pushImage assumes a contiguous (packed) source buffer, so feeding the + // whole rectangle at once would read wrong pixels after the first row. + // Instead, copy one row at a time, each time jumping by bgStride pixels. + for (int row = 0; row < h; row++) { + uint16_t* rowSrc = bgPtr + ((y + row) * bgStride) + x; + composite.pushImage(x, y + row, w, 1, rowSrc); } -} \ No newline at end of file +} diff --git a/src/draw/draw_sprites.cpp b/src/draw/draw_sprites.cpp index 1302744..b930755 100644 --- a/src/draw/draw_sprites.cpp +++ b/src/draw/draw_sprites.cpp @@ -9,106 +9,56 @@ const char* TAG_D = "[DRAW]"; -/*void draw_drawSprite( - TFT_eSprite &spr, int x, int y, - struct SpriteData* spriteData, uint8_t spriteNumber, uint8_t factor, bool flipHorizontal -) { - int scaledWidth = spriteData->spriteWidth * factor; - int scaledHeight = spriteData->spriteHeight * factor; - - spr.createSprite(scaledWidth, scaledHeight); - - for (int sy = 0; sy < scaledHeight; sy++) { - for (int sx = 0; sx < scaledWidth; sx++) { - int srcX = sx / factor; - if (flipHorizontal) { - srcX = (spriteData->spriteWidth - 1) - srcX; - } - - int srcY = sy / factor; - - uint16_t color = spriteData->spriteData - [spriteNumber] - [srcY * spriteData->spriteWidth + srcX]; - - spr.drawPixel(sx, sy, color); - } - } - - spr.pushToSprite(&composite1, x, y, TFT_TRANSPARENT); - spr.pushToSprite(&composite2, x, y - 120, TFT_TRANSPARENT); - - spriteData->lastX = x; - spriteData->lastY = y; - spriteData->lastW = scaledWidth; - spriteData->lastH = scaledWidth; - - //printf("%s: Sprite %d drawn at (%d, %d) %s\n", TAG_D, spriteNumber, x, y, (flipHorizontal ? "flipped" : "")); -}*/ - - void draw_drawSprite( TFT_eSprite &spr, int x, int y, struct SpriteData* spriteData, uint8_t spriteNumber, - uint8_t factor, bool flipHorizontal ) { - int srcW = spriteData->spriteWidth; - int srcH = spriteData->spriteHeight; - int scaledW = srcW * factor; - int scaledH = srcH * factor; + // Sprites are pre-scaled at load time; width/height are already final. + const int W = spriteData->spriteWidth; + const int H = spriteData->spriteHeight; - if (spr.width() != scaledW || spr.height() != scaledH) { + if (spr.width() != W || spr.height() != H) { spr.deleteSprite(); - spr.createSprite(scaledW, scaledH); + spr.createSprite(W, H); } - uint16_t *sprBuf = (uint16_t *)spr.getPointer(); - uint16_t *srcBuf = spriteData->spriteData[spriteNumber]; + uint16_t* sprBuf = (uint16_t*) spr.getPointer(); + uint16_t* srcBuf = spriteData->spriteData[spriteNumber]; - for (int srcY = 0; srcY < srcH; srcY++) { - int destYBase = srcY * factor; - for (int srcX = 0; srcX < srcW; srcX++) { - int useX = flipHorizontal ? (srcW - 1 - srcX) : srcX; - uint16_t raw = srcBuf[srcY * srcW + useX]; - uint16_t color = (raw << 8) | (raw >> 8); - - int destXBase = srcX * factor; - for (int dy = 0; dy < factor; dy++) { - int rowStart = (destYBase + dy) * scaledW + destXBase; - for (int dx = 0; dx < factor; dx++) { - sprBuf[rowStart + dx] = color; - } + if (!flipHorizontal) { + // Fast path: one memcpy of the whole frame + memcpy(sprBuf, srcBuf, W * H * sizeof(uint16_t)); + } else { + // Mirror each row horizontally + for (int row = 0; row < H; row++) { + const uint16_t* src = srcBuf + row * W; + uint16_t* dst = sprBuf + row * W; + for (int col = 0; col < W; col++) { + dst[col] = src[W - 1 - col]; } } } - spr.pushToSprite(&composite1, x, y, TFT_TRANSPARENT); - spr.pushToSprite(&composite2, x, y - 120, TFT_TRANSPARENT); + spr.pushToSprite(&composite, x, y, TFT_TRANSPARENT); spriteData->lastX = x; spriteData->lastY = y; - spriteData->lastW = scaledW; - spriteData->lastH = scaledH; + spriteData->lastW = W; + spriteData->lastH = H; } void draw_drawSpriteCentered( TFT_eSprite &spr, - struct SpriteData* spriteData, uint8_t spriteNumber, uint8_t factor, bool flipped, int y + struct SpriteData* spriteData, uint8_t spriteNumber, bool flipped, int y ) { - int x = (BUFFER_X - (spriteData->spriteWidth * factor)) / 2; - int new_y; - if (y == -1) { - new_y = (BUFFER_Y - (spriteData->spriteHeight * factor)) / 2; - } else { - new_y = y; - } + int x = (BUFFER_X - spriteData->spriteWidth) / 2; + int new_y = (y == -1) + ? (BUFFER_Y - spriteData->spriteHeight) / 2 + : y; - draw_drawSprite( - spr, x, new_y, - spriteData, spriteNumber, factor, flipped - ); + draw_drawSprite(spr, x, new_y, spriteData, spriteNumber, flipped); } \ No newline at end of file diff --git a/src/energy/light_sleep.cpp b/src/energy/light_sleep.cpp index acb5bba..19b80f5 100644 --- a/src/energy/light_sleep.cpp +++ b/src/energy/light_sleep.cpp @@ -1,28 +1,77 @@ #include "energy.h" #include #include "defs/defs.h" +#include "defs/chara_data.h" +#include "defs/sprite_data.h" #include "display/display.h" #include "driver/rtc_io.h" #include "defs/screen_defs.h" +#include "storage/storage.h" +#include "vpet/vpet/vpet.h" -#define SLEEP_TIME_US 15000000ull - -#define BUTTON_PIN_BITMASK(GPIO) (1ULL << GPIO) // Macro for individual GPIO bitmask +#define SLEEP_TIME_US 60000000ull // 60 seconds periodic wakeup void energy_setUpLightSleep() { - // Plena confianza en manolo - esp_sleep_enable_ext0_wakeup((gpio_num_t) K4_PIN, LOW); - esp_sleep_enable_timer_wakeup(SLEEP_TIME_US); + // Left as a placeholder for backward compatibility } void energy_startLightSleep() { + printf("[ENERGY] Entering light sleep...\n"); + + // 1. Configure wake-up sources + esp_sleep_enable_timer_wakeup(SLEEP_TIME_US); + + uint64_t mask = (1ULL << K1_PIN) | (1ULL << K2_PIN) | (1ULL << K3_PIN) | (1ULL << K4_PIN); + #if BUTTON_MODE == INPUT_PULLUP + #if defined(ESP_EXT1_WAKEUP_ANY_LOW) + esp_sleep_enable_ext1_wakeup(mask, ESP_EXT1_WAKEUP_ANY_LOW); + #else + esp_sleep_enable_ext1_wakeup(mask, ESP_EXT1_WAKEUP_ALL_LOW); + #endif + #else + esp_sleep_enable_ext1_wakeup(mask, ESP_EXT1_WAKEUP_ANY_HIGH); + #endif + + // 2. Start light sleep (powers down CPU core and clocks, keeps RAM and state) esp_light_sleep_start(); - printf("[MAIN] Woken up\n"); - - // Who woke you up???? TELL me!! - auto cause = esp_sleep_get_wakeup_cause(); + // 3. Woken up! Let's check why + esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); + printf("[ENERGY] Woken up. Cause: %d\n", cause); + // 4. Force immediate simulation update runVpetTasks = true; -} - \ No newline at end of file + vpet_runVpetTasks(); + + // 5. Evaluate the current character's state to see if any alert/event was triggered + if (cause == ESP_SLEEP_WAKEUP_TIMER) { + bool hasAlert = ( + charaData[currentCharacter].hunger == 0 || + charaData[currentCharacter].strength == 0 || + charaData[currentCharacter].careMistakeCallLight || + screenKey == TIMER_FINISHED_SCREEN + ); + + if (hasAlert) { + // Wake up display and backlight to notify the user + printf("[ENERGY] Periodic wakeup triggered a critical alert! Waking up completely.\n"); + digitalWrite(BL_PIN, HIGH); + screenOff = false; + inactive = false; + if (screenKey != TIMER_FINISHED_SCREEN) { + screenKey = TIMER_FINISHED_SCREEN; + } + } else { + // Background checkpoint save, then let the loop put the CPU back to sleep + printf("[ENERGY] Periodic simulation update successful. No alerts. Saving state...\n"); + storage_saveState(); + } + } else if (cause == ESP_SLEEP_WAKEUP_EXT1) { + // Woken up by a user button press + printf("[ENERGY] User button press detected. Restoring UI...\n"); + digitalWrite(BL_PIN, HIGH); + screenOff = false; + inactive = false; + screenKey = MAIN_SCREEN; + } +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index a3d4473..65529e5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,8 +20,7 @@ const char* TAG = "[MAIN]"; // TFT_eSPI stuff, important TFT_eSPI tft = TFT_eSPI(); -TFT_eSprite composite1 = TFT_eSprite(&tft); -TFT_eSprite composite2 = TFT_eSprite(&tft); +TFT_eSprite composite = TFT_eSprite(&tft); TFT_eSprite sprite = TFT_eSprite(&tft); TFT_eSprite bg = TFT_eSprite(&tft); @@ -41,7 +40,7 @@ struct CharacterData* charaData; uint8_t currentCharacter = 0; // Boot flag, tells if the device clock has been initialized -bool coldBoot = true; +bool timeSet = false; // Screen keys, this tells which screen is being shown the screens state machine int screenKey = TITLE_SCREEN; @@ -70,42 +69,40 @@ void secondCoreTask(void*); void setup() { Serial.begin(115200); - delay(100); // Give MPU6050 and ESP32 time to power up + + //delay(10000); //Wire.begin(MPU_SDA_PIN, MPU_SCL_PIN); // I2C init before MPU6050 //mpu.initialize(); tft_initDisplay(tft, TFT_BLACK); - tft_initScreenBuffer(TFT_BLACK); + tft_initScreenBuffer(TFT_TRANSPARENT); storage_init(); - charaData = (struct CharacterData*) calloc(CHARA_COUNT_IN_DEVICE, sizeof(struct CharacterData)); - storage_readFile("/menu.bin", &menuElementsData); storage_readFile("/ui.bin", &uiElementsData); - - storage_initBackground("/bg.bin", bg); - - pinMode(K1_PIN, INPUT_PULLDOWN); - pinMode(K2_PIN, INPUT_PULLDOWN); - pinMode(K3_PIN, INPUT_PULLDOWN); - pinMode(K4_PIN, INPUT_PULLDOWN); - + + storage_initBackground("/bg2.bin", bg); + + pinMode(K1_PIN, BUTTON_MODE); + pinMode(K2_PIN, BUTTON_MODE); + pinMode(K3_PIN, BUTTON_MODE); + pinMode(K4_PIN, BUTTON_MODE); + xTaskCreatePinnedToCore(secondCoreTask, "VPET_EVAL", 4096, NULL, 0, &secondLoop, 0); lines_initLineStorage(); - vpet_initTimer(); - - energy_setUpLightSleep(); + storage_loadState(); + } void loop() { switch (screenKey) { case TITLE_SCREEN: - menu_drawTitle(bg); + menu_drawTitle(bg, composite); break; case CLOCK_EDIT_SCREEN: @@ -185,7 +182,7 @@ void loop() { break; case EGG_EMPTY_SCREEN: - menu_drawDeathScreen( bg, sprite, &menuElementsData, &uiElementsData); + menu_drawDeathScreen(bg, sprite, &menuElementsData, &uiElementsData); break; case EVOLUTION_SCREEN: @@ -193,7 +190,7 @@ void loop() { break; case TRAINING_SCREEN_1: - training_screenTraining1(bg, sprite, &mainCharacterSprites, &uiElementsData); + training_screenTraining2(bg, sprite, &mainCharacterSprites, &uiElementsData); break; case MAIN_SCREEN: @@ -203,10 +200,14 @@ void loop() { case CHANGE_SCREEN: menu_changeCharaScreen(bg, sprite, &mainCharacterSprites, &uiElementsData); break; + + case FROZEN_SCREEN: + menu_drawFridgeScreen(bg, sprite, &mainCharacterSprites, &menuElementsData); + break; } if (screenKey == IDLE_SCREEN || screenKey == OFF_SCREEN) { - steps_countSteps(); + //steps_countSteps(); } } diff --git a/src/menu/angry_screen.cpp b/src/menu/angry_screen.cpp index 718b4a5..f40af96 100644 --- a/src/menu/angry_screen.cpp +++ b/src/menu/angry_screen.cpp @@ -6,7 +6,7 @@ #include "animations/animations.h" void menu_drawAngryScreen( - TFT_eSprite &bg, TFT_eSprite &sprite, + TFT_eSprite& bg, TFT_eSprite &sprite, struct SpriteData* spriteData, struct SpriteData* smallUiElements ) { uint8_t frameCounter = 0; @@ -33,8 +33,8 @@ void menu_drawAngryScreen( tone(SPK_PIN, 1000, 200); tft_clearBuffer(sprite, TFT_TRANSPARENT); - draw_drawSprite(sprite, 18, 72, smallUiElements, FIREWORKS_ICON, 6); - draw_drawSprite(sprite, 174, 72, smallUiElements, FIREWORKS_ICON, 6); + draw_drawSprite(sprite, 18, 72, smallUiElements, FIREWORKS_ICON); + draw_drawSprite(sprite, 174, 72, smallUiElements, FIREWORKS_ICON); } frameCounter++; diff --git a/src/menu/care_mistake_screen.cpp b/src/menu/care_mistake_screen.cpp index e251f85..50081e3 100644 --- a/src/menu/care_mistake_screen.cpp +++ b/src/menu/care_mistake_screen.cpp @@ -8,7 +8,7 @@ uint64_t lastBeepTime = esp_timer_get_time(); uint8_t beepCounter = 0; -void menu_careMistakeScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* spriteData, struct SpriteData* uiSpritesBig) { +void menu_careMistakeScreen(TFT_eSprite& bg, TFT_eSprite &sprite, struct SpriteData* spriteData, struct SpriteData* uiSpritesBig) { uint64_t currentTime = esp_timer_get_time(); uint8_t pressedButtons = buttons_getPressedButtons(); diff --git a/src/menu/change_animation_screen.cpp b/src/menu/change_animation_screen.cpp index 8387f21..5da80c6 100644 --- a/src/menu/change_animation_screen.cpp +++ b/src/menu/change_animation_screen.cpp @@ -8,18 +8,33 @@ struct SpriteData* checkerboardPattern; void menu_createCheckerboard() { + // Build the pattern pre-scaled by SPRITE_SCALE (6) so that + // draw_drawSprite can treat it identically to SPIFFS-loaded sprites. + // Logical size: 34 wide × 1 tall → Scaled: 204 wide × 6 tall + 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 uint32_t bufferSize = scaledW * scaledH; + checkerboardPattern = (SpriteData*) malloc(sizeof(SpriteData)); - checkerboardPattern->spriteHeight = 1; - checkerboardPattern->spriteWidth = 34; + checkerboardPattern->spriteWidth = scaledW; + checkerboardPattern->spriteHeight = scaledH; checkerboardPattern->spriteNumber = 1; - checkerboardPattern->spriteData = (uint16_t**) malloc(sizeof(uint16_t*) * checkerboardPattern->spriteNumber); - checkerboardPattern->spriteData[0] = (uint16_t*) malloc(sizeof(uint16_t) * checkerboardPattern->spriteWidth); - - for (int i = 0; i < checkerboardPattern->spriteWidth; i++) { - if (i % 2 == 0) { - checkerboardPattern->spriteData[0][i] = TFT_BLACK; - } else { - checkerboardPattern->spriteData[0][i] = TFT_TRANSPARENT; + checkerboardPattern->spriteData = (uint16_t**) malloc(sizeof(uint16_t*)); + checkerboardPattern->spriteData[0] = (uint16_t*) malloc(sizeof(uint16_t) * bufferSize); + + uint16_t* buf = checkerboardPattern->spriteData[0]; + + // Fill: repeat each logical pixel as a SCALE×SCALE block across all rows + for (uint16_t row = 0; row < scaledH; row++) { + for (uint8_t col = 0; col < logicalW; col++) { + uint16_t color = (col % 2 == 0) ? TFT_BLACK : TFT_TRANSPARENT; + uint16_t* dst = buf + row * scaledW + col * SCALE; + for (uint8_t dx = 0; dx < SCALE; dx++) { + dst[dx] = color; + } } } } @@ -32,7 +47,7 @@ void menu_freeCheckerboard() { } // Don't worry, I hate this too -void menu_evolutionScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* mainCharacterSprites) { +void menu_evolutionScreen(TFT_eSprite& bg, TFT_eSprite &sprite, struct SpriteData* mainCharacterSprites) { menu_createCheckerboard(); TFT_eSprite checkerboard = TFT_eSprite(&tft); @@ -48,7 +63,7 @@ void menu_evolutionScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteDat tone(SPK_PIN, 3500, 50); draw_drawBackground(bg, 90, 90, 3); - draw_drawSprite(sprite, 72 + ((i % 2 == 0) * 6), 72, mainCharacterSprites, 6, 6); + draw_drawSprite(sprite, 72 + ((i % 2 == 0) * 6), 72, mainCharacterSprites, 6); tft_drawBuffer(); @@ -59,7 +74,7 @@ void menu_evolutionScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteDat } draw_drawBackground(bg, 90, 90, 3); - draw_drawSprite(sprite, 72, 72, mainCharacterSprites, 7, 6); + draw_drawSprite(sprite, 72, 72, mainCharacterSprites, 7); tft_clearBuffer(sprite, TFT_TRANSPARENT); @@ -70,7 +85,7 @@ void menu_evolutionScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteDat tft_drawRectangle(18, startYPos, 204, 6, TFT_RED); - draw_drawSprite(checkerboard, 18, startYPos, checkerboardPattern, 0, 6, checkerboardShift); + draw_drawSprite(checkerboard, 18, startYPos, checkerboardPattern, 0, checkerboardShift); tft_drawBuffer(); @@ -105,7 +120,7 @@ void menu_evolutionScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteDat uint8_t startYPos = 72 + (i * 6); tft_drawRectangle(18, startYPos, 204, 6, TFT_GREEN); - draw_drawSprite(checkerboard, 18, startYPos, checkerboardPattern, 0, 6, checkerboardShift); + draw_drawSprite(checkerboard, 18, startYPos, checkerboardPattern, 0, checkerboardShift); tft_drawBuffer(); @@ -120,7 +135,7 @@ void menu_evolutionScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteDat uint64_t currentTime = esp_timer_get_time(); if (currentTime - lastUpdateTime > 100000) { draw_drawBackground(bg, 90, 90, 3); - draw_drawSprite(sprite, 72, 72, mainCharacterSprites, 7, 6); + draw_drawSprite(sprite, 72, 72, mainCharacterSprites, 7); uint8_t rectHeight = (6 * i); @@ -129,7 +144,7 @@ void menu_evolutionScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteDat for (int j = 0; j < i; j++) { uint8_t rectYPos = 72 + (6 * j); - draw_drawSprite(checkerboard, 18, rectYPos, checkerboardPattern, 0, 6, checkerboardShift); + draw_drawSprite(checkerboard, 18, rectYPos, checkerboardPattern, 0, checkerboardShift); checkerboardShift = !checkerboardShift; } diff --git a/src/menu/change_chara_screen.cpp b/src/menu/change_chara_screen.cpp index 61ba8f6..d5196bb 100644 --- a/src/menu/change_chara_screen.cpp +++ b/src/menu/change_chara_screen.cpp @@ -8,7 +8,7 @@ #include "defs/defs.h" -void menu_changeCharaScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* mainSpriteData, struct SpriteData* uiSpriteData) { +void menu_changeCharaScreen(TFT_eSprite& bg, TFT_eSprite &sprite, struct SpriteData* mainSpriteData, struct SpriteData* uiSpriteData) { vTaskSuspend(secondLoop); uint8_t selectedChara = currentCharacter; @@ -63,13 +63,13 @@ void menu_changeCharaScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteD sprintf(fileName, "/chara/%02x.bin", selectedCharaData->idChara); storage_readFile(fileName, mainSpriteData); - draw_drawSprite(sprite, 18, 72, mainSpriteData, 0, 6); + draw_drawSprite(sprite, 18, 72, mainSpriteData, 0); } else { tft_drawCenteredText("EMPTY", 4, 120); } - draw_drawSprite(sprite, 174, 96, uiSpriteData, ARROW_ICON, 6); + draw_drawSprite(sprite, 174, 96, uiSpriteData, ARROW_ICON); tft_drawBuffer(); diff --git a/src/menu/clock_screen.cpp b/src/menu/clock_screen.cpp index 297b33e..1448ef6 100644 --- a/src/menu/clock_screen.cpp +++ b/src/menu/clock_screen.cpp @@ -4,8 +4,9 @@ #include "display/display.h" #include "buttons/buttons.h" #include "defs/screen_defs.h" +#include "vpet/vpet/vpet.h" -void menu_drawClock(TFT_eSprite &bg) { +void menu_drawClock(TFT_eSprite& bg) { uint8_t pressedButtons = buttons_getPressedButtons(); switch (pressedButtons) { case K2_PRESSED: @@ -30,7 +31,7 @@ void menu_drawClock(TFT_eSprite &bg) { tft_drawBuffer(); } -void menu_drawClockEdit(TFT_eSprite &bg) { +void menu_drawClockEdit(TFT_eSprite& bg) { char textBuffer[6]; static int clockHourCount = 0; @@ -50,10 +51,14 @@ void menu_drawClockEdit(TFT_eSprite &bg) { 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); + srand(time(NULL)); - coldBoot = false; - + timeSet = true; + screenKey = CLOCK_SCREEN; + + vpet_initTimer(); + break; default: diff --git a/src/menu/death_screen.cpp b/src/menu/death_screen.cpp index e118a09..f3d5f36 100644 --- a/src/menu/death_screen.cpp +++ b/src/menu/death_screen.cpp @@ -6,7 +6,7 @@ #include "defs/sprite_data.h" #include "vpet/lines/lines.h" -void menu_drawDeathScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* uiBigSprite, struct SpriteData* uiSmallSprite) { +void menu_drawDeathScreen(TFT_eSprite& bg, TFT_eSprite &sprite, struct SpriteData* uiBigSprite, struct SpriteData* uiSmallSprite) { static uint8_t frameCounter = 0; uint64_t currentTime = esp_timer_get_time(); @@ -33,7 +33,7 @@ void menu_drawDeathScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteDat if (currentTime - lastUpdateTime > ANIMATION_THRESHOLD_TIME_US) { draw_drawBackground(bg, 90, 90, 3); - draw_drawSprite(sprite, 72 + (6 * (frameCounter == 0)), 72, uiBigSprite, EMPTY_EGG, 6); + draw_drawSprite(sprite, 72 + (6 * (frameCounter == 0)), 72, uiBigSprite, EMPTY_EGG); tft_clearBuffer(sprite, TFT_TRANSPARENT); menu_uiOverlay(sprite, uiSmallSprite); tft_clearBuffer(sprite, TFT_TRANSPARENT); diff --git a/src/menu/egg_hatch_screen.cpp b/src/menu/egg_hatch_screen.cpp index 23053e6..1b250f1 100644 --- a/src/menu/egg_hatch_screen.cpp +++ b/src/menu/egg_hatch_screen.cpp @@ -9,7 +9,7 @@ #include "vpet/vpet/vpet.h" #include "vpet/lines/lines.h" -void menu_eggHatchScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* uiBigSprite, struct SpriteData* uiSmallSprite) { +void menu_eggHatchScreen(TFT_eSprite& bg, TFT_eSprite &sprite, struct SpriteData* uiBigSprite, struct SpriteData* uiSmallSprite) { static bool eggSpriteFrame = false; uint8_t pressedButtons = buttons_getPressedButtons(); @@ -26,7 +26,7 @@ void menu_eggHatchScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData 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, 6); + draw_drawSpriteCentered(sprite, ¤tEgg->eggSprite, eggSpriteFrame); eggSpriteFrame = !eggSpriteFrame; lastUpdateTime = currentTime; @@ -47,7 +47,7 @@ void menu_eggHatchScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData draw_drawBackground(bg, 90, 90, 3); - draw_drawSpriteCentered(sprite, ¤tEgg->eggSprite, 2, 6); + draw_drawSpriteCentered(sprite, ¤tEgg->eggSprite, 2); tft_drawBuffer(); diff --git a/src/menu/egg_select_screen.cpp b/src/menu/egg_select_screen.cpp index b128b63..16ec0a4 100644 --- a/src/menu/egg_select_screen.cpp +++ b/src/menu/egg_select_screen.cpp @@ -9,7 +9,7 @@ #include "vpet/vpet/vpet.h" -void menu_lineSwitcher(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* uiSmallSprite) { +void menu_lineSwitcher(TFT_eSprite& bg, TFT_eSprite &sprite, struct SpriteData* uiSmallSprite) { static uint8_t eggCounter = 0; uint8_t buttonsPressed = buttons_getPressedButtons(); @@ -36,9 +36,9 @@ void menu_lineSwitcher(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* draw_drawBackground(bg, 90, 90, 3); tft_clearBuffer(sprite, TFT_TRANSPARENT); - draw_drawSpriteCentered(sprite, &eggSelection[eggCounter].eggSprite, 0, 6); + draw_drawSpriteCentered(sprite, &eggSelection[eggCounter].eggSprite, 0); tft_clearBuffer(sprite, TFT_TRANSPARENT); - draw_drawSprite(sprite, 194, 96, uiSmallSprite, ARROW_ICON, 6); + draw_drawSprite(sprite, 194, 96, uiSmallSprite, ARROW_ICON); tft_drawBuffer(); } diff --git a/src/menu/feeding_screen.cpp b/src/menu/feeding_screen.cpp index 90525d9..7b764f9 100644 --- a/src/menu/feeding_screen.cpp +++ b/src/menu/feeding_screen.cpp @@ -5,7 +5,7 @@ #include "display/display.h" void menu_feedingScreen( - TFT_eSprite &bg, TFT_eSprite &charaSprite, + TFT_eSprite& bg, TFT_eSprite &charaSprite, struct SpriteData* uiSpriteData, struct SpriteData* charaSpriteData, uint8_t item ) { static int currentAnimationFrame = 0; @@ -19,7 +19,7 @@ void menu_feedingScreen( animate_performEatingAnimation(charaSprite, charaSpriteData); tft_clearBuffer(charaSprite, TFT_TRANSPARENT); - draw_drawSprite(charaSprite, 24, 120, uiSpriteData, item, 6); + draw_drawSprite(charaSprite, 24, 120, uiSpriteData, item); lastUpdateTime = currentTime; currentAnimationFrame++; diff --git a/src/menu/food_select_screen.cpp b/src/menu/food_select_screen.cpp index c922208..700aa78 100644 --- a/src/menu/food_select_screen.cpp +++ b/src/menu/food_select_screen.cpp @@ -1,92 +1,94 @@ -#include "menu.h" -#include "display/display.h" -#include "draw/draw.h" #include "buttons/buttons.h" #include "defs/chara_data.h" +#include "display/display.h" +#include "draw/draw.h" +#include "menu.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); - screenKey = MENU_SCREEN; - - return; - } +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); + screenKey = MENU_SCREEN; - static uint8_t arrowPosition = 0; - - uint8_t pressedButtons = buttons_getPressedButtons(); - switch (pressedButtons) { - case 8: - arrowPosition = (arrowPosition + 1) % 2; - break; + return; + } - case 2: - screenKey = MENU_SCREEN; - break; - - default: - break; - } - - if (pressedButtons == 4) { - lastUpdateTime = 0; - switch(arrowPosition) { - case 0: - if (charaData[currentCharacter].hunger < 8) { - charaData[currentCharacter].hungerCareMistakeTimer = charaData[currentCharacter].initialStatsReductionTime; - charaData[currentCharacter].hungerCareMistakeObtained = false; - charaData[currentCharacter].weight++; - charaData[currentCharacter].hunger++; - screenKey = FEEDING_SCREEN; - submenuKey = FOOD_ICON; - } else { - screenKey = REFUSING_SCREEN; - if (!charaData[currentCharacter].overfeedHappened) { - charaData[currentCharacter].overfeed++; - charaData[currentCharacter].overfeedHappened = true; - } - } - return; - break; + static uint8_t arrowPosition = 0; - case 1: - if (charaData[currentCharacter].strength < 8) { - charaData[currentCharacter].strengthCareMistakeTimer = charaData[currentCharacter].initialStatsReductionTime; - charaData[currentCharacter].strength++; - charaData[currentCharacter].weight += 2; - screenKey = FEEDING_SCREEN; - submenuKey = PILL_ICON; - } else { - screenKey = REFUSING_SCREEN; - } - return; - break; - - default: - break; + uint8_t pressedButtons = buttons_getPressedButtons(); + switch (pressedButtons) { + case 8: + arrowPosition = (arrowPosition + 1) % 2; + break; + + case 2: + screenKey = MENU_SCREEN; + break; + + default: + break; + } + + if (pressedButtons == 4) { + lastUpdateTime = 0; + switch (arrowPosition) { + case 0: + if (charaData[currentCharacter].hunger < 8) { + charaData[currentCharacter].hungerCareMistakeTimer = + charaData[currentCharacter].initialStatsReductionTime; + charaData[currentCharacter].hungerCareMistakeObtained = false; + charaData[currentCharacter].weight++; + charaData[currentCharacter].hunger++; + screenKey = FEEDING_SCREEN; + submenuKey = FOOD_ICON; + } else { + screenKey = REFUSING_SCREEN; + if (!charaData[currentCharacter].overfeedHappened) { + charaData[currentCharacter].overfeed++; + charaData[currentCharacter].overfeedHappened = true; } + } + return; + break; - vpet_computeCallLight(); + case 1: + if (charaData[currentCharacter].strength < 8) { + charaData[currentCharacter].strengthCareMistakeTimer = + charaData[currentCharacter].initialStatsReductionTime; + charaData[currentCharacter].strength++; + charaData[currentCharacter].weight += 2; + screenKey = FEEDING_SCREEN; + submenuKey = PILL_ICON; + } else { + screenKey = REFUSING_SCREEN; + } + return; + break; + + default: + break; } + vpet_computeCallLight(); + } - draw_drawBackground(bg, 90, 90, 3); - menu_foodScreen_drawEntry(mainChara, spriteData, 0, FOOD_ICON, "Meat"); - menu_foodScreen_drawEntry(mainChara, spriteData, 1, PILL_ICON, "Pill"); - - draw_drawSprite(mainChara, 5, (arrowPosition * 34) + 5, spriteData, ARROW_ICON, 4); + draw_drawBackground(bg, 90, 90, 3); + menu_foodScreen_drawEntry(mainChara, spriteData, 0, FOOD_ICON, "Meat"); + menu_foodScreen_drawEntry(mainChara, spriteData, 1, PILL_ICON, "Pill"); - tft_drawBuffer(); + draw_drawSprite(mainChara, 5, (arrowPosition * 34) + 5, spriteData, + ARROW_ICON); + + tft_drawBuffer(); } -void menu_foodScreen_drawEntry( - TFT_eSprite &mainChara, struct SpriteData* spriteData, - uint8_t entryId, uint8_t spriteNumber, const char* textEntry -) { - tft_clearBuffer(mainChara, TFT_TRANSPARENT); - draw_drawSprite(mainChara, 45, (entryId * 34) + 5, spriteData, spriteNumber, 4); - tft_drawText(textEntry, 4, 80, (entryId * 34) + 5); +void menu_foodScreen_drawEntry(TFT_eSprite &mainChara, + struct SpriteData *spriteData, uint8_t entryId, + uint8_t spriteNumber, const char *textEntry) { + tft_clearBuffer(mainChara, TFT_TRANSPARENT); + draw_drawSprite(mainChara, 45, (entryId * 34) + 5, spriteData, spriteNumber); + tft_drawText(textEntry, 4, 80, (entryId * 34) + 5); } \ No newline at end of file diff --git a/src/menu/freeze_screen.cpp b/src/menu/freeze_screen.cpp new file mode 100644 index 0000000..593b3e2 --- /dev/null +++ b/src/menu/freeze_screen.cpp @@ -0,0 +1,34 @@ +#include "menu.h" +#include "buttons/buttons.h" +#include "draw/draw.h" +#include "display/display.h" + +void menu_drawFridgeScreen(TFT_eSprite &bg, TFT_eSprite& sprite, struct SpriteData* smallUiElements, struct SpriteData* bigUiElements) { + uint8_t pressedButtons = buttons_getPressedButtons(); + switch (pressedButtons) { + case K1_PRESSED: + screenKey = MENU_SCREEN; + menuKey = STATUS_SCREEN_MENU; + break; + + case K2_PRESSED: + screenKey = CLOCK_SCREEN; + break; + + default: + break; + } + + uint64_t currentTime = esp_timer_get_time(); + if (currentTime - lastUpdateTime > ANIMATION_THRESHOLD_TIME_US) { + draw_drawBackground(bg, 90, 90, 3); + + draw_drawSpriteCentered(sprite, bigUiElements, FRIDGE_DOOR); + + menu_uiOverlay(sprite, bigUiElements); + + lastUpdateTime = currentTime; + } + + tft_drawBuffer(); +} \ No newline at end of file diff --git a/src/menu/happy_screen.cpp b/src/menu/happy_screen.cpp index 544a895..4054de0 100644 --- a/src/menu/happy_screen.cpp +++ b/src/menu/happy_screen.cpp @@ -6,8 +6,8 @@ #include "animations/animations.h" void menu_drawHappyScreen( - TFT_eSprite &bg, TFT_eSprite &sprite, - struct SpriteData* spriteData, struct SpriteData* smallUiElements + TFT_eSprite& bg, TFT_eSprite &sprite, + struct SpriteData* spriteData, struct SpriteData* smallUiElements, const int returnScreen ) { uint8_t frameCounter = 0; @@ -15,11 +15,9 @@ void menu_drawHappyScreen( 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 + screenKey = returnScreen; // TODO: Change for while battling menuKey = STATUS_SCREEN; - vTaskResume(secondLoop); - return; } @@ -35,8 +33,8 @@ void menu_drawHappyScreen( tone(SPK_PIN, 1000, 50); tft_clearBuffer(sprite, TFT_TRANSPARENT); - draw_drawSprite(sprite, 18, 72, smallUiElements, FIREWORKS_ICON, 6); - draw_drawSprite(sprite, 174, 72, smallUiElements, FIREWORKS_ICON, 6); + draw_drawSprite(sprite, 18, 72, smallUiElements, FIREWORKS_ICON); + draw_drawSprite(sprite, 174, 72, smallUiElements, FIREWORKS_ICON); } frameCounter++; diff --git a/src/menu/idle_screen.cpp b/src/menu/idle_screen.cpp index 7c3c712..5f2da0f 100644 --- a/src/menu/idle_screen.cpp +++ b/src/menu/idle_screen.cpp @@ -13,7 +13,7 @@ void menu_drawIdleScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData switch (pressedButtons) { case K1_PRESSED: screenKey = MENU_SCREEN; - menuKey = 0; + menuKey = STATUS_SCREEN_MENU; break; case K2_PRESSED: diff --git a/src/menu/main_screen.cpp b/src/menu/main_screen.cpp index 23f9a1f..32c10ea 100644 --- a/src/menu/main_screen.cpp +++ b/src/menu/main_screen.cpp @@ -4,10 +4,14 @@ void menu_mainScreen() { printf("[MAINSCR] on main screen\n"); + lastUpdateTime = 0; - if (coldBoot) { + if (!timeSet) { screenKey = TITLE_SCREEN; return; + } else if (charaData[currentCharacter].frozen) { + screenKey = FROZEN_SCREEN; + return; } else if (!charaData[currentCharacter].hatched && !charaData[currentCharacter].hatching) { screenKey = EGG_EMPTY_SCREEN; return; diff --git a/src/menu/menu.h b/src/menu/menu.h index a735045..fdf1194 100644 --- a/src/menu/menu.h +++ b/src/menu/menu.h @@ -3,11 +3,12 @@ #include #include "defs/defs.h" +#include "defs/sprite_data.h" void menu_drawCurrentMenuOption(TFT_eSprite &bg, TFT_eSprite &icon, struct SpriteData* spriteData); void menu_drawClock(TFT_eSprite &bg); void menu_drawClockEdit(TFT_eSprite &bg); -void menu_drawTitle(TFT_eSprite &bg); +void menu_drawTitle(TFT_eSprite &bg, TFT_eSprite &composite); void menu_drawIdleScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* spriteData, struct SpriteData* bigUiElements, struct SpriteData* smallUiElements); void menu_offScreen(); void menu_statusScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* spriteData); @@ -38,7 +39,7 @@ uint8_t menu_poopOverlay(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData void menu_clearPoopScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* spriteData, struct SpriteData* bigUiElements, struct SpriteData* smallUiElements); void menu_drawHappyScreen( TFT_eSprite &bg, TFT_eSprite &sprite, - struct SpriteData* spriteData, struct SpriteData* smallUiElements + struct SpriteData* spriteData, struct SpriteData* smallUiElements, const int returnScreen = MAIN_SCREEN ); void menu_lineSwitcher(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* uiSmallSprite); void menu_eggHatchScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* uiBigSprite, struct SpriteData* uiSmallSprite); @@ -51,8 +52,15 @@ void menu_drawAngryScreen( TFT_eSprite &bg, TFT_eSprite &sprite, 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_sleepScreen_sleepAction(); void menu_sleepScreen_recalculateSleep(); +void menu_freezeScreen_alternateFreeze(); #endif \ No newline at end of file diff --git a/src/menu/menu_screen.cpp b/src/menu/menu_screen.cpp index ddcd11a..2d5192f 100644 --- a/src/menu/menu_screen.cpp +++ b/src/menu/menu_screen.cpp @@ -12,7 +12,7 @@ const int textXPos = 10; const int textYPos = 180; -void menu_drawCurrentMenuOption(TFT_eSprite &bg, TFT_eSprite &icon, struct SpriteData* spriteData) { +void menu_drawCurrentMenuOption(TFT_eSprite& bg, TFT_eSprite &icon, struct SpriteData* spriteData) { draw_drawBackground(bg, 90, 90, 3); uint8_t pressedButtons = buttons_getPressedButtons(); @@ -40,19 +40,23 @@ void menu_drawCurrentMenuOption(TFT_eSprite &bg, TFT_eSprite &icon, struct Sprit break; case FOOD_SCREEN_MENU: + if (charaData[currentCharacter].frozen) { break; } screenKey = FOOD_SCREEN; break; case SLEEP_SCREEN_MENU: + if (charaData[currentCharacter].frozen) { break; } menu_sleepScreen_sleepAction(); break; case TRAIN_SCREEN_MENU: + if (charaData[currentCharacter].frozen) { break; } screenKey = TRAINING_SCREEN_1; return; break; case POOP_SCREEN_MENU: + if (charaData[currentCharacter].frozen) { break; } menuKey = STATUS_SCREEN; screenKey = CLEAR_POOP_SCREEN; return; @@ -64,15 +68,20 @@ void menu_drawCurrentMenuOption(TFT_eSprite &bg, TFT_eSprite &icon, struct Sprit return; break; + case FREEZE_SCREEN_MENU: + menu_freezeScreen_alternateFreeze(); + return; + break; + default: break; } return; } - draw_drawSpriteCentered(icon, spriteData, menuKey % 9, 6); + draw_drawSpriteCentered(icon, spriteData, menuKey % 10); - switch(menuKey % 10) { + switch(menuKey % 11) { case STATUS_SCREEN_MENU: tft_drawCenteredText("Status", 4, textYPos); break; @@ -108,8 +117,12 @@ void menu_drawCurrentMenuOption(TFT_eSprite &bg, TFT_eSprite &icon, struct Sprit case SETTINGS_SCREEN_MENU: tft_drawCenteredText("Settings", 4, textYPos); break; - - case 9: + + case FREEZE_SCREEN_MENU: + tft_drawCenteredText("Freeze", 4, textYPos); + break; + + case 10: menuKey = STATUS_SCREEN_MENU; screenKey = MAIN_SCREEN; return; @@ -130,7 +143,7 @@ void menu_sleepScreen_sleepAction() { charaData[currentCharacter].sleepDisturbances++; - menuKey = STATUS_SCREEN; + menuKey = STATUS_SCREEN_MENU; screenKey = MAIN_SCREEN; } else { @@ -138,11 +151,18 @@ void menu_sleepScreen_sleepAction() { vpet_computeCallLight(); // Lo hago por cortesia, no me gusta - menuKey = STATUS_SCREEN; + menuKey = STATUS_SCREEN_MENU; screenKey = SLEEP_SCREEN; } } +void menu_freezeScreen_alternateFreeze() { + charaData[currentCharacter].frozen = !charaData[currentCharacter].frozen; + + menuKey = STATUS_SCREEN; + screenKey = MAIN_SCREEN; +} + void menu_sleepScreen_recalculateSleep() { uint32_t newSleepTime = (dayUnixTime + 3600) % SECONDS_IN_DAY; uint32_t newWakeUpTime = charaData[currentCharacter].wakeupTime + 3600; diff --git a/src/menu/poop_clean.cpp b/src/menu/poop_clean.cpp index 4ea3b82..fa472cc 100644 --- a/src/menu/poop_clean.cpp +++ b/src/menu/poop_clean.cpp @@ -36,15 +36,21 @@ void menu_clearPoopScreen( tft_clearBuffer(sprite, TFT_TRANSPARENT); - while (cleanerXPos > 18) { - draw_drawSprite(sprite, cleanerXPos, 72, smallUiElements, CLEANER_ICON, 6); - draw_drawSprite(sprite, cleanerXPos, 120, smallUiElements, CLEANER_ICON, 6); + while (cleanerXPos > 18 - 48) { + draw_drawBackgroundSection(bg, cleanerXPos + 6, 72, 48, 96); + + draw_drawSprite(sprite, cleanerXPos, 72, smallUiElements, CLEANER_ICON); + draw_drawSprite(sprite, cleanerXPos, 120, smallUiElements, CLEANER_ICON); + + draw_drawBackgroundSection(bg, 0, 72, 18, 96); + tft_drawBuffer(); + cleanerXPos -= 6; - delay(50); } screenKey = HAPPY_SCREEN; + menuKey = -1; charaData[currentCharacter].poopNumber = 0; return; diff --git a/src/menu/poop_overlay.cpp b/src/menu/poop_overlay.cpp index b9292fc..465b26c 100644 --- a/src/menu/poop_overlay.cpp +++ b/src/menu/poop_overlay.cpp @@ -13,7 +13,7 @@ uint8_t menu_poopOverlay(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData bool poopTop = false; for (int i = 0; i < charaData[currentCharacter].poopNumber; i++) { - draw_drawSprite(sprite, poopStartX, poopStartY - (48 * poopTop), smallUiElements, POOP_ICON, 6, poopFlip); + draw_drawSprite(sprite, poopStartX, poopStartY - (48 * poopTop), smallUiElements, POOP_ICON, poopFlip); poopStartX -= (i % 2) * 48; poopTop = !poopTop; } diff --git a/src/menu/poop_screen.cpp b/src/menu/poop_screen.cpp index fafb7f6..7d67451 100644 --- a/src/menu/poop_screen.cpp +++ b/src/menu/poop_screen.cpp @@ -22,7 +22,7 @@ void menu_poopScreen( draw_drawBackground(bg, 90, 90, 3); tft_clearBuffer(sprite, TFT_TRANSPARENT); - draw_drawSprite(sprite, 72 + (animationPosition * 6), 72, spriteData, 6, 6); + draw_drawSprite(sprite, 72 + (animationPosition * 6), 72, spriteData, 6); tft_clearBuffer(sprite, TFT_TRANSPARENT); menu_uiOverlay(sprite, bigUiElements); @@ -45,13 +45,13 @@ void menu_poopScreen( draw_drawBackground(bg, 90, 90, 3); tft_clearBuffer(sprite, TFT_TRANSPARENT); - draw_drawSprite(sprite, 174, 120, smallUiElements, POOP_ICON, 6); + 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, 6); + draw_drawSprite(sprite, 72, 72, spriteData, 7); animationFrame++; animationPosition = !animationPosition; @@ -69,7 +69,7 @@ void menu_poopScreen( screenKey = MAIN_SCREEN; } - menuKey = 0; + menuKey = -1; animationFrame = 0; animationPosition = 0; diff --git a/src/menu/sleeping_screen.cpp b/src/menu/sleeping_screen.cpp index 361c1e1..af012a2 100644 --- a/src/menu/sleeping_screen.cpp +++ b/src/menu/sleeping_screen.cpp @@ -42,10 +42,10 @@ void menu_sleepingScreen( animate_performSleepyAnimation(sprite, mainCharaData); tft_clearBuffer(sprite, TFT_TRANSPARENT); - draw_drawSprite(sprite, 72, 72, bigUiElements, BED_SPRITE, 6); + draw_drawSprite(sprite, 72, 72, bigUiElements, BED_SPRITE); tft_clearBuffer(sprite, TFT_TRANSPARENT); - draw_drawSprite(sprite, 172, 72, smallUIElements, ZZZ_ICON, 6); + draw_drawSprite(sprite, 172, 72, smallUIElements, ZZZ_ICON); tft_clearBuffer(sprite, TFT_TRANSPARENT); menu_uiOverlay(sprite, bigUiElements); diff --git a/src/menu/status_screen.cpp b/src/menu/status_screen.cpp index b7e993c..da72b4d 100644 --- a/src/menu/status_screen.cpp +++ b/src/menu/status_screen.cpp @@ -6,6 +6,8 @@ #include "display/display.h" #include "draw/draw.h" +#include + void menu_statusScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* spriteData) { tft_clearBuffer(sprite, TFT_TRANSPARENT); @@ -23,7 +25,7 @@ void menu_statusScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* menu_statusScreen_drawStat(sprite, spriteData, 10, 10, "Hunger", charaData[currentCharacter].hunger); menu_statusScreen_drawStat(sprite, spriteData, 10, 80, "Strength", charaData[currentCharacter].strength); - menu_statusScreen_drawStat(sprite, spriteData, 10, 150, "Effort", charaData[currentCharacter].effort); + menu_statusScreen_drawStat(sprite, spriteData, 10, 150, "Effort", floor(charaData[currentCharacter].effort / 4)); tft_drawBuffer(); } @@ -43,7 +45,6 @@ void menu_statusScreen_drawStat(TFT_eSprite &sprite, struct SpriteData* spriteDa y + 30, spriteData, icon, - 4, false ); } diff --git a/src/menu/title_screen.cpp b/src/menu/title_screen.cpp index 5e255f4..0b43e96 100644 --- a/src/menu/title_screen.cpp +++ b/src/menu/title_screen.cpp @@ -4,7 +4,7 @@ #include "defs/defs.h" #include "buttons/buttons.h" -void menu_drawTitle(TFT_eSprite &bg) { +void menu_drawTitle(TFT_eSprite &bg, TFT_eSprite &composite) { uint8_t pressedButtons = buttons_getPressedButtons(); if (pressedButtons == 8 || pressedButtons == 4) { screenKey = CLOCK_EDIT_SCREEN; @@ -18,4 +18,6 @@ void menu_drawTitle(TFT_eSprite &bg) { tft_drawCenteredText(VERSION, 2, 80); tft_drawBuffer(); + + delay(200); } \ No newline at end of file diff --git a/src/menu/training/training_screen1.cpp b/src/menu/training/training_screen1.cpp index d987e8c..9c4e7fd 100644 --- a/src/menu/training/training_screen1.cpp +++ b/src/menu/training/training_screen1.cpp @@ -14,7 +14,7 @@ void training_screenTraining1( vTaskSuspend(secondLoop); draw_drawBackground(bg, 90, 90, 3); - draw_drawSpriteCentered(sprite, mainCharaData, 11, 6); + draw_drawSpriteCentered(sprite, mainCharaData, 11); tone(SPK_PIN, 4100, 100); tone(SPK_PIN, 3500, 100); @@ -24,7 +24,7 @@ void training_screenTraining1( delay(500); draw_drawBackground(bg, 90, 90, 3); - draw_drawSpriteCentered(sprite, mainCharaData, 0, 6); + draw_drawSpriteCentered(sprite, mainCharaData, 0); tft_drawCenteredText("PUSH!!", 4, 190); tft_drawBuffer(); diff --git a/src/menu/training/training_screens.h b/src/menu/training/training_screens.h index 9f72247..234956e 100644 --- a/src/menu/training/training_screens.h +++ b/src/menu/training/training_screens.h @@ -7,5 +7,10 @@ void training_screenTraining1( TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* mainCharaData, struct SpriteData* attackSprites ); +void training_screenTraining2( + TFT_eSprite &bg, TFT_eSprite &sprite, + struct SpriteData* mainCharaData, struct SpriteData* attackSprites +); + #endif \ No newline at end of file diff --git a/src/menu/training_screen2.cpp b/src/menu/training_screen2.cpp new file mode 100644 index 0000000..a95aeb1 --- /dev/null +++ b/src/menu/training_screen2.cpp @@ -0,0 +1,96 @@ +#include "menu.h" +#include "vpet/training/training.h" +#include "defs/defs.h" +#include "defs/chara_data.h" +#include "draw/draw.h" +#include "display/display.h" +#include "buttons/buttons.h" + +void training_screenTraining2( + TFT_eSprite &bg, TFT_eSprite &sprite, + struct SpriteData* mainCharaData, struct SpriteData* attackSprites +) { + vTaskSuspend(secondLoop); + + draw_drawBackground(bg, 90, 90 ,3); + + // Player + draw_drawSprite(sprite, 174, 72, mainCharaData, 0, false); + draw_drawBackgroundSection(bg, 222, 72, 18, 96); + + // Opponent + draw_drawSprite(sprite, -30, 72, mainCharaData, 0, true); + draw_drawBackgroundSection(bg, 0, 72, 18, 96); + + tft_drawBuffer(); + + 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; + } + + if (currentTime - inactivityTimer > 3000000) { + screenKey = MAIN_SCREEN; + submenuKey = STATUS_SCREEN_MENU; + + vTaskResume(secondLoop); + + 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 + 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(); + + // Player attack + draw_drawSprite(sprite, 126, 72 + 48 * projectilePosition, attackSprites, POOP_ICON); + + // Opponent attack + draw_drawSprite(sprite, 66, 72 + 48 * randomPosition, attackSprites, FOOD_ICON); + + tft_drawBuffer(); + + if (projectilePosition != randomPosition) { + delay(500); + + 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); + } + } + } +} \ No newline at end of file diff --git a/src/menu/ui_overlay.cpp b/src/menu/ui_overlay.cpp index 637f42a..0a051b5 100644 --- a/src/menu/ui_overlay.cpp +++ b/src/menu/ui_overlay.cpp @@ -1,22 +1,23 @@ -#include "menu.h" -#include "draw/draw.h" -#include "display/display.h" #include "defs/chara_data.h" #include "defs/screen_defs.h" +#include "display/display.h" +#include "draw/draw.h" +#include "menu.h" -void menu_uiOverlay(TFT_eSprite &charSprite, struct SpriteData* uiElements) { - char hourBuffer[6]; +void menu_uiOverlay(TFT_eSprite &charSprite, struct SpriteData *uiElements) { + char hourBuffer[6]; - snprintf(hourBuffer, 6, "%02d:%02d", timeInfo.tm_hour, timeInfo.tm_min); + snprintf(hourBuffer, 6, "%02d:%02d", timeInfo.tm_hour, timeInfo.tm_min); - composite1.fillRect(0, 0, 240, 24, TFT_BLACK); - tft_drawText(hourBuffer, 2, 4, 4, TFT_WHITE); - - snprintf(hourBuffer, 6, "%05d", stepCounter); - tft_drawText(hourBuffer, 2, 176, 4, TFT_WHITE); - - if (charaData[currentCharacter].careMistakeCallLight) { - tft_clearBuffer(charSprite, TFT_TRANSPARENT); - draw_drawSprite(charSprite, 192, 192, uiElements, CARE_MISTAKE_CALL_LIGHT, 2); - } + composite.fillRect(0, 0, 240, 24, TFT_BLACK); + tft_drawText(hourBuffer, 2, 4, 4, TFT_WHITE); + + snprintf(hourBuffer, 6, "%05d", stepCounter); + tft_drawText(hourBuffer, 2, 176, 4, TFT_WHITE); + + if (charaData[currentCharacter].careMistakeCallLight) { + tft_clearBuffer(charSprite, TFT_TRANSPARENT); + // draw_drawSprite(charSprite, 192, 192, uiElements, + // CARE_MISTAKE_CALL_LIGHT, 2); + } } \ No newline at end of file diff --git a/src/storage/storage.cpp b/src/storage/storage.cpp index 7ceb89b..c493a6f 100644 --- a/src/storage/storage.cpp +++ b/src/storage/storage.cpp @@ -1,9 +1,17 @@ #include "storage.h" #include "memory/memory.h" +#include "defs/defs.h" +#include "defs/chara_data.h" #include "defs/sprite_data.h" +#include "defs/screen_defs.h" +#include "TFT_eSPI.h" const char* TAG_S = "[STORAGE]"; +// All sprites are upscaled by this factor at load time so draw_drawSprite +// can skip the scaling loop entirely at runtime. +#define SPRITE_SCALE 6 + void storage_init() { if (!SPIFFS.begin(true)) { printf("%s Failed to mount file system\n", TAG_S); @@ -20,56 +28,93 @@ void storage_readFile(const char* path, struct SpriteData* spriteData) { return; } - size_t bytesRead = 0; - size_t fileSize = file.size(); - uint8_t width, height, spriteNumber; - - bytesRead += file.read(&width, 1); - bytesRead += file.read(&height, 1); - bytesRead += file.read(&spriteNumber, 1); + + file.read(&width, 1); + file.read(&height, 1); + file.read(&spriteNumber, 1); if (spriteData->spriteData != NULL) { memory_free(spriteData); - } - - spriteData->spriteWidth = width; - spriteData->spriteHeight = height; - spriteData->spriteNumber = spriteNumber; - - spriteData->spriteData = memory_allocate(spriteData->spriteNumber, spriteData->spriteWidth, spriteData->spriteHeight); + } + + const uint8_t scaledW = width * SPRITE_SCALE; + const uint8_t scaledH = height * SPRITE_SCALE; + + // Allocate scaled buffers in PSRAM (ps_malloc falls back to regular heap + // automatically if PSRAM is not available for a given allocation). + 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; + } + } + + // Temporary single-row scratch buffer in internal RAM for reading from file + 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\n", - TAG_S, spriteData->spriteWidth, spriteData->spriteHeight, spriteData->spriteNumber + "%s Read header: width=%d, height=%d, numSprites=%d -> scaled to %dx%d\n", + TAG_S, width, height, spriteNumber, scaledW, scaledH ); - fileSize = (fileSize - 3) / sizeof(uint16_t); + for (int sprN = 0; sprN < spriteNumber; sprN++) { + uint16_t* dst = scaled[sprN]; - size_t bufferSize = spriteData->spriteNumber * spriteData->spriteWidth * spriteData->spriteHeight; + for (int srcY = 0; srcY < height; srcY++) { + // --- Read one source row, byte-swapping as we go --- + for (int srcX = 0; srcX < width; srcX++) { + uint8_t hi, lo; + file.read(&hi, 1); + file.read(&lo, 1); + // File is big-endian RGB565; TFT_eSPI expects little-endian + rowBuf[srcX] = (lo << 8) | hi; + } - uint8_t highByte; - uint8_t lowByte; + // --- Scale row vertically (repeat SPRITE_SCALE times) --- + for (int dy = 0; dy < SPRITE_SCALE; dy++) { + uint16_t* dstRow = dst + (srcY * SPRITE_SCALE + dy) * scaledW; - for (int sprN = 0; sprN < spriteData->spriteNumber; sprN++) { - for (int i = 0; i < spriteData->spriteWidth * spriteData->spriteHeight; i++) { - bytesRead += file.read(&highByte, 1); - bytesRead += file.read(&lowByte, 1); - - uint16_t pixel = (highByte << 8) | lowByte; - - if (i < bufferSize) { - (spriteData->spriteData)[sprN][i] = pixel; - } else { - printf("%s Buffer overflow, skipping pixel\n", TAG_S); - break; + // --- Scale each pixel horizontally --- + 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; + } + } } } } - printf("%s Read %zu bytes from file %s\n", TAG_S, bytesRead, path); - + free(rowBuf); file.close(); + + // Store scaled dimensions so the rest of the code sees the final size + 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) { @@ -79,40 +124,196 @@ void storage_initBackground(const char* path, TFT_eSprite& bg) { return; } - size_t bytesRead = 0; + uint8_t width, height; + file.read(&width, 1); + file.read(&height, 1); - size_t fileSize = file.size(); + size_t pixelCount = width * height; - uint8_t width; - uint8_t height; - - bytesRead += file.read(&width, 1); - bytesRead += file.read(&height, 1); - - printf("%s Read header: width=%d, height=%d\n", TAG_S, width, height); - - fileSize = (fileSize - 2) / sizeof(uint16_t); + printf("%s width=%d height=%d pixels=%zu\n", TAG_S, width, height, pixelCount); bg.createSprite(width, height); - for(int i = 0; i < width * height; i++) { - uint8_t highByte; - uint8_t lowByte; + uint16_t* bgBuf = (uint16_t*) bg.getPointer(); - bytesRead += file.read(&highByte, 1); - bytesRead += file.read(&lowByte, 1); + for (size_t i = 0; i < pixelCount; i++) { + uint8_t hi, lo; + file.read(&lo, 1); + file.read(&hi, 1); + // Store directly into sprite buffer – no byte swap needed here since + // background pixels are not going through the draw_drawSprite path. + bgBuf[i] = (hi << 8) | lo; + } - uint16_t pixel = (highByte << 8) | lowByte; + file.close(); +} - if (i < fileSize) { - bg.drawPixel(i % width, i / width, pixel); - } else { - printf("%s Buffer overflow, skipping pixel\n", TAG_S); - break; +void storage_saveState() { + File file; + + file = SPIFFS.open("/save.bin", "w"); + + if (!file) { + printf("%s Cannot save: cannot open save file.\n", TAG_S); + return; + } + + file.write( + (uint8_t*) charaData, + sizeof(struct CharacterData) * CHARA_COUNT_IN_DEVICE + ); + + printf("%s Saved current character data.\n", TAG_S); + + for (int i = 0; i < CHARA_COUNT_IN_DEVICE; i++) { + printf("%s Saving line data %i\n", TAG_S, i); + + uint8_t lineUsed = (currentLine[i] != NULL); + file.write(lineUsed); + + if (lineUsed) { + file.write(currentLine[i]->id); + file.write((uint8_t*) &(currentLine[i]->hatchTime), sizeof(uint16_t)); + file.write((uint8_t*) currentLine[i]->name, 16); + file.write(currentLine[i]->charaNumber); + + printf("%s Done saving static line %i\n", TAG_S, i); + + uint8_t hasCharacters = (currentLine[i]->characters != NULL); + file.write(hasCharacters); + + printf("%s hasCharacters=%i, characters=%i, charaNumber=%i\n", + TAG_S, hasCharacters, currentLine[i]->characters, currentLine[i]->charaNumber); + + if (hasCharacters) { + file.write( + (uint8_t*) currentLine[i]->characters, + sizeof(LineChara_t) * currentLine[i]->charaNumber + ); + } + + printf("%s Done saving line data for %i\n", TAG_S, i); + } + } + + for (int i = 0; i < CHARA_COUNT_IN_DEVICE; i++) { + printf("%s Saving care data %i\n", TAG_S, i); + + uint8_t careDataUsed = currentLineCareInstr[i] != NULL; + file.write(careDataUsed); + + if (careDataUsed) { + file.write(currentLineCareInstr[i]->lineId); + file.write(currentLineCareInstr[i]->numCareMistakesData); + + printf("%s Done saving static care data %i\n", TAG_S, i); + + uint8_t hasCareData = (currentLineCareInstr[i]->careMistakeData != NULL); + file.write(hasCareData); + + printf("%s hasCharacters=%i, characters=%i, charaNumber=%i\n", + TAG_S, hasCareData, currentLineCareInstr[i]->careMistakeData, currentLineCareInstr[i]->numCareMistakesData); + + if (hasCareData) { + file.write( + (uint8_t*) currentLineCareInstr[i]->careMistakeData, + sizeof(CareMistakes_t) * currentLineCareInstr[i]->numCareMistakesData + ); + } + + printf("%s Done saving care data for %i\n", TAG_S, i); + } + + } + + file.write(currentCharacter); + + file.close(); + + printf("%s Save completed!\n", TAG_S); +} + +void storage_loadState() { + File file; + + if (!SPIFFS.exists("/save.bin")) { + printf("%s Cannot load: File does not exist.\n", TAG_S); + return; + } + + file = SPIFFS.open("/save.bin", "r"); + + if (!file) { + printf("%s Cannot save: cannot open save file.\n", TAG_S); + return; + } + + file.read((uint8_t*) charaData, sizeof(struct CharacterData) * CHARA_COUNT_IN_DEVICE); + + for (int i = 0; i < CHARA_COUNT_IN_DEVICE; i++) { + uint8_t currentLineUsed = file.read(); + + if (currentLineUsed) { + currentLine[i] = (Line_t*) calloc(1, sizeof(Line_t)); + + currentLine[i]->id = file.read(); + file.read((uint8_t*) &(currentLine[i]->hatchTime), sizeof(uint16_t)); + file.read((uint8_t*) currentLine[i]->name, 16); + currentLine[i]->charaNumber = file.read(); + + uint8_t hasCharacters = file.read(); + + if (hasCharacters) { + if (currentLine[i]->characters != NULL) { + free(currentLine[i]->characters); + } + + currentLine[i]->characters = (LineChara_t*) malloc(sizeof(LineChara_t) * currentLine[i]->charaNumber); + file.read( + (uint8_t*) currentLine[i]->characters, + sizeof(LineChara_t) * currentLine[i]->charaNumber + ); + } else { + currentLine[i]->characters = NULL; + } + } + + } + + for (int i = 0; i < CHARA_COUNT_IN_DEVICE; i++) { + uint8_t currentLineUsed = file.read(); + + if (currentLineUsed) { + currentLineCareInstr[i] = (LineCare_t*) calloc(1, sizeof(LineCare_t)); + + currentLineCareInstr[i]->lineId = file.read(); + currentLineCareInstr[i]->numCareMistakesData = file.read(); + + uint8_t hasCareData = file.read(); + if (hasCareData) { + if (currentLineCareInstr[i]->careMistakeData != NULL) { + free(currentLineCareInstr[i]->careMistakeData); + } + + currentLineCareInstr[i]->careMistakeData = (CareMistakes_t*) malloc(sizeof(CareMistakes_t) * currentLineCareInstr[i]->numCareMistakesData); + file.read( + (uint8_t*) currentLineCareInstr[i]->careMistakeData, + sizeof(CareMistakes_t) * currentLineCareInstr[i]->numCareMistakesData + ); + } else { + currentLineCareInstr[i]->careMistakeData = NULL; + } } } - printf("%s Read %zu bytes from file %s\n", TAG_S, bytesRead, path); + currentCharacter = file.read(); file.close(); + + char spriteFileName[30]; + snprintf(spriteFileName, 30, "/chara/%02x.bin", charaData[currentCharacter].idChara); + + storage_readFile(spriteFileName, &mainCharacterSprites); + + printf("%s Load completed!\n", TAG_S); } \ No newline at end of file diff --git a/src/storage/storage.h b/src/storage/storage.h index 512538c..7c73ce6 100644 --- a/src/storage/storage.h +++ b/src/storage/storage.h @@ -9,6 +9,9 @@ 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 char* path, TFT_eSprite &bg); + +void storage_saveState(); +void storage_loadState(); #endif \ No newline at end of file diff --git a/src/vpet/evolution/evolution.cpp b/src/vpet/evolution/evolution.cpp index 9cc61af..a5ac55b 100644 --- a/src/vpet/evolution/evolution.cpp +++ b/src/vpet/evolution/evolution.cpp @@ -86,4 +86,6 @@ void change_onChangeComplete() { snprintf(spriteFileName, 30, "/chara/%02x.bin", charaData[currentCharacter].idChara); storage_readFile(spriteFileName, &mainCharacterSprites); + + storage_saveState(); } \ No newline at end of file diff --git a/src/vpet/lines/get_available_lines.cpp b/src/vpet/lines/get_available_lines.cpp index c362667..a129e8f 100644 --- a/src/vpet/lines/get_available_lines.cpp +++ b/src/vpet/lines/get_available_lines.cpp @@ -2,7 +2,8 @@ #include "memory/memory.h" #include "defs/defs.h" -#include "SPIFFS.h" +#include +#include const char lineHeader[5] = "NPET"; const uint8_t headerSize = 4; @@ -12,8 +13,8 @@ void lines_getAvailableLines() { return; } - File root = SPIFFS.open("/lines"); - File lineFile = root.openNextFile(); + fs::File root = SPIFFS.open("/lines"); + fs::File lineFile = root.openNextFile(); uint8_t allocCount = 0; char header[5]; diff --git a/src/vpet/lines/get_care_mistakes.cpp b/src/vpet/lines/get_care_mistakes.cpp index 92e4dd2..84443d6 100644 --- a/src/vpet/lines/get_care_mistakes.cpp +++ b/src/vpet/lines/get_care_mistakes.cpp @@ -2,19 +2,20 @@ #include "defs/file_chara.h" #include "defs/defs.h" -#include "SPIFFS.h" +#include +#include void lines_getLineCareMistakes(const char* fileName) { char careMistakesPath[strlen(fileName) + 8]; snprintf(careMistakesPath, strlen(fileName) + 8, "/care/%s", fileName); - File careMistakesFile = SPIFFS.open(careMistakesPath); + fs::File careMistakesFile = SPIFFS.open(careMistakesPath); uint8_t bytesRead = 0; LineCare_t* careMistakesData = (LineCare_t*) malloc(sizeof(LineCare_t)); - careMistakesFile.seek(4, SeekCur); + careMistakesFile.seek(4, fs::SeekCur); bytesRead += careMistakesFile.read(&careMistakesData->lineId, 1); bytesRead += careMistakesFile.read(&careMistakesData->numCareMistakesData, 1); diff --git a/src/vpet/lines/get_single_line.cpp b/src/vpet/lines/get_single_line.cpp index e99af4a..5f02e01 100644 --- a/src/vpet/lines/get_single_line.cpp +++ b/src/vpet/lines/get_single_line.cpp @@ -2,13 +2,14 @@ #include "memory/memory.h" #include "defs/defs.h" +#include #include void lines_getSingleLine(const char* fileName) { char fullPath[8 + strlen(fileName)]; snprintf(fullPath, 20, "/lines/%s", fileName); - File lineFile = SPIFFS.open(fullPath); + fs::File lineFile = SPIFFS.open(fullPath); struct Line_t* selectedLine = (struct Line_t*) malloc(sizeof(struct Line_t)); if (selectedLine == NULL) { @@ -17,7 +18,7 @@ void lines_getSingleLine(const char* fileName) { uint8_t buffer[4]; - lineFile.seek(4, SeekCur); + lineFile.seek(4, fs::SeekCur); uint8_t bytesRead = lineFile.read(&selectedLine->id, 1); bytesRead += lineFile.readBytes(selectedLine->name, 16); @@ -40,7 +41,7 @@ void lines_getSingleLine(const char* fileName) { currentEgg = selectedEgg; } -void lines_getSingleEggSprites(File &lineFile, Egg_t* 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()); diff --git a/src/vpet/lines/init_lines.cpp b/src/vpet/lines/init_lines.cpp index 6abe684..4166786 100644 --- a/src/vpet/lines/init_lines.cpp +++ b/src/vpet/lines/init_lines.cpp @@ -1,12 +1,14 @@ #include "lines.h" #include "defs/defs.h" #include "defs/file_chara.h" +#include "defs/chara_data.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); + charaData = (struct CharacterData*) calloc(CHARA_COUNT_IN_DEVICE, sizeof(struct CharacterData)); + currentLineCareInstr = (LineCare_t**) calloc(CHARA_COUNT_IN_DEVICE, sizeof(LineCare_t*)); + currentLine = (Line_t**) calloc(CHARA_COUNT_IN_DEVICE, sizeof(Line_t*)); } \ No newline at end of file diff --git a/src/vpet/training/training.h b/src/vpet/training/training.h index 81a2129..5915e31 100644 --- a/src/vpet/training/training.h +++ b/src/vpet/training/training.h @@ -2,6 +2,7 @@ #define TRAINING_H #include +#include "defs/sprite_data.h" void training_displayTrainingResult( TFT_eSprite &bg, TFT_eSprite &sprite, diff --git a/src/vpet/training/training_resultScreen.cpp b/src/vpet/training/training_resultScreen.cpp index 03cbf80..ec4ce52 100644 --- a/src/vpet/training/training_resultScreen.cpp +++ b/src/vpet/training/training_resultScreen.cpp @@ -2,6 +2,7 @@ #include "draw/draw.h" #include "defs/defs.h" #include "defs/chara_data.h" +#include "defs/sprite_data.h" #include "display/display.h" #define NUM_ROUNDS 5 @@ -75,13 +76,17 @@ void training_displayTrainingResult( break; } + draw_drawBackground(bg, 90, 90, 3); for (int i = 0; i < NUM_ROUNDS; i++) { training_trainingAttackSounds(); - for (int j = 78; j >= -48; j -= 3) { - draw_drawBackground(bg, 90, 90, 3); - draw_drawSprite(sprite, 126, 72, mainCharaData, 11, 6); - draw_drawAttacks(sprite, attackSprites, j, 72, pattern[i], charaData[currentCharacter].spriteAttackId, 6); + + for (int j = 78; j >= -48; j -= 6) { + draw_drawSprite(sprite, 126, 72, mainCharaData, 11); + + draw_drawAttacks(bg, sprite, attackSprites, j, 72, pattern[i], charaData[currentCharacter].spriteAttackId); + + draw_drawBackgroundSection(bg, 0, 72, 18, 96); tft_drawBuffer(); } diff --git a/src/vpet/vpet/vpet.cpp b/src/vpet/vpet/vpet.cpp index 3fcf573..b2c407d 100644 --- a/src/vpet/vpet/vpet.cpp +++ b/src/vpet/vpet/vpet.cpp @@ -167,7 +167,12 @@ void vpet_evalHungerTimer() { charaData[currentCharacter].hungerCareMistakeTimer <= 0 && charaData[currentCharacter].hunger > 0 ) { + #ifndef DEBUG charaData[currentCharacter].hunger--; + #else + charaData[currentCharacter].hunger -= 60; + #endif + if (charaData[currentCharacter].hunger > 0) { charaData[currentCharacter].hungerCareMistakeTimer = charaData[currentCharacter].initialStatsReductionTime; @@ -202,7 +207,12 @@ void vpet_evalStrengthTimer() { charaData[currentCharacter].strengthCareMistakeTimer <= 0 && charaData[currentCharacter].strength > 0 ) { + #ifndef DEBUG charaData[currentCharacter].strength--; + #else + charaData[currentCharacter].strength -= 60; + #endif + if (charaData[currentCharacter].strength > 0) { charaData[currentCharacter].strengthCareMistakeTimer = charaData[currentCharacter].initialStatsReductionTime; } else { @@ -226,7 +236,11 @@ void vpet_evalStrengthTimer() { void vpet_evalChangeTimer(uint8_t diff_sec) { if (charaData[currentCharacter].changeTimerLeft > 0) { + #ifndef DEBUG charaData[currentCharacter].changeTimerLeft -= diff_sec; + #else + charaData[currentCharacter].changeTimerLeft -= 600; + #endif } if (charaData[currentCharacter].changeTimerLeft <= 0) { @@ -245,7 +259,7 @@ void IRAM_ATTR onActionTimerDelta() { } void vpet_runVpetTasks() { - if (runVpetTasks) { + if (runVpetTasks && !charaData[currentCharacter].frozen) { uint64_t currentEvaluationTime = esp_timer_get_time(); uint64_t deltaUs = currentEvaluationTime - vpetLastEvaluationTime; diff --git a/test/README b/test/README deleted file mode 100644 index 9b1e87b..0000000 --- a/test/README +++ /dev/null @@ -1,11 +0,0 @@ - -This directory is intended for PlatformIO Test Runner and project tests. - -Unit Testing is a software testing method by which individual units of -source code, sets of one or more MCU program modules together with associated -control data, usage procedures, and operating procedures, are tested to -determine whether they are fit for use. Unit testing finds problems early -in the development cycle. - -More information about PlatformIO Unit Testing: -- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html