Compare commits

...

3 Commits

Author SHA1 Message Date
ce23c44077 Mierda 2026-05-27 14:38:10 +02:00
595faaf946 Merge branch 'main' of github.com:nacabaro/nacapet 2026-05-27 14:32:43 +02:00
570d7f8bc4 Let's get this up to date, i'll update the readme later on 2026-05-27 14:30:33 +02:00
53 changed files with 912 additions and 897 deletions

1
.gitignore vendored
View File

@ -8,6 +8,7 @@
*.line *.line
*.egg *.egg
*.cm *.cm
*.png
__pycache__/ __pycache__/
venv/ venv/
sprites/ sprites/

View File

@ -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 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_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 TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue
//#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_WIDTH 240 // ST7789 240 x 240 and 240 x 320 #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 240 // ST7789 240 x 240
// #define TFT_HEIGHT 320 // ST7789 240 x 320 #define TFT_BL 1 // LED back-light control pin
// #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_BACKLIGHT_ON HIGH // Level to turn ON back-light (HIGH or LOW) #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. #define TFT_SPI_PORT SPI2_HOST
// 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 SPI_FREQUENCY 27000000
// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### #define TFT_USE_DMA false
// 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 LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #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 #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_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 #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 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 #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 #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

View File

@ -8,12 +8,40 @@
; Please visit documentation for the other options and examples ; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html ; 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 platform = espressif32
board = esp32dev board = esp32-s3-devkitc-1
framework = arduino framework = arduino
monitor_speed = 115200
monitor_port = /dev/ttyUSB0 ; Flash and PSRAM settings for 4MB Flash / 2MB PSRAM (Quad SPI)
monitor_filters = esp32_exception_decoder 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 lib_deps = TFT_eSPI, fbiego/ESP32Time@^2.0.6, electroniccats/MPU6050@^1.4.3
build_flags = -Wl,-Map,output.map

View File

@ -11,11 +11,10 @@ int currentAnimationFrame = 0;
void animate_performAnimation(TFT_eSprite &spr, struct SpriteData* spriteData, uint8_t offsetX) { void animate_performAnimation(TFT_eSprite &spr, struct SpriteData* spriteData, uint8_t offsetX) {
draw_drawSprite( draw_drawSprite(
spr, spr,
animationPositions[currentAnimationFrame] - offsetX, animationPositions[currentAnimationFrame] - offsetX,
spriteHeightOnScreen, spriteHeightOnScreen,
spriteData, spriteData,
animationFrames[currentAnimationFrame], animationFrames[currentAnimationFrame],
6,
animationFlipSprites[currentAnimationFrame] animationFlipSprites[currentAnimationFrame]
); );
@ -26,14 +25,12 @@ void animate_performAttentionAnimation(TFT_eSprite &spr, struct SpriteData* spri
currentAnimationFrame = (currentAnimationFrame + 1) % numFramesAngry; currentAnimationFrame = (currentAnimationFrame + 1) % numFramesAngry;
draw_drawSprite( draw_drawSprite(
spr, spr,
spriteHeightOnScreen, spriteHeightOnScreen,
spriteHeightOnScreen, spriteHeightOnScreen,
spriteData, spriteData,
angryAnimationFrames[currentAnimationFrame], angryAnimationFrames[currentAnimationFrame],
6,
animationFlipSprites[currentAnimationFrame] animationFlipSprites[currentAnimationFrame]
); );
} }
void animate_performEatingAnimation(TFT_eSprite &spr, struct SpriteData* spriteData) { void animate_performEatingAnimation(TFT_eSprite &spr, struct SpriteData* spriteData) {
@ -44,7 +41,6 @@ void animate_performEatingAnimation(TFT_eSprite &spr, struct SpriteData* spriteD
spriteHeightOnScreen, spriteHeightOnScreen,
spriteData, spriteData,
eatingAnimationFrames[currentAnimationFrame], eatingAnimationFrames[currentAnimationFrame],
6,
false false
); );
} }
@ -57,7 +53,6 @@ void animate_performRefuseAnimation(TFT_eSprite &spr, struct SpriteData* spriteD
spriteHeightOnScreen, spriteHeightOnScreen,
spriteData, spriteData,
refuseAnimationFrames[currentAnimationFrame], refuseAnimationFrames[currentAnimationFrame],
6,
refuseAnimationFlips[currentAnimationFrame] refuseAnimationFlips[currentAnimationFrame]
); );
} }
@ -70,7 +65,6 @@ void animate_performSleepyAnimation(TFT_eSprite &spr, struct SpriteData* spriteD
spriteHeightOnScreen, spriteHeightOnScreen,
spriteData, spriteData,
sleepyAnimationFrames[currentAnimationFrame], sleepyAnimationFrames[currentAnimationFrame],
6,
false false
); );
} }
@ -83,7 +77,6 @@ void animate_performHappyAnimation(TFT_eSprite &spr, struct SpriteData* spriteDa
spriteHeightOnScreen, spriteHeightOnScreen,
spriteData, spriteData,
happyAnimationFrames[currentAnimationFrame], happyAnimationFrames[currentAnimationFrame],
6,
false false
); );
} }
@ -97,7 +90,6 @@ void animate_performAngryAnimation(TFT_eSprite &spr, struct SpriteData* spriteDa
spriteHeightOnScreen, spriteHeightOnScreen,
spriteData, spriteData,
angryAnimationFrames[currentAnimationFrame], angryAnimationFrames[currentAnimationFrame],
6,
false false
); );
} }
@ -110,7 +102,6 @@ void animate_performHatchingAnimation(TFT_eSprite &spr, struct SpriteData* sprit
spriteHeightOnScreen, spriteHeightOnScreen,
spriteData, spriteData,
0, 0,
6,
false false
); );
} }

View File

