#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
// --- Configuration Écran CYD ---
#define TFT_CS 15
#define TFT_DC 2
#define TFT_MOSI 13
#define TFT_MISO 12
#define TFT_SCK 14
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
// --- Configuration LED RGB ---
#define LED_R 4
#define LED_G 16
#define LED_B 17
// --- Structures de données du Tamagotchi ---
enum Humeur { HEUREUX, AFFAME, FATIGUE, MORT };
struct Pixel { uint8_t x; uint8_t y; uint16_t couleur; };
struct Tamagotchi {
int generation;
int faim;
int energie;
Humeur humeur;
int pixels_utilises;
Pixel corps[50];
};
Tamagotchi monPerso;
// --- Timers et Variables Système ---
unsigned long dernierTickAnim = 0;
unsigned long dernierTickVie = 0;
const int INTERVALLE_ANIM = 400; // Animation toutes les 400ms
const int INTERVALLE_VIE = 2000; // Le métabolisme (Faim/Energie) baisse toutes les 2s pour le test
int frameAnim = 0;
int decalageY = 0;
const int TAILLE_GRILLE = 16;
const int TAILLE_MACRO_PIXEL = 240 / TAILLE_GRILLE;
const int OFFSET_Y_JEU = 40;
#define GRIS_FONCE 0x3186
// --- Fonctions Utilitaires ---
void setRGB(bool r, bool g, bool b) {
// Les LEDs du CYD s'allument souvent à l'état LOW
digitalWrite(LED_R, r ? LOW : HIGH);
digitalWrite(LED_G, g ? LOW : HIGH);
digitalWrite(LED_B, b ? LOW : HIGH);
}
void creerSlimeDeBase() {
monPerso.generation = 1;
monPerso.faim = 100;
monPerso.energie = 100;
monPerso.humeur = HEUREUX;
monPerso.pixels_utilises = 14;
uint16_t vert = tft.color565(50, 205, 50);
uint16_t blanc = ILI9341_WHITE;
// Création des pixels
monPerso.corps[0] = {7, 6, vert}; monPerso.corps[1] = {8, 6, vert};
monPerso.corps[2] = {6, 7, vert}; monPerso.corps[3] = {7, 7, blanc};
monPerso.corps[4] = {8, 7, blanc}; monPerso.corps[5] = {9, 7, vert};
monPerso.corps[6] = {5, 8, vert}; monPerso.corps[7] = {6, 8, vert};
monPerso.corps[8] = {7, 8, vert}; monPerso.corps[9] = {8, 8, vert};
monPerso.corps[10] = {9, 8, vert}; monPerso.corps[11] = {10, 8, vert};
monPerso.corps[12] = {6, 9, vert}; monPerso.corps[13] = {9, 9, vert};
}
void setup() {
Serial.begin(115200);
// Initialisation LED
pinMode(LED_R, OUTPUT);
pinMode(LED_G, OUTPUT);
pinMode(LED_B, OUTPUT);
setRGB(false, false, false);
// Initialisation Écran avec tes broches spécifiques
SPI.begin(TFT_SCK, TFT_MISO, TFT_MOSI, TFT_CS);
tft.begin();
tft.setRotation(0); // Mode Portrait
tft.fillScreen(ILI9341_BLACK);
creerSlimeDeBase();
dessinerBarreEtat();
dessinerMenuBas();
}
void loop() {
boucleDeVie();
boucleAnimation();
// Bientôt, on ajoutera ici la lecture de l'écran tactile !
}
// --- Moteur Logique ---
void boucleDeVie() {
if (millis() - dernierTickVie >= INTERVALLE_VIE) {
dernierTickVie = millis();
if (monPerso.humeur != MORT) {
monPerso.faim -= 5;
monPerso.energie -= 2;
}
if (monPerso.faim < 0) monPerso.faim = 0;
if (monPerso.energie < 0) monPerso.energie = 0;
// Mise à jour de l'humeur
if (monPerso.faim == 0 && monPerso.energie == 0) monPerso.humeur = MORT;
else if (monPerso.faim <= 30) monPerso.humeur = AFFAME;
else if (monPerso.energie <= 30) monPerso.humeur = FATIGUE;
else monPerso.humeur = HEUREUX;
// Mise à jour de la LED RGB selon l'humeur !
switch (monPerso.humeur) {
case HEUREUX: setRGB(false, true, false); break; // Vert
case AFFAME: setRGB(true, true, false); break; // Jaune
case FATIGUE: setRGB(false, false, true); break; // Bleu
case MORT: setRGB(true, false, false); break; // Rouge
}
dessinerBarreEtat();
}
}
void boucleAnimation() {
if (millis() - dernierTickAnim >= INTERVALLE_ANIM) {
dernierTickAnim = millis();
// Nettoie l'ancienne position
int yDepart = OFFSET_Y_JEU + (4 * TAILLE_MACRO_PIXEL);
tft.fillRect(3 * TAILLE_MACRO_PIXEL, yDepart - 10, 10 * TAILLE_MACRO_PIXEL, 8 * TAILLE_MACRO_PIXEL + 15, ILI9341_BLACK);
if (monPerso.humeur == MORT) decalageY = 0;
else {
if (frameAnim == 0) { frameAnim = 1; decalageY = -5; }
else { frameAnim = 0; decalageY = 0; }
}
// Dessine la nouvelle position
for (int i = 0; i < monPerso.pixels_utilises; i++) {
int xPhysique = monPerso.corps[i].x * TAILLE_MACRO_PIXEL;
int yPhysique = OFFSET_Y_JEU + (monPerso.corps[i].y * TAILLE_MACRO_PIXEL) + decalageY;
tft.fillRect(xPhysique, yPhysique, TAILLE_MACRO_PIXEL, TAILLE_MACRO_PIXEL, monPerso.corps[i].couleur);
}
}
}
// --- Interface Graphique ---
void dessinerBarreEtat() {
tft.fillRect(0, 0, 240, 30, GRIS_FONCE);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1);
String icone = "";
uint16_t couleurHumeur = ILI9341_WHITE;
switch (monPerso.humeur) {
case HEUREUX: icone = "(^_^)"; couleurHumeur = ILI9341_GREEN; break;
case AFFAME: icone = "(o_O)"; couleurHumeur = ILI9341_ORANGE; break;
case FATIGUE: icone = "(-_-)"; couleurHumeur = ILI9341_CYAN; break;
case MORT: icone = "(X_X)"; couleurHumeur = ILI9341_RED; break;
}
tft.setCursor(5, 10); tft.print("GEN:"); tft.print(monPerso.generation);
tft.setCursor(60, 10); tft.print("F:"); tft.print(monPerso.faim); tft.print("%");
tft.setCursor(110, 10); tft.print("E:"); tft.print(monPerso.energie); tft.print("%");
tft.setTextColor(couleurHumeur);
tft.setCursor(180, 10); tft.setTextSize(2); tft.print(icone);
tft.drawFastHLine(0, 30, 240, ILI9341_WHITE);
}
void dessinerMenuBas() {
tft.fillRect(0, 280, 240, 40, GRIS_FONCE);
tft.drawFastHLine(0, 280, 240, ILI9341_WHITE);
tft.fillRoundRect(10, 285, 60, 30, 4, ILI9341_GREEN);
tft.fillRoundRect(90, 285, 60, 30, 4, ILI9341_BLUE);
tft.fillRoundRect(170, 285, 60, 30, 4, ILI9341_ORANGE);
tft.setTextColor(ILI9341_BLACK);
tft.setTextSize(1);
tft.setCursor(18, 295); tft.print("MANGER");
tft.setCursor(102, 295); tft.print("JOUER");
tft.setCursor(180, 295); tft.print("EDITER");
}Loading
esp32-2432s028r
esp32-2432s028r