@ -33,10 +33,10 @@ uint8_t buttons_getPressedButtons() {
bool k4_current = digitalRead(K4_PIN); bool k4_current = digitalRead(K4_PIN);
uint8_t retV = ( uint8_t retV = (
(k1_prev == HIGH && k1_current == LOW) << 3 | (k1_prev == LOW && k1_current == HIGH) << 3 |
(k2_prev == HIGH && k2_current == LOW) << 2 | (k2_prev == LOW && k2_current == HIGH) << 2 |
(k3_prev == HIGH && k3_current == LOW) << 1 | (k3_prev == LOW && k3_current == HIGH) << 1 |
(k4_prev == HIGH && k4_current == LOW) (k4_prev == LOW && k4_current == HIGH)
); );
if (retV != 0) { if (retV != 0) {

View File

@ -1,6 +1,8 @@
#ifndef BUTTONS_H #ifndef BUTTONS_H
#define BUTTONS_H #define BUTTONS_H
#include <Arduino.h>
uint8_t buttons_getPressedButtons(); uint8_t buttons_getPressedButtons();
void buttons_checkInactivity(); void buttons_checkInactivity();

View File

@ -46,7 +46,8 @@ struct CharacterData {
bool asleep = false; bool asleep = false;
bool injured = false; bool injured = false;
bool dead = 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 // Usado para recalcular cuantos dias van a tardar en recuperarse, max 5 pls
uint8_t dynamicSleepDists; uint8_t dynamicSleepDists;

View File

@ -11,24 +11,38 @@
#define VERSION "Alpha v0.1" #define VERSION "Alpha v0.1"
// SCREEN PINOUT // SCREEN PINOUT
#define SCL_PIN 34
#define SDA_PIN 35
#define RST_PIN 32
#define BL_PIN 25
// BUTTONS PINOUT // BUTTONS PINOUT
#define K1_PIN 35 #ifdef DEV_UNIT
#define K2_PIN 13
#define K3_PIN 33 #define K1_PIN 1
#define K4_PIN 14 #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 // SPEAKER PINOUT
#define SPK_PIN 21 #define SPK_PIN 7
// MPU6050 PINOUT // MPU6050 PINOUT
#define MPU_SCL_PIN 4 #define MPU_SCL_PIN 9
#define MPU_SDA_PIN 16 #define MPU_SDA_PIN 8
#define MPU_INT_PIN 12
// SPECIAL SCREEN THAT OPENS WHEN TIMERS ARE DONE // SPECIAL SCREEN THAT OPENS WHEN TIMERS ARE DONE
// RECEIVES AN EXTRA PARAMETER (INTERRUPTKEY) // RECEIVES AN EXTRA PARAMETER (INTERRUPTKEY)
@ -59,6 +73,7 @@
#define SLEEP_SCREEN_MENU 6 #define SLEEP_SCREEN_MENU 6
#define CHANGE_SCREEN_MENU 7 #define CHANGE_SCREEN_MENU 7
#define SETTINGS_SCREEN_MENU 8 #define SETTINGS_SCREEN_MENU 8
#define FREEZE_SCREEN_MENU 9
// SCREENS THAT OPEN AFTER CLICKING ON A MENU ENTRY // SCREENS THAT OPEN AFTER CLICKING ON A MENU ENTRY
#define STATUS_SCREEN 10 #define STATUS_SCREEN 10
@ -80,9 +95,11 @@
#define MEDICAL_SCREEN_ICON 5 #define MEDICAL_SCREEN_ICON 5
#define SLEEP_SCREEN_ICON 6 #define SLEEP_SCREEN_ICON 6
#define SETTINGS_SCREEN_ICON 8 #define SETTINGS_SCREEN_ICON 8
#define CARE_MISTAKE_CALL_LIGHT 9 #define FRIDGE_DOOR 9
#define BED_SPRITE 10 #define BED_SPRITE 10
#define EMPTY_EGG 11 #define EMPTY_EGG 11
#define CARE_MISTAKE_CALL_LIGHT 12
// SCREENS // SCREENS
#define OFF_SCREEN -1 #define OFF_SCREEN -1
@ -98,6 +115,7 @@
#define FEEDING_SCREEN 20 #define FEEDING_SCREEN 20
#define REFUSING_SCREEN 21 #define REFUSING_SCREEN 21
#define SLEEPY_SCREEN 22 #define SLEEPY_SCREEN 22
#define FROZEN_SCREEN 28
#define CARE_MISTAKE_SCREEN 23 #define CARE_MISTAKE_SCREEN 23
#define POOPING_SCREEN 24 #define POOPING_SCREEN 24
#define HAPPY_SCREEN 25 #define HAPPY_SCREEN 25
@ -163,7 +181,6 @@ extern uint64_t lastPressedButtonTime;
extern uint64_t lastUpdateTime; extern uint64_t lastUpdateTime;
extern uint64_t lastBeepTime; extern uint64_t lastBeepTime;
extern struct CharacterData* charaData;
extern struct tm timeInfo; extern struct tm timeInfo;
extern uint32_t dayUnixTime; extern uint32_t dayUnixTime;
@ -179,16 +196,18 @@ extern uint8_t beepCounter;
extern uint16_t stepCounter; extern uint16_t stepCounter;
extern bool coldBoot; extern bool timeSet;
extern uint8_t eggNumber; extern uint8_t eggNumber;
extern Egg_t* eggSelection; extern Egg_t* eggSelection;
extern uint8_t currentCharacter; extern uint8_t currentCharacter;
// Rescatar
extern Egg_t* currentEgg; extern Egg_t* currentEgg;
extern LineCare_t** currentLineCareInstr; extern LineCare_t** currentLineCareInstr;
extern Line_t** currentLine; extern Line_t** currentLine;
extern struct CharacterData* charaData;
extern struct SpriteData mainCharacterSprites; extern struct SpriteData mainCharacterSprites;

View File

@ -4,8 +4,7 @@
#include <TFT_eSPI.h> #include <TFT_eSPI.h>
extern TFT_eSPI tft; extern TFT_eSPI tft;
extern TFT_eSprite composite1; extern TFT_eSprite composite;
extern TFT_eSprite composite2;
// ALTAMENTE TEMPORAL // ALTAMENTE TEMPORAL
extern int xPos; extern int xPos;

View File

@ -10,75 +10,61 @@ static const int BUF_H = 120;
void tft_initDisplay(TFT_eSPI &tft, uint16_t color) { void tft_initDisplay(TFT_eSPI &tft, uint16_t color) {
tft.begin(); #ifdef ANDREW_UNIT
tft.initDMA(); pinMode(BL_PIN, OUTPUT);
digitalWrite(BL_PIN, HIGH);
#endif
tft.init();
tft.setRotation(0); tft.setRotation(0);
tft.fillScreen(TFT_RED); tft.fillScreen(color);
} }
void tft_initScreenBuffer(uint16_t color) { void tft_initScreenBuffer(uint16_t color) {
bool status = composite1.createSprite(240, 120); composite.setAttribute(PSRAM_ENABLE, true);
composite1.fillSprite(TFT_BLUE);
composite1.setTextColor(TFT_BLACK);
composite1.setTextSize(4);
composite1.pushSprite(0, 0);
status = composite2.createSprite(240, 120); if (composite.createSprite(240, 240)) {
composite2.fillSprite(TFT_BLUE); printf("SUCCESS: Composite sprite created.\n");
composite2.setTextColor(TFT_BLACK); composite.fillSprite(TFT_RED);
composite2.setTextSize(4); } else {
composite2.pushSprite(0, 120); printf("FATAL: Composite sprite failed! No RAM/PSRAM.\n");
return;
}
composite.setFreeFont(NULL);
composite.setTextFont(1);
composite.setTextColor(TFT_BLUE);
composite.setTextSize(4);
composite.pushSprite(0, 0);
} }
void tft_drawBuffer() { void tft_drawBuffer() {
tft.startWrite(); composite.pushSprite(0, 0, TFT_TRANSPARENT);
composite1.pushSprite(0, 0);
composite2.pushSprite(0, 0 + BUF_H);
tft.endWrite();
} }
/*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) { void tft_clearBuffer(TFT_eSprite &composite, uint16_t color) {
composite.fillSprite(color); composite.fillSprite(color);
} }
void tft_clearBuffer(uint16_t color) { void tft_clearBuffer(uint16_t color) {
composite1.fillSprite(color); composite.fillSprite(color);
composite2.fillSprite(color);
} }
void tft_drawCenteredText(const char* text, int size, int yGlobal) { void tft_drawCenteredText(const char* text, int size, int yGlobal) {
int textW = strlen(text) * size * 6; int textW = strlen(text) * size * 6;
int x = (SCREEN_WIDTH - textW) / 2; int x = (SCREEN_WIDTH - textW) / 2;
composite1.setTextSize(size); composite.setTextSize(size);
composite1.setTextColor(TFT_BLACK); composite.setTextColor(TFT_BLACK);
composite1.drawString(text, x, yGlobal); composite.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);
} }
void tft_drawText(const char* text, int size, int x, int y, uint16_t color) { void tft_drawText(const char* text, int size, int x, int y, uint16_t color) {
composite1.setTextSize(size); composite.setTextSize(size);
composite1.setTextColor(color); composite.setTextColor(color);
composite1.drawString(text, x, y); composite.drawString(text, x, y);
composite2.setTextSize(size);
composite2.setTextColor(color);
composite2.drawString(text, x, y - BUF_H);
} }
void tft_drawRectangle(int x, int y, int w, int h, uint16_t color) { void tft_drawRectangle(int x, int y, int w, int h, uint16_t color) {
composite1.fillRect(x, y, w, h, color); composite.fillRect(x, y, w, h, color);
composite2.fillRect(x, y - BUF_H, w, h, color);
} }

View File

@ -2,17 +2,19 @@
#define DRAW_H #define DRAW_H
#include <TFT_eSPI.h> #include <TFT_eSPI.h>
#include "defs/sprite_data.h"
void draw_drawSprite( void draw_drawSprite(
TFT_eSprite &tft, int x, int y, TFT_eSprite &tft, int x, int y,
struct SpriteData* spriteData, uint8_t spriteNumber, 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_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_drawBackgroundSection(TFT_eSprite& bg, int x, int y, int w, int h);
void draw_drawSpriteCentered( 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 #endif

View File

@ -2,16 +2,19 @@
#include "defs/sprite_data.h" #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) {
int cleanWidth = attackSpriteData->spriteWidth + 6;
draw_drawBackgroundSection(bg, x, y, cleanWidth, attackSpriteData->spriteHeight * 2);
switch(attackType) { switch(attackType) {
case 1: case 1:
draw_drawSprite(sprite, x, y, attackSpriteData, attackSprite, factor, flipped); draw_drawSprite(sprite, x, y, attackSpriteData, attackSprite, flipped);
draw_drawSprite(sprite, x, y + 48, attackSpriteData, attackSprite, factor, flipped); draw_drawSprite(sprite, x, y + 48, attackSpriteData, attackSprite, flipped);
break; break;
case 0: case 0:
default: default:
draw_drawSprite(sprite, x, y, attackSpriteData, attackSprite, factor, flipped); draw_drawSprite(sprite, x, y, attackSpriteData, attackSprite, flipped);
break; break;
} }
} }

View File

@ -1,83 +1,20 @@
#include "draw.h" #include "draw.h"
#include "defs/sprite_data.h"
#include "defs/screen_defs.h" #include "defs/screen_defs.h"
const char* TAG_DB = "[DRAW BG]"; const char* TAG_DB = "[DRAW BG]";
void draw_drawBackground(TFT_eSprite &bg, int spr_w, int spr_h, int factor) { void draw_drawBackground(TFT_eSprite& bg, int spr_w, int spr_h, int factor) {
// spr_w, spr_h = dimensions of the source sprite “bg” bg.pushToSprite(&composite, 0, 0, TFT_TRANSPARENT);
// 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);
}
}
}
}
} }
// USO FUTURO void draw_drawBackgroundSection(TFT_eSprite& bg, int x, int y, int w, int h) {
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) { uint16_t* bgPtr = (uint16_t*)bg.getPointer();
int srcX_start = tft_x / factor; int bgStride = bg.width();
int srcX_end = (tft_x + tft_w - 1) / factor;
int srcY_start = tft_y / factor;
int srcY_end = (tft_y + tft_h - 1) / factor;
if (srcX_start < 0) srcX_start = 0; for (int row = 0; row < h; row++) {
if (srcY_start < 0) srcY_start = 0; uint16_t* rowSrc = bgPtr + ((y + row) * bgStride) + x;
if (srcX_end >= spr_w) srcX_end = spr_w - 1; composite.pushImage(x, y + row, w, 1, rowSrc);
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);
}
}
}
} }
} }

View File

@ -9,106 +9,53 @@
const char* TAG_D = "[DRAW]"; 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( void draw_drawSprite(
TFT_eSprite &spr, TFT_eSprite &spr,
int x, int y, int x, int y,
struct SpriteData* spriteData, struct SpriteData* spriteData,
uint8_t spriteNumber, uint8_t spriteNumber,
uint8_t factor,
bool flipHorizontal bool flipHorizontal
) { ) {
int srcW = spriteData->spriteWidth; const int W = spriteData->spriteWidth;
int srcH = spriteData->spriteHeight; const int H = spriteData->spriteHeight;
int scaledW = srcW * factor;
int scaledH = srcH * factor;
if (spr.width() != scaledW || spr.height() != scaledH) { if (spr.width() != W || spr.height() != H) {
spr.deleteSprite(); spr.deleteSprite();
spr.createSprite(scaledW, scaledH); spr.createSprite(W, H);
} }
uint16_t *sprBuf = (uint16_t *)spr.getPointer(); uint16_t* sprBuf = (uint16_t*) spr.getPointer();
uint16_t *srcBuf = spriteData->spriteData[spriteNumber]; uint16_t* srcBuf = spriteData->spriteData[spriteNumber];
for (int srcY = 0; srcY < srcH; srcY++) { if (!flipHorizontal) {
int destYBase = srcY * factor; memcpy(sprBuf, srcBuf, W * H * sizeof(uint16_t));
for (int srcX = 0; srcX < srcW; srcX++) { } else {
int useX = flipHorizontal ? (srcW - 1 - srcX) : srcX; for (int row = 0; row < H; row++) {
uint16_t raw = srcBuf[srcY * srcW + useX]; const uint16_t* src = srcBuf + row * W;
uint16_t color = (raw << 8) | (raw >> 8); uint16_t* dst = sprBuf + row * W;
for (int col = 0; col < W; col++) {
int destXBase = srcX * factor; dst[col] = src[W - 1 - col];
for (int dy = 0; dy < factor; dy++) {
int rowStart = (destYBase + dy) * scaledW + destXBase;
for (int dx = 0; dx < factor; dx++) {
sprBuf[rowStart + dx] = color;
}
} }
} }
} }
spr.pushToSprite(&composite1, x, y, TFT_TRANSPARENT); spr.pushToSprite(&composite, x, y, TFT_TRANSPARENT);
spr.pushToSprite(&composite2, x, y - 120, TFT_TRANSPARENT);
spriteData->lastX = x; spriteData->lastX = x;
spriteData->lastY = y; spriteData->lastY = y;
spriteData->lastW = scaledW; spriteData->lastW = W;
spriteData->lastH = scaledH; spriteData->lastH = H;
} }
void draw_drawSpriteCentered( void draw_drawSpriteCentered(
TFT_eSprite &spr, 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 x = (BUFFER_X - spriteData->spriteWidth) / 2;
int new_y; int new_y = (y == -1)
if (y == -1) { ? (BUFFER_Y - spriteData->spriteHeight) / 2
new_y = (BUFFER_Y - (spriteData->spriteHeight * factor)) / 2; : y;
} else {
new_y = y;
}
draw_drawSprite( draw_drawSprite(spr, x, new_y, spriteData, spriteNumber, flipped);
spr, x, new_y,
spriteData, spriteNumber, factor, flipped
);
} }

View File

@ -1,28 +1,77 @@
#include "energy.h" #include "energy.h"
#include <Arduino.h> #include <Arduino.h>
#include "defs/defs.h" #include "defs/defs.h"
#include "defs/chara_data.h"
#include "defs/sprite_data.h"
#include "display/display.h" #include "display/display.h"
#include "driver/rtc_io.h" #include "driver/rtc_io.h"
#include "defs/screen_defs.h" #include "defs/screen_defs.h"
#include "storage/storage.h"
#include "vpet/vpet/vpet.h"
#define SLEEP_TIME_US 15000000ull #define SLEEP_TIME_US 60000000ull // 60 seconds periodic wakeup
#define BUTTON_PIN_BITMASK(GPIO) (1ULL << GPIO) // Macro for individual GPIO bitmask
void energy_setUpLightSleep() { void energy_setUpLightSleep() {
// Plena confianza en manolo // Left as a placeholder for backward compatibility
esp_sleep_enable_ext0_wakeup((gpio_num_t) K4_PIN, LOW);
esp_sleep_enable_timer_wakeup(SLEEP_TIME_US);
} }
void energy_startLightSleep() { 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(); esp_light_sleep_start();
printf("[MAIN] Woken up\n"); // 3. Woken up! Let's check why
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
// Who woke you up???? TELL me!! printf("[ENERGY] Woken up. Cause: %d\n", cause);
auto cause = esp_sleep_get_wakeup_cause();
// 4. Force immediate simulation update
runVpetTasks = true; runVpetTasks = true;
} 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;
}
}

View File

@ -20,8 +20,7 @@ const char* TAG = "[MAIN]";
// TFT_eSPI stuff, important // TFT_eSPI stuff, important
TFT_eSPI tft = TFT_eSPI(); TFT_eSPI tft = TFT_eSPI();
TFT_eSprite composite1 = TFT_eSprite(&tft); TFT_eSprite composite = TFT_eSprite(&tft);
TFT_eSprite composite2 = TFT_eSprite(&tft);
TFT_eSprite sprite = TFT_eSprite(&tft); TFT_eSprite sprite = TFT_eSprite(&tft);
TFT_eSprite bg = TFT_eSprite(&tft); TFT_eSprite bg = TFT_eSprite(&tft);
@ -41,7 +40,7 @@ struct CharacterData* charaData;
uint8_t currentCharacter = 0; uint8_t currentCharacter = 0;
// Boot flag, tells if the device clock has been initialized // 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 // Screen keys, this tells which screen is being shown the screens state machine
int screenKey = TITLE_SCREEN; int screenKey = TITLE_SCREEN;
@ -70,42 +69,40 @@ void secondCoreTask(void*);
void setup() { void setup() {
Serial.begin(115200); 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 //Wire.begin(MPU_SDA_PIN, MPU_SCL_PIN); // I2C init before MPU6050
//mpu.initialize(); //mpu.initialize();
tft_initDisplay(tft, TFT_BLACK); tft_initDisplay(tft, TFT_BLACK);
tft_initScreenBuffer(TFT_BLACK); tft_initScreenBuffer(TFT_TRANSPARENT);
storage_init(); storage_init();
charaData = (struct CharacterData*) calloc(CHARA_COUNT_IN_DEVICE, sizeof(struct CharacterData));
storage_readFile("/menu.bin", &menuElementsData); storage_readFile("/menu.bin", &menuElementsData);
storage_readFile("/ui.bin", &uiElementsData); storage_readFile("/ui.bin", &uiElementsData);
storage_initBackground("/bg.bin", bg); storage_initBackground("/bg2.bin", bg);
pinMode(K1_PIN, INPUT_PULLDOWN); pinMode(K1_PIN, BUTTON_MODE);
pinMode(K2_PIN, INPUT_PULLDOWN); pinMode(K2_PIN, BUTTON_MODE);
pinMode(K3_PIN, INPUT_PULLDOWN); pinMode(K3_PIN, BUTTON_MODE);
pinMode(K4_PIN, INPUT_PULLDOWN); pinMode(K4_PIN, BUTTON_MODE);
xTaskCreatePinnedToCore(secondCoreTask, "VPET_EVAL", 4096, NULL, 0, &secondLoop, 0); xTaskCreatePinnedToCore(secondCoreTask, "VPET_EVAL", 4096, NULL, 0, &secondLoop, 0);
lines_initLineStorage(); lines_initLineStorage();
vpet_initTimer(); storage_loadState();
energy_setUpLightSleep();
} }
void loop() { void loop() {
switch (screenKey) { switch (screenKey) {
case TITLE_SCREEN: case TITLE_SCREEN:
menu_drawTitle(bg); menu_drawTitle(bg, composite);
break; break;
case CLOCK_EDIT_SCREEN: case CLOCK_EDIT_SCREEN:
@ -185,7 +182,7 @@ void loop() {
break; break;
case EGG_EMPTY_SCREEN: case EGG_EMPTY_SCREEN:
menu_drawDeathScreen( bg, sprite, &menuElementsData, &uiElementsData); menu_drawDeathScreen(bg, sprite, &menuElementsData, &uiElementsData);
break; break;
case EVOLUTION_SCREEN: case EVOLUTION_SCREEN:
@ -193,7 +190,7 @@ void loop() {
break; break;
case TRAINING_SCREEN_1: case TRAINING_SCREEN_1:
training_screenTraining1(bg, sprite, &mainCharacterSprites, &uiElementsData); training_screenTraining2(bg, sprite, &mainCharacterSprites, &uiElementsData);
break; break;
case MAIN_SCREEN: case MAIN_SCREEN:
@ -203,10 +200,14 @@ void loop() {
case CHANGE_SCREEN: case CHANGE_SCREEN:
menu_changeCharaScreen(bg, sprite, &mainCharacterSprites, &uiElementsData); menu_changeCharaScreen(bg, sprite, &mainCharacterSprites, &uiElementsData);
break; break;
case FROZEN_SCREEN:
menu_drawFridgeScreen(bg, sprite, &mainCharacterSprites, &menuElementsData);
break;
} }
if (screenKey == IDLE_SCREEN || screenKey == OFF_SCREEN) { if (screenKey == IDLE_SCREEN || screenKey == OFF_SCREEN) {
steps_countSteps(); //steps_countSteps();
} }
} }

View File

@ -6,7 +6,7 @@
#include "animations/animations.h" #include "animations/animations.h"
void menu_drawAngryScreen( void menu_drawAngryScreen(
TFT_eSprite &bg, TFT_eSprite &sprite, TFT_eSprite& bg, TFT_eSprite &sprite,
struct SpriteData* spriteData, struct SpriteData* smallUiElements struct SpriteData* spriteData, struct SpriteData* smallUiElements
) { ) {
uint8_t frameCounter = 0; uint8_t frameCounter = 0;
@ -33,8 +33,8 @@ void menu_drawAngryScreen(
tone(SPK_PIN, 1000, 200); tone(SPK_PIN, 1000, 200);
tft_clearBuffer(sprite, TFT_TRANSPARENT); tft_clearBuffer(sprite, TFT_TRANSPARENT);
draw_drawSprite(sprite, 18, 72, smallUiElements, FIREWORKS_ICON, 6); draw_drawSprite(sprite, 18, 72, smallUiElements, FIREWORKS_ICON);
draw_drawSprite(sprite, 174, 72, smallUiElements, FIREWORKS_ICON, 6); draw_drawSprite(sprite, 174, 72, smallUiElements, FIREWORKS_ICON);
} }
frameCounter++; frameCounter++;

View File

@ -8,7 +8,7 @@
uint64_t lastBeepTime = esp_timer_get_time(); uint64_t lastBeepTime = esp_timer_get_time();
uint8_t beepCounter = 0; 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(); uint64_t currentTime = esp_timer_get_time();
uint8_t pressedButtons = buttons_getPressedButtons(); uint8_t pressedButtons = buttons_getPressedButtons();

View File

@ -8,18 +8,29 @@
struct SpriteData* checkerboardPattern; struct SpriteData* checkerboardPattern;
void menu_createCheckerboard() { void menu_createCheckerboard() {
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 = (SpriteData*) malloc(sizeof(SpriteData));
checkerboardPattern->spriteHeight = 1; checkerboardPattern->spriteWidth = scaledW;
checkerboardPattern->spriteWidth = 34; checkerboardPattern->spriteHeight = scaledH;
checkerboardPattern->spriteNumber = 1; checkerboardPattern->spriteNumber = 1;
checkerboardPattern->spriteData = (uint16_t**) malloc(sizeof(uint16_t*) * checkerboardPattern->spriteNumber); checkerboardPattern->spriteData = (uint16_t**) malloc(sizeof(uint16_t*));
checkerboardPattern->spriteData[0] = (uint16_t*) malloc(sizeof(uint16_t) * checkerboardPattern->spriteWidth); checkerboardPattern->spriteData[0] = (uint16_t*) malloc(sizeof(uint16_t) * bufferSize);
for (int i = 0; i < checkerboardPattern->spriteWidth; i++) { uint16_t* buf = checkerboardPattern->spriteData[0];
if (i % 2 == 0) {
checkerboardPattern->spriteData[0][i] = TFT_BLACK; for (uint16_t row = 0; row < scaledH; row++) {
} else { for (uint8_t col = 0; col < logicalW; col++) {
checkerboardPattern->spriteData[0][i] = TFT_TRANSPARENT; 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 +43,7 @@ void menu_freeCheckerboard() {
} }
// Don't worry, I hate this too // 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(); menu_createCheckerboard();
TFT_eSprite checkerboard = TFT_eSprite(&tft); TFT_eSprite checkerboard = TFT_eSprite(&tft);
@ -48,7 +59,7 @@ void menu_evolutionScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteDat
tone(SPK_PIN, 3500, 50); tone(SPK_PIN, 3500, 50);
draw_drawBackground(bg, 90, 90, 3); 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(); tft_drawBuffer();
@ -59,7 +70,7 @@ void menu_evolutionScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteDat
} }
draw_drawBackground(bg, 90, 90, 3); 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); tft_clearBuffer(sprite, TFT_TRANSPARENT);
@ -70,7 +81,7 @@ void menu_evolutionScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteDat
tft_drawRectangle(18, startYPos, 204, 6, TFT_RED); 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(); tft_drawBuffer();
@ -105,7 +116,7 @@ void menu_evolutionScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteDat
uint8_t startYPos = 72 + (i * 6); uint8_t startYPos = 72 + (i * 6);
tft_drawRectangle(18, startYPos, 204, 6, TFT_GREEN); 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(); tft_drawBuffer();
@ -120,7 +131,7 @@ void menu_evolutionScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteDat
uint64_t currentTime = esp_timer_get_time(); uint64_t currentTime = esp_timer_get_time();
if (currentTime - lastUpdateTime > 100000) { if (currentTime - lastUpdateTime > 100000) {
draw_drawBackground(bg, 90, 90, 3); 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); uint8_t rectHeight = (6 * i);
@ -129,7 +140,7 @@ void menu_evolutionScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteDat
for (int j = 0; j < i; j++) { for (int j = 0; j < i; j++) {
uint8_t rectYPos = 72 + (6 * 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; checkerboardShift = !checkerboardShift;
} }

View File

@ -8,7 +8,7 @@
#include "defs/defs.h" #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); vTaskSuspend(secondLoop);
uint8_t selectedChara = currentCharacter; 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); sprintf(fileName, "/chara/%02x.bin", selectedCharaData->idChara);
storage_readFile(fileName, mainSpriteData); storage_readFile(fileName, mainSpriteData);
draw_drawSprite(sprite, 18, 72, mainSpriteData, 0, 6); draw_drawSprite(sprite, 18, 72, mainSpriteData, 0);
} else { } else {
tft_drawCenteredText("EMPTY", 4, 120); tft_drawCenteredText("EMPTY", 4, 120);
} }
draw_drawSprite(sprite, 174, 96, uiSpriteData, ARROW_ICON, 6); draw_drawSprite(sprite, 174, 96, uiSpriteData, ARROW_ICON);
tft_drawBuffer(); tft_drawBuffer();

View File

@ -4,8 +4,9 @@
#include "display/display.h" #include "display/display.h"
#include "buttons/buttons.h" #include "buttons/buttons.h"
#include "defs/screen_defs.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(); uint8_t pressedButtons = buttons_getPressedButtons();
switch (pressedButtons) { switch (pressedButtons) {
case K2_PRESSED: case K2_PRESSED:
@ -30,7 +31,7 @@ void menu_drawClock(TFT_eSprite &bg) {
tft_drawBuffer(); tft_drawBuffer();
} }
void menu_drawClockEdit(TFT_eSprite &bg) { void menu_drawClockEdit(TFT_eSprite& bg) {
char textBuffer[6]; char textBuffer[6];
static int clockHourCount = 0; static int clockHourCount = 0;
@ -50,10 +51,14 @@ void menu_drawClockEdit(TFT_eSprite &bg) {
case K3_PRESSED: case K3_PRESSED:
// Es un dia random, nada significativo, ya pondre mas adelante que tenga dia del año // Es un dia random, nada significativo, ya pondre mas adelante que tenga dia del año
rtc.setTime(0, clockMinuteCount, clockHourCount, 1, 11, 2024); rtc.setTime(0, clockMinuteCount, clockHourCount, 1, 11, 2024);
srand(time(NULL));
coldBoot = false; timeSet = true;
screenKey = CLOCK_SCREEN; screenKey = CLOCK_SCREEN;
vpet_initTimer();
break; break;
default: default:

View File

@ -6,7 +6,7 @@
#include "defs/sprite_data.h" #include "defs/sprite_data.h"
#include "vpet/lines/lines.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; static uint8_t frameCounter = 0;
uint64_t currentTime = esp_timer_get_time(); 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) { if (currentTime - lastUpdateTime > ANIMATION_THRESHOLD_TIME_US) {
draw_drawBackground(bg, 90, 90, 3); 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); tft_clearBuffer(sprite, TFT_TRANSPARENT);
menu_uiOverlay(sprite, uiSmallSprite); menu_uiOverlay(sprite, uiSmallSprite);
tft_clearBuffer(sprite, TFT_TRANSPARENT); tft_clearBuffer(sprite, TFT_TRANSPARENT);

View File

@ -9,7 +9,7 @@
#include "vpet/vpet/vpet.h" #include "vpet/vpet/vpet.h"
#include "vpet/lines/lines.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; static bool eggSpriteFrame = false;
uint8_t pressedButtons = buttons_getPressedButtons(); 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 (currentTime - lastUpdateTime > ANIMATION_THRESHOLD_TIME_US) {
if (charaData[currentCharacter].hatchTimer <= currentLine[currentCharacter]->hatchTime) { if (charaData[currentCharacter].hatchTimer <= currentLine[currentCharacter]->hatchTime) {
draw_drawBackground(bg, 90, 90, 3); draw_drawBackground(bg, 90, 90, 3);
draw_drawSpriteCentered(sprite, &currentEgg->eggSprite, eggSpriteFrame, 6); draw_drawSpriteCentered(sprite, &currentEgg->eggSprite, eggSpriteFrame);
eggSpriteFrame = !eggSpriteFrame; eggSpriteFrame = !eggSpriteFrame;
lastUpdateTime = currentTime; lastUpdateTime = currentTime;
@ -47,7 +47,7 @@ void menu_eggHatchScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData
draw_drawBackground(bg, 90, 90, 3); draw_drawBackground(bg, 90, 90, 3);
draw_drawSpriteCentered(sprite, &currentEgg->eggSprite, 2, 6); draw_drawSpriteCentered(sprite, &currentEgg->eggSprite, 2);
tft_drawBuffer(); tft_drawBuffer();

View File

@ -9,7 +9,7 @@
#include "vpet/vpet/vpet.h" #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; static uint8_t eggCounter = 0;
uint8_t buttonsPressed = buttons_getPressedButtons(); 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); draw_drawBackground(bg, 90, 90, 3);
tft_clearBuffer(sprite, TFT_TRANSPARENT); 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); tft_clearBuffer(sprite, TFT_TRANSPARENT);
draw_drawSprite(sprite, 194, 96, uiSmallSprite, ARROW_ICON, 6); draw_drawSprite(sprite, 194, 96, uiSmallSprite, ARROW_ICON);
tft_drawBuffer(); tft_drawBuffer();
} }

View File

@ -5,7 +5,7 @@
#include "display/display.h" #include "display/display.h"
void menu_feedingScreen( void menu_feedingScreen(
TFT_eSprite &bg, TFT_eSprite &charaSprite, TFT_eSprite& bg, TFT_eSprite &charaSprite,
struct SpriteData* uiSpriteData, struct SpriteData* charaSpriteData, uint8_t item struct SpriteData* uiSpriteData, struct SpriteData* charaSpriteData, uint8_t item
) { ) {
static int currentAnimationFrame = 0; static int currentAnimationFrame = 0;
@ -19,7 +19,7 @@ void menu_feedingScreen(
animate_performEatingAnimation(charaSprite, charaSpriteData); animate_performEatingAnimation(charaSprite, charaSpriteData);
tft_clearBuffer(charaSprite, TFT_TRANSPARENT); tft_clearBuffer(charaSprite, TFT_TRANSPARENT);
draw_drawSprite(charaSprite, 24, 120, uiSpriteData, item, 6); draw_drawSprite(charaSprite, 24, 120, uiSpriteData, item);
lastUpdateTime = currentTime; lastUpdateTime = currentTime;
currentAnimationFrame++; currentAnimationFrame++;

View File

@ -1,92 +1,94 @@
#include "menu.h"
#include "display/display.h"
#include "draw/draw.h"
#include "buttons/buttons.h" #include "buttons/buttons.h"
#include "defs/chara_data.h" #include "defs/chara_data.h"
#include "display/display.h"
#include "draw/draw.h"
#include "menu.h"
#include "vpet/vpet/vpet.h" #include "vpet/vpet/vpet.h"
void menu_foodScreen(TFT_eSprite &bg, TFT_eSprite &mainChara, struct SpriteData* spriteData) { void menu_foodScreen(TFT_eSprite &bg, TFT_eSprite &mainChara,
if (charaData[currentCharacter].sleepy) { struct SpriteData *spriteData) {
tone(SPK_PIN, BEEP_FREQ_HZ, BEEP_LEN_MS); if (charaData[currentCharacter].sleepy) {
delay(100); tone(SPK_PIN, BEEP_FREQ_HZ, BEEP_LEN_MS);
tone(SPK_PIN, BEEP_FREQ_HZ, BEEP_LEN_MS); delay(100);
screenKey = MENU_SCREEN; tone(SPK_PIN, BEEP_FREQ_HZ, BEEP_LEN_MS);
screenKey = MENU_SCREEN;
return;
}
static uint8_t arrowPosition = 0; return;
}
uint8_t pressedButtons = buttons_getPressedButtons();
switch (pressedButtons) {
case 8:
arrowPosition = (arrowPosition + 1) % 2;
break;
case 2: static uint8_t arrowPosition = 0;
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;
case 1: uint8_t pressedButtons = buttons_getPressedButtons();
if (charaData[currentCharacter].strength < 8) { switch (pressedButtons) {
charaData[currentCharacter].strengthCareMistakeTimer = charaData[currentCharacter].initialStatsReductionTime; case 8:
charaData[currentCharacter].strength++; arrowPosition = (arrowPosition + 1) % 2;
charaData[currentCharacter].weight += 2; break;
screenKey = FEEDING_SCREEN;
submenuKey = PILL_ICON; case 2:
} else { screenKey = MENU_SCREEN;
screenKey = REFUSING_SCREEN; break;
}
return; default:
break; 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); draw_drawBackground(bg, 90, 90, 3);
menu_foodScreen_drawEntry(mainChara, spriteData, 0, FOOD_ICON, "Meat"); menu_foodScreen_drawEntry(mainChara, spriteData, 0, FOOD_ICON, "Meat");
menu_foodScreen_drawEntry(mainChara, spriteData, 1, PILL_ICON, "Pill"); menu_foodScreen_drawEntry(mainChara, spriteData, 1, PILL_ICON, "Pill");
draw_drawSprite(mainChara, 5, (arrowPosition * 34) + 5, spriteData, ARROW_ICON, 4);
tft_drawBuffer(); draw_drawSprite(mainChara, 5, (arrowPosition * 34) + 5, spriteData,
ARROW_ICON);
tft_drawBuffer();
} }
void menu_foodScreen_drawEntry( void menu_foodScreen_drawEntry(TFT_eSprite &mainChara,
TFT_eSprite &mainChara, struct SpriteData* spriteData, struct SpriteData *spriteData, uint8_t entryId,
uint8_t entryId, uint8_t spriteNumber, const char* textEntry uint8_t spriteNumber, const char *textEntry) {
) { tft_clearBuffer(mainChara, TFT_TRANSPARENT);
tft_clearBuffer(mainChara, TFT_TRANSPARENT); draw_drawSprite(mainChara, 45, (entryId * 34) + 5, spriteData, spriteNumber);
draw_drawSprite(mainChara, 45, (entryId * 34) + 5, spriteData, spriteNumber, 4); tft_drawText(textEntry, 4, 80, (entryId * 34) + 5);
tft_drawText(textEntry, 4, 80, (entryId * 34) + 5);
} }

View File

@ -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();
}

View File

@ -6,8 +6,8 @@
#include "animations/animations.h" #include "animations/animations.h"
void menu_drawHappyScreen( void menu_drawHappyScreen(
TFT_eSprite &bg, TFT_eSprite &sprite, TFT_eSprite& bg, TFT_eSprite &sprite,
struct SpriteData* spriteData, struct SpriteData* smallUiElements struct SpriteData* spriteData, struct SpriteData* smallUiElements, const int returnScreen
) { ) {
uint8_t frameCounter = 0; uint8_t frameCounter = 0;
@ -15,11 +15,9 @@ void menu_drawHappyScreen(
uint64_t currentTime = esp_timer_get_time(); uint64_t currentTime = esp_timer_get_time();
if (currentTime - lastUpdateTime > ANIMATION_THRESHOLD_TIME_US) { if (currentTime - lastUpdateTime > ANIMATION_THRESHOLD_TIME_US) {
if (frameCounter > 3) { if (frameCounter > 3) {
screenKey = MAIN_SCREEN; // TODO: Change for while battling screenKey = returnScreen; // TODO: Change for while battling
menuKey = STATUS_SCREEN; menuKey = STATUS_SCREEN;
vTaskResume(secondLoop);
return; return;
} }
@ -35,8 +33,8 @@ void menu_drawHappyScreen(
tone(SPK_PIN, 1000, 50); tone(SPK_PIN, 1000, 50);
tft_clearBuffer(sprite, TFT_TRANSPARENT); tft_clearBuffer(sprite, TFT_TRANSPARENT);
draw_drawSprite(sprite, 18, 72, smallUiElements, FIREWORKS_ICON, 6); draw_drawSprite(sprite, 18, 72, smallUiElements, FIREWORKS_ICON);
draw_drawSprite(sprite, 174, 72, smallUiElements, FIREWORKS_ICON, 6); draw_drawSprite(sprite, 174, 72, smallUiElements, FIREWORKS_ICON);
} }
frameCounter++; frameCounter++;

View File

@ -13,7 +13,7 @@ void menu_drawIdleScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData
switch (pressedButtons) { switch (pressedButtons) {
case K1_PRESSED: case K1_PRESSED:
screenKey = MENU_SCREEN; screenKey = MENU_SCREEN;
menuKey = 0; menuKey = STATUS_SCREEN_MENU;
break; break;
case K2_PRESSED: case K2_PRESSED:

View File

@ -4,10 +4,14 @@
void menu_mainScreen() { void menu_mainScreen() {
printf("[MAINSCR] on main screen\n"); printf("[MAINSCR] on main screen\n");
lastUpdateTime = 0;
if (coldBoot) { if (!timeSet) {
screenKey = TITLE_SCREEN; screenKey = TITLE_SCREEN;
return; return;
} else if (charaData[currentCharacter].frozen) {
screenKey = FROZEN_SCREEN;
return;
} else if (!charaData[currentCharacter].hatched && !charaData[currentCharacter].hatching) { } else if (!charaData[currentCharacter].hatched && !charaData[currentCharacter].hatching) {
screenKey = EGG_EMPTY_SCREEN; screenKey = EGG_EMPTY_SCREEN;
return; return;

View File

@ -3,11 +3,12 @@
#include <TFT_eSPI.h> #include <TFT_eSPI.h>
#include "defs/defs.h" #include "defs/defs.h"
#include "defs/sprite_data.h"
void menu_drawCurrentMenuOption(TFT_eSprite &bg, TFT_eSprite &icon, struct SpriteData* spriteData); void menu_drawCurrentMenuOption(TFT_eSprite &bg, TFT_eSprite &icon, struct SpriteData* spriteData);
void menu_drawClock(TFT_eSprite &bg); void menu_drawClock(TFT_eSprite &bg);
void menu_drawClockEdit(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_drawIdleScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* spriteData, struct SpriteData* bigUiElements, struct SpriteData* smallUiElements);
void menu_offScreen(); void menu_offScreen();
void menu_statusScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* spriteData); 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_clearPoopScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* spriteData, struct SpriteData* bigUiElements, struct SpriteData* smallUiElements);
void menu_drawHappyScreen( void menu_drawHappyScreen(
TFT_eSprite &bg, TFT_eSprite &sprite, 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_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); 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, TFT_eSprite &bg, TFT_eSprite &sprite,
struct SpriteData* spriteData, struct SpriteData* smallUiElements 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_sleepAction();
void menu_sleepScreen_recalculateSleep(); void menu_sleepScreen_recalculateSleep();
void menu_freezeScreen_alternateFreeze();
#endif #endif

View File

@ -12,7 +12,7 @@
const int textXPos = 10; const int textXPos = 10;
const int textYPos = 180; 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); draw_drawBackground(bg, 90, 90, 3);
uint8_t pressedButtons = buttons_getPressedButtons(); uint8_t pressedButtons = buttons_getPressedButtons();
@ -40,19 +40,23 @@ void menu_drawCurrentMenuOption(TFT_eSprite &bg, TFT_eSprite &icon, struct Sprit
break; break;
case FOOD_SCREEN_MENU: case FOOD_SCREEN_MENU:
if (charaData[currentCharacter].frozen) { break; }
screenKey = FOOD_SCREEN; screenKey = FOOD_SCREEN;
break; break;
case SLEEP_SCREEN_MENU: case SLEEP_SCREEN_MENU:
if (charaData[currentCharacter].frozen) { break; }
menu_sleepScreen_sleepAction(); menu_sleepScreen_sleepAction();
break; break;
case TRAIN_SCREEN_MENU: case TRAIN_SCREEN_MENU:
if (charaData[currentCharacter].frozen) { break; }
screenKey = TRAINING_SCREEN_1; screenKey = TRAINING_SCREEN_1;
return; return;
break; break;
case POOP_SCREEN_MENU: case POOP_SCREEN_MENU:
if (charaData[currentCharacter].frozen) { break; }
menuKey = STATUS_SCREEN; menuKey = STATUS_SCREEN;
screenKey = CLEAR_POOP_SCREEN; screenKey = CLEAR_POOP_SCREEN;
return; return;
@ -64,15 +68,20 @@ void menu_drawCurrentMenuOption(TFT_eSprite &bg, TFT_eSprite &icon, struct Sprit
return; return;
break; break;
case FREEZE_SCREEN_MENU:
menu_freezeScreen_alternateFreeze();
return;
break;
default: default:
break; break;
} }
return; return;
} }
draw_drawSpriteCentered(icon, spriteData, menuKey % 9, 6); draw_drawSpriteCentered(icon, spriteData, menuKey % 10);
switch(menuKey % 10) { switch(menuKey % 11) {
case STATUS_SCREEN_MENU: case STATUS_SCREEN_MENU:
tft_drawCenteredText("Status", 4, textYPos); tft_drawCenteredText("Status", 4, textYPos);
break; break;
@ -108,8 +117,12 @@ void menu_drawCurrentMenuOption(TFT_eSprite &bg, TFT_eSprite &icon, struct Sprit
case SETTINGS_SCREEN_MENU: case SETTINGS_SCREEN_MENU:
tft_drawCenteredText("Settings", 4, textYPos); tft_drawCenteredText("Settings", 4, textYPos);
break; break;
case 9: case FREEZE_SCREEN_MENU:
tft_drawCenteredText("Freeze", 4, textYPos);
break;
case 10:
menuKey = STATUS_SCREEN_MENU; menuKey = STATUS_SCREEN_MENU;
screenKey = MAIN_SCREEN; screenKey = MAIN_SCREEN;
return; return;
@ -130,7 +143,7 @@ void menu_sleepScreen_sleepAction() {
charaData[currentCharacter].sleepDisturbances++; charaData[currentCharacter].sleepDisturbances++;
menuKey = STATUS_SCREEN; menuKey = STATUS_SCREEN_MENU;
screenKey = MAIN_SCREEN; screenKey = MAIN_SCREEN;
} else { } else {
@ -138,11 +151,18 @@ void menu_sleepScreen_sleepAction() {
vpet_computeCallLight(); // Lo hago por cortesia, no me gusta vpet_computeCallLight(); // Lo hago por cortesia, no me gusta
menuKey = STATUS_SCREEN; menuKey = STATUS_SCREEN_MENU;
screenKey = SLEEP_SCREEN; screenKey = SLEEP_SCREEN;
} }
} }
void menu_freezeScreen_alternateFreeze() {
charaData[currentCharacter].frozen = !charaData[currentCharacter].frozen;
menuKey = STATUS_SCREEN;
screenKey = MAIN_SCREEN;
}
void menu_sleepScreen_recalculateSleep() { void menu_sleepScreen_recalculateSleep() {
uint32_t newSleepTime = (dayUnixTime + 3600) % SECONDS_IN_DAY; uint32_t newSleepTime = (dayUnixTime + 3600) % SECONDS_IN_DAY;
uint32_t newWakeUpTime = charaData[currentCharacter].wakeupTime + 3600; uint32_t newWakeUpTime = charaData[currentCharacter].wakeupTime + 3600;

View File

@ -36,15 +36,21 @@ void menu_clearPoopScreen(
tft_clearBuffer(sprite, TFT_TRANSPARENT); tft_clearBuffer(sprite, TFT_TRANSPARENT);
while (cleanerXPos > 18) { while (cleanerXPos > 18 - 48) {
draw_drawSprite(sprite, cleanerXPos, 72, smallUiElements, CLEANER_ICON, 6); draw_drawBackgroundSection(bg, cleanerXPos + 6, 72, 48, 96);
draw_drawSprite(sprite, cleanerXPos, 120, smallUiElements, CLEANER_ICON, 6);
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(); tft_drawBuffer();
cleanerXPos -= 6; cleanerXPos -= 6;
delay(50);
} }
screenKey = HAPPY_SCREEN; screenKey = HAPPY_SCREEN;
menuKey = -1;
charaData[currentCharacter].poopNumber = 0; charaData[currentCharacter].poopNumber = 0;
return; return;

View File

@ -13,7 +13,7 @@ uint8_t menu_poopOverlay(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData
bool poopTop = false; bool poopTop = false;
for (int i = 0; i < charaData[currentCharacter].poopNumber; i++) { 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; poopStartX -= (i % 2) * 48;
poopTop = !poopTop; poopTop = !poopTop;
} }

View File

@ -22,7 +22,7 @@ void menu_poopScreen(
draw_drawBackground(bg, 90, 90, 3); draw_drawBackground(bg, 90, 90, 3);
tft_clearBuffer(sprite, TFT_TRANSPARENT); 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); tft_clearBuffer(sprite, TFT_TRANSPARENT);
menu_uiOverlay(sprite, bigUiElements); menu_uiOverlay(sprite, bigUiElements);
@ -45,13 +45,13 @@ void menu_poopScreen(
draw_drawBackground(bg, 90, 90, 3); draw_drawBackground(bg, 90, 90, 3);
tft_clearBuffer(sprite, TFT_TRANSPARENT); 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); tft_clearBuffer(sprite, TFT_TRANSPARENT);
menu_uiOverlay(sprite, bigUiElements); menu_uiOverlay(sprite, bigUiElements);
tft_clearBuffer(sprite, TFT_TRANSPARENT); tft_clearBuffer(sprite, TFT_TRANSPARENT);
draw_drawSprite(sprite, 72, 72, spriteData, 7, 6); draw_drawSprite(sprite, 72, 72, spriteData, 7);
animationFrame++; animationFrame++;
animationPosition = !animationPosition; animationPosition = !animationPosition;
@ -69,7 +69,7 @@ void menu_poopScreen(
screenKey = MAIN_SCREEN; screenKey = MAIN_SCREEN;
} }
menuKey = 0; menuKey = -1;
animationFrame = 0; animationFrame = 0;
animationPosition = 0; animationPosition = 0;

View File

@ -42,10 +42,10 @@ void menu_sleepingScreen(
animate_performSleepyAnimation(sprite, mainCharaData); animate_performSleepyAnimation(sprite, mainCharaData);
tft_clearBuffer(sprite, TFT_TRANSPARENT); 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); 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); tft_clearBuffer(sprite, TFT_TRANSPARENT);
menu_uiOverlay(sprite, bigUiElements); menu_uiOverlay(sprite, bigUiElements);

View File

@ -6,6 +6,8 @@
#include "display/display.h" #include "display/display.h"
#include "draw/draw.h" #include "draw/draw.h"
#include <math.h>
void menu_statusScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* spriteData) { void menu_statusScreen(TFT_eSprite &bg, TFT_eSprite &sprite, struct SpriteData* spriteData) {
tft_clearBuffer(sprite, TFT_TRANSPARENT); 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, 10, "Hunger", charaData[currentCharacter].hunger);
menu_statusScreen_drawStat(sprite, spriteData, 10, 80, "Strength", charaData[currentCharacter].strength); 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(); tft_drawBuffer();
} }
@ -43,7 +45,6 @@ void menu_statusScreen_drawStat(TFT_eSprite &sprite, struct SpriteData* spriteDa
y + 30, y + 30,
spriteData, spriteData,
icon, icon,
4,
false false
); );
} }

View File

@ -4,7 +4,7 @@
#include "defs/defs.h" #include "defs/defs.h"
#include "buttons/buttons.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(); uint8_t pressedButtons = buttons_getPressedButtons();
if (pressedButtons == 8 || pressedButtons == 4) { if (pressedButtons == 8 || pressedButtons == 4) {
screenKey = CLOCK_EDIT_SCREEN; screenKey = CLOCK_EDIT_SCREEN;
@ -18,4 +18,6 @@ void menu_drawTitle(TFT_eSprite &bg) {
tft_drawCenteredText(VERSION, 2, 80); tft_drawCenteredText(VERSION, 2, 80);
tft_drawBuffer(); tft_drawBuffer();
delay(200);
} }

View File

@ -14,7 +14,7 @@ void training_screenTraining1(
vTaskSuspend(secondLoop); vTaskSuspend(secondLoop);
draw_drawBackground(bg, 90, 90, 3); 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, 4100, 100);
tone(SPK_PIN, 3500, 100); tone(SPK_PIN, 3500, 100);
@ -24,7 +24,7 @@ void training_screenTraining1(
delay(500); delay(500);
draw_drawBackground(bg, 90, 90, 3); draw_drawBackground(bg, 90, 90, 3);
draw_drawSpriteCentered(sprite, mainCharaData, 0, 6); draw_drawSpriteCentered(sprite, mainCharaData, 0);
tft_drawCenteredText("PUSH!!", 4, 190); tft_drawCenteredText("PUSH!!", 4, 190);
tft_drawBuffer(); tft_drawBuffer();

View File

@ -7,5 +7,10 @@ void training_screenTraining1(
TFT_eSprite &bg, TFT_eSprite &sprite, TFT_eSprite &bg, TFT_eSprite &sprite,
struct SpriteData* mainCharaData, struct SpriteData* attackSprites struct SpriteData* mainCharaData, struct SpriteData* attackSprites
); );
void training_screenTraining2(
TFT_eSprite &bg, TFT_eSprite &sprite,
struct SpriteData* mainCharaData, struct SpriteData* attackSprites
);
#endif #endif

View File

@ -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);
}
}
}
}

View File

@ -1,22 +1,23 @@
#include "menu.h"
#include "draw/draw.h"
#include "display/display.h"
#include "defs/chara_data.h" #include "defs/chara_data.h"
#include "defs/screen_defs.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) { void menu_uiOverlay(TFT_eSprite &charSprite, struct SpriteData *uiElements) {
char hourBuffer[6]; 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); composite.fillRect(0, 0, 240, 24, TFT_BLACK);
tft_drawText(hourBuffer, 2, 4, 4, TFT_WHITE); tft_drawText(hourBuffer, 2, 4, 4, TFT_WHITE);
snprintf(hourBuffer, 6, "%05d", stepCounter); snprintf(hourBuffer, 6, "%05d", stepCounter);
tft_drawText(hourBuffer, 2, 176, 4, TFT_WHITE); tft_drawText(hourBuffer, 2, 176, 4, TFT_WHITE);
if (charaData[currentCharacter].careMistakeCallLight) { if (charaData[currentCharacter].careMistakeCallLight) {
tft_clearBuffer(charSprite, TFT_TRANSPARENT); tft_clearBuffer(charSprite, TFT_TRANSPARENT);
draw_drawSprite(charSprite, 192, 192, uiElements, CARE_MISTAKE_CALL_LIGHT, 2); // draw_drawSprite(charSprite, 192, 192, uiElements,
} // CARE_MISTAKE_CALL_LIGHT, 2);
}
} }

View File

@ -1,9 +1,15 @@
#include "storage.h" #include "storage.h"
#include "memory/memory.h" #include "memory/memory.h"
#include "defs/defs.h"
#include "defs/chara_data.h"
#include "defs/sprite_data.h" #include "defs/sprite_data.h"
#include "defs/screen_defs.h"
#include "TFT_eSPI.h"
const char* TAG_S = "[STORAGE]"; const char* TAG_S = "[STORAGE]";
#define SPRITE_SCALE 6
void storage_init() { void storage_init() {
if (!SPIFFS.begin(true)) { if (!SPIFFS.begin(true)) {
printf("%s Failed to mount file system\n", TAG_S); printf("%s Failed to mount file system\n", TAG_S);
@ -20,56 +26,85 @@ void storage_readFile(const char* path, struct SpriteData* spriteData) {
return; return;
} }
size_t bytesRead = 0;
size_t fileSize = file.size();
uint8_t width, height, spriteNumber; uint8_t width, height, spriteNumber;
bytesRead += file.read(&width, 1); file.read(&width, 1);
bytesRead += file.read(&height, 1); file.read(&height, 1);
bytesRead += file.read(&spriteNumber, 1); file.read(&spriteNumber, 1);
if (spriteData->spriteData != NULL) { if (spriteData->spriteData != NULL) {
memory_free(spriteData); memory_free(spriteData);
} }
spriteData->spriteWidth = width; const uint8_t scaledW = width * SPRITE_SCALE;
spriteData->spriteHeight = height; const uint8_t scaledH = height * SPRITE_SCALE;
spriteData->spriteNumber = spriteNumber;
uint16_t** scaled = (uint16_t**) ps_malloc(spriteNumber * sizeof(uint16_t*));
spriteData->spriteData = memory_allocate(spriteData->spriteNumber, spriteData->spriteWidth, spriteData->spriteHeight); if (!scaled) {
printf("%s PSRAM alloc failed for pointer table\n", TAG_S);
file.close();
return;
}
for (uint8_t i = 0; i < spriteNumber; i++) {
scaled[i] = (uint16_t*) ps_malloc(scaledW * scaledH * sizeof(uint16_t));
if (!scaled[i]) {
printf("%s PSRAM alloc failed for sprite %d\n", TAG_S, i);
for (uint8_t j = 0; j < i; j++) free(scaled[j]);
free(scaled);
file.close();
return;
}
}
uint16_t* rowBuf = (uint16_t*) malloc(width * sizeof(uint16_t));
if (!rowBuf) {
printf("%s scratch alloc failed\n", TAG_S);
for (uint8_t i = 0; i < spriteNumber; i++) free(scaled[i]);
free(scaled);
file.close();
return;
}
printf( printf(
"%s Read header: width=%d, height=%d, numSprites=%d\n", "%s Read header: width=%d, height=%d, numSprites=%d -> scaled to %dx%d\n",
TAG_S, spriteData->spriteWidth, spriteData->spriteHeight, spriteData->spriteNumber 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++) {
for (int srcX = 0; srcX < width; srcX++) {
uint8_t hi, lo;
file.read(&hi, 1);
file.read(&lo, 1);
rowBuf[srcX] = (lo << 8) | hi;
}
uint8_t highByte; for (int dy = 0; dy < SPRITE_SCALE; dy++) {
uint8_t lowByte; uint16_t* dstRow = dst + (srcY * SPRITE_SCALE + dy) * scaledW;
for (int sprN = 0; sprN < spriteData->spriteNumber; sprN++) { for (int srcX = 0; srcX < width; srcX++) {
for (int i = 0; i < spriteData->spriteWidth * spriteData->spriteHeight; i++) { uint16_t color = rowBuf[srcX];
bytesRead += file.read(&highByte, 1); uint16_t* dstPixel = dstRow + srcX * SPRITE_SCALE;
bytesRead += file.read(&lowByte, 1); for (int dx = 0; dx < SPRITE_SCALE; dx++) {
dstPixel[dx] = color;
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;
} }
} }
} }
printf("%s Read %zu bytes from file %s\n", TAG_S, bytesRead, path); free(rowBuf);
file.close(); file.close();
spriteData->spriteWidth = scaledW;
spriteData->spriteHeight = scaledH;
spriteData->spriteNumber = spriteNumber;
spriteData->spriteData = scaled;
printf("%s Loaded & upscaled %s (%d sprites, each %dx%d px)\n",
TAG_S, path, spriteNumber, scaledW, scaledH);
} }
void storage_initBackground(const char* path, TFT_eSprite& bg) { void storage_initBackground(const char* path, TFT_eSprite& bg) {
@ -79,40 +114,194 @@ void storage_initBackground(const char* path, TFT_eSprite& bg) {
return; 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; printf("%s width=%d height=%d pixels=%zu\n", TAG_S, width, height, pixelCount);
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);
bg.createSprite(width, height); bg.createSprite(width, height);
for(int i = 0; i < width * height; i++) { uint16_t* bgBuf = (uint16_t*) bg.getPointer();
uint8_t highByte;
uint8_t lowByte;
bytesRead += file.read(&highByte, 1); for (size_t i = 0; i < pixelCount; i++) {
bytesRead += file.read(&lowByte, 1); uint8_t hi, lo;
file.read(&lo, 1);
file.read(&hi, 1);
bgBuf[i] = (hi << 8) | lo;
}
uint16_t pixel = (highByte << 8) | lowByte; file.close();
}
if (i < fileSize) { void storage_saveState() {
bg.drawPixel(i % width, i / width, pixel); File file;
} else {
printf("%s Buffer overflow, skipping pixel\n", TAG_S); file = SPIFFS.open("/save.bin", "w");
break;
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(); 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);
} }

View File

@ -9,6 +9,9 @@
void storage_init(); void storage_init();
void storage_readFile(const char* path, struct SpriteData* spriteData); 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 #endif

View File

@ -86,4 +86,6 @@ void change_onChangeComplete() {
snprintf(spriteFileName, 30, "/chara/%02x.bin", charaData[currentCharacter].idChara); snprintf(spriteFileName, 30, "/chara/%02x.bin", charaData[currentCharacter].idChara);
storage_readFile(spriteFileName, &mainCharacterSprites); storage_readFile(spriteFileName, &mainCharacterSprites);
storage_saveState();
} }

View File

@ -2,7 +2,8 @@
#include "memory/memory.h" #include "memory/memory.h"
#include "defs/defs.h" #include "defs/defs.h"
#include "SPIFFS.h" #include <FS.h>
#include <SPIFFS.h>
const char lineHeader[5] = "NPET"; const char lineHeader[5] = "NPET";
const uint8_t headerSize = 4; const uint8_t headerSize = 4;
@ -12,8 +13,8 @@ void lines_getAvailableLines() {
return; return;
} }
File root = SPIFFS.open("/lines"); fs::File root = SPIFFS.open("/lines");
File lineFile = root.openNextFile(); fs::File lineFile = root.openNextFile();
uint8_t allocCount = 0; uint8_t allocCount = 0;
char header[5]; char header[5];

View File

@ -2,19 +2,20 @@
#include "defs/file_chara.h" #include "defs/file_chara.h"
#include "defs/defs.h" #include "defs/defs.h"
#include "SPIFFS.h" #include <FS.h>
#include <SPIFFS.h>
void lines_getLineCareMistakes(const char* fileName) { void lines_getLineCareMistakes(const char* fileName) {
char careMistakesPath[strlen(fileName) + 8]; char careMistakesPath[strlen(fileName) + 8];
snprintf(careMistakesPath, strlen(fileName) + 8, "/care/%s", fileName); snprintf(careMistakesPath, strlen(fileName) + 8, "/care/%s", fileName);
File careMistakesFile = SPIFFS.open(careMistakesPath); fs::File careMistakesFile = SPIFFS.open(careMistakesPath);
uint8_t bytesRead = 0; uint8_t bytesRead = 0;
LineCare_t* careMistakesData = (LineCare_t*) malloc(sizeof(LineCare_t)); 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->lineId, 1);
bytesRead += careMistakesFile.read(&careMistakesData->numCareMistakesData, 1); bytesRead += careMistakesFile.read(&careMistakesData->numCareMistakesData, 1);

View File

@ -2,13 +2,14 @@
#include "memory/memory.h" #include "memory/memory.h"
#include "defs/defs.h" #include "defs/defs.h"
#include <FS.h>
#include <SPIFFS.h> #include <SPIFFS.h>
void lines_getSingleLine(const char* fileName) { void lines_getSingleLine(const char* fileName) {
char fullPath[8 + strlen(fileName)]; char fullPath[8 + strlen(fileName)];
snprintf(fullPath, 20, "/lines/%s", 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)); struct Line_t* selectedLine = (struct Line_t*) malloc(sizeof(struct Line_t));
if (selectedLine == NULL) { if (selectedLine == NULL) {
@ -17,7 +18,7 @@ void lines_getSingleLine(const char* fileName) {
uint8_t buffer[4]; uint8_t buffer[4];
lineFile.seek(4, SeekCur); lineFile.seek(4, fs::SeekCur);
uint8_t bytesRead = lineFile.read(&selectedLine->id, 1); uint8_t bytesRead = lineFile.read(&selectedLine->id, 1);
bytesRead += lineFile.readBytes(selectedLine->name, 16); bytesRead += lineFile.readBytes(selectedLine->name, 16);
@ -40,7 +41,7 @@ void lines_getSingleLine(const char* fileName) {
currentEgg = selectedEgg; 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 // Importante tener el nombre de archivo del huevo en todo momento
strcpy(selectedEgg->fileName, lineFile.name()); strcpy(selectedEgg->fileName, lineFile.name());

View File

@ -1,12 +1,14 @@
#include "lines.h" #include "lines.h"
#include "defs/defs.h" #include "defs/defs.h"
#include "defs/file_chara.h" #include "defs/file_chara.h"
#include "defs/chara_data.h"
Egg_t* currentEgg = NULL; Egg_t* currentEgg = NULL;
LineCare_t** currentLineCareInstr = NULL; LineCare_t** currentLineCareInstr = NULL;
Line_t** currentLine = NULL; Line_t** currentLine = NULL;
void lines_initLineStorage() { void lines_initLineStorage() {
currentLineCareInstr = (LineCare_t**) malloc(sizeof(LineCare_t*) * CHARA_COUNT_IN_DEVICE); charaData = (struct CharacterData*) calloc(CHARA_COUNT_IN_DEVICE, sizeof(struct CharacterData));
currentLine = (Line_t**) malloc(sizeof(Line_t*) * CHARA_COUNT_IN_DEVICE); currentLineCareInstr = (LineCare_t**) calloc(CHARA_COUNT_IN_DEVICE, sizeof(LineCare_t*));
currentLine = (Line_t**) calloc(CHARA_COUNT_IN_DEVICE, sizeof(Line_t*));
} }

View File

@ -2,6 +2,7 @@
#define TRAINING_H #define TRAINING_H
#include <TFT_eSPI.h> #include <TFT_eSPI.h>
#include "defs/sprite_data.h"
void training_displayTrainingResult( void training_displayTrainingResult(
TFT_eSprite &bg, TFT_eSprite &sprite, TFT_eSprite &bg, TFT_eSprite &sprite,

View File

@ -2,6 +2,7 @@
#include "draw/draw.h" #include "draw/draw.h"
#include "defs/defs.h" #include "defs/defs.h"
#include "defs/chara_data.h" #include "defs/chara_data.h"
#include "defs/sprite_data.h"
#include "display/display.h" #include "display/display.h"
#define NUM_ROUNDS 5 #define NUM_ROUNDS 5
@ -75,13 +76,17 @@ void training_displayTrainingResult(
break; break;
} }
draw_drawBackground(bg, 90, 90, 3);
for (int i = 0; i < NUM_ROUNDS; i++) { for (int i = 0; i < NUM_ROUNDS; i++) {
training_trainingAttackSounds(); training_trainingAttackSounds();
for (int j = 78; j >= -48; j -= 3) {
draw_drawBackground(bg, 90, 90, 3); for (int j = 78; j >= -48; j -= 6) {
draw_drawSprite(sprite, 126, 72, mainCharaData, 11, 6); draw_drawSprite(sprite, 126, 72, mainCharaData, 11);
draw_drawAttacks(sprite, attackSprites, j, 72, pattern[i], charaData[currentCharacter].spriteAttackId, 6);
draw_drawAttacks(bg, sprite, attackSprites, j, 72, pattern[i], charaData[currentCharacter].spriteAttackId);
draw_drawBackgroundSection(bg, 0, 72, 18, 96);
tft_drawBuffer(); tft_drawBuffer();
} }

View File

@ -167,7 +167,12 @@ void vpet_evalHungerTimer() {
charaData[currentCharacter].hungerCareMistakeTimer <= 0 && charaData[currentCharacter].hungerCareMistakeTimer <= 0 &&
charaData[currentCharacter].hunger > 0 charaData[currentCharacter].hunger > 0
) { ) {
#ifndef DEBUG
charaData[currentCharacter].hunger--; charaData[currentCharacter].hunger--;
#else
charaData[currentCharacter].hunger -= 60;
#endif
if (charaData[currentCharacter].hunger > 0) { if (charaData[currentCharacter].hunger > 0) {
charaData[currentCharacter].hungerCareMistakeTimer = charaData[currentCharacter].initialStatsReductionTime; charaData[currentCharacter].hungerCareMistakeTimer = charaData[currentCharacter].initialStatsReductionTime;
@ -202,7 +207,12 @@ void vpet_evalStrengthTimer() {
charaData[currentCharacter].strengthCareMistakeTimer <= 0 && charaData[currentCharacter].strengthCareMistakeTimer <= 0 &&
charaData[currentCharacter].strength > 0 charaData[currentCharacter].strength > 0
) { ) {
#ifndef DEBUG
charaData[currentCharacter].strength--; charaData[currentCharacter].strength--;
#else
charaData[currentCharacter].strength -= 60;
#endif
if (charaData[currentCharacter].strength > 0) { if (charaData[currentCharacter].strength > 0) {
charaData[currentCharacter].strengthCareMistakeTimer = charaData[currentCharacter].initialStatsReductionTime; charaData[currentCharacter].strengthCareMistakeTimer = charaData[currentCharacter].initialStatsReductionTime;
} else { } else {
@ -226,7 +236,11 @@ void vpet_evalStrengthTimer() {
void vpet_evalChangeTimer(uint8_t diff_sec) { void vpet_evalChangeTimer(uint8_t diff_sec) {
if (charaData[currentCharacter].changeTimerLeft > 0) { if (charaData[currentCharacter].changeTimerLeft > 0) {
#ifndef DEBUG
charaData[currentCharacter].changeTimerLeft -= diff_sec; charaData[currentCharacter].changeTimerLeft -= diff_sec;
#else
charaData[currentCharacter].changeTimerLeft -= 600;
#endif
} }
if (charaData[currentCharacter].changeTimerLeft <= 0) { if (charaData[currentCharacter].changeTimerLeft <= 0) {
@ -245,7 +259,7 @@ void IRAM_ATTR onActionTimerDelta() {
} }
void vpet_runVpetTasks() { void vpet_runVpetTasks() {
if (runVpetTasks) { if (runVpetTasks && !charaData[currentCharacter].frozen) {
uint64_t currentEvaluationTime = esp_timer_get_time(); uint64_t currentEvaluationTime = esp_timer_get_time();
uint64_t deltaUs = currentEvaluationTime - vpetLastEvaluationTime; uint64_t deltaUs = currentEvaluationTime - vpetLastEvaluationTime;

View File

@ -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