Mini Virtual Pet 🐣
No Space for a Pet? Why Not a Virtual Pet?
My concept was to create a simple virtual pet similar to a Tamagotchi. The pet has happiness and health bars, and both values drop every 30 seconds. The user must keep feeding and playing with the pet, or it dies when its health reaches zero.
Schematic Diagram
Code
virtual_pet_v2.ino
#include "SPI.h"
#include "TFT_22_ILI9225.h"
#include <TFT.h>
#define TFT_RST 8
#define TFT_RS 9
#define TFT_CS 10 // SS
#define TFT_SDI 11 // MOSI
#define TFT_CLK 13 // SCK
#define TFT_LED 0
#define BUTTON_LED 6
//#define speaker 5
#define POT_LED 3
#define BUTTON 12
#define POT 2
int buttonState;
int potState;
int rgb;
int health = 99;
int happy = 99;
int caseState = 0;
int counter;
int counterState;
String outPutHealth;
String outPutPot;
String outPutHappy;
TFT_22_ILI9225 tft = TFT_22_ILI9225(TFT_RST, TFT_RS, TFT_CS, TFT_LED);
void setup() {
pinMode(BUTTON_LED, OUTPUT);
pinMode(POT_LED, OUTPUT);
pinMode(BUTTON, INPUT);
tft.begin();
tft.setOrientation(2);
tft.setFont(Terminal6x8);
//tft.drawText(10, 10, "hello!");
Serial.begin(9600);
}
void loop() {
buttonState = digitalRead(BUTTON);
potState = analogRead(POT);
potState = map(potState, 0, 1023, 0, 9);
interface();
displayInfo();
serialPort();
digitalWrite(BUTTON_LED, HIGH);
digitalWrite(POT_LED, HIGH);
//tone(speaker, 0);
}
display.ino
\void displayInfo() {
String outPutPot = String(potState, DEC);
String outPutHealth = String(health, DEC);
String outPutHappy = String(happy, DEC);
//counter logic
switch (counterState) {
case 0:
counter++;
if (health <= 0) counterState = 2;
if (health <= 0) counterState = 2;
if (counter == 5) counterState = 1;
break;
case 1:
health -= 5;
if (health <= 0) counterState = 2;
if (health <= 0) counterState = 2;
happy -= 2;
counter = 0;
if (counter == 0) counterState = 0;
break;
case 2:
counter = 0;
caseState = 3;
}
//control graphic
if (health <= 0) {
dieGraphic();
} else {
gameGraphic();
}
}
void serialPort() {
Serial.print("Button State = \t");
Serial.print(buttonState);
Serial.print("\t Pot State = \t");
Serial.print(potState);
Serial.print("\t counter = \t");
Serial.print(counter);
Serial.print("\t counterState = \t");
Serial.print(counterState);
Serial.println();
}
graphic.ino
void gameGraphic() {
String outPutPot = String(potState, DEC);
String outPutHealth = String(health, DEC);
String outPutHappy = String(happy, DEC);
if (potState <= 4) {
if (happy <= 70) {
rgb = COLOR_RED;
} else {
rgb = COLOR_YELLOW;
}
} else {
if (happy <= 70) {
rgb = COLOR_RED;
} else {
rgb = COLOR_GREEN;
}
}
tft.fillCircle(80, 100, 30, rgb);
tft.fillCircle(70, 100, 5, COLOR_BLACK);
tft.fillCircle(70, 100, 1, COLOR_WHITE);
tft.fillCircle(90, 100, 5, COLOR_BLACK);
tft.fillCircle(90, 100, 1, COLOR_WHITE);
if(health <= 60){
tft.drawText(ILI9225_LCD_WIDTH / 11, ILI9225_LCD_HEIGHT / 1.1, "Health: " + outPutHealth, COLOR_RED);
}else{
tft.drawText(ILI9225_LCD_WIDTH / 11, ILI9225_LCD_HEIGHT / 1.1, "Health: " + outPutHealth, COLOR_WHITE);
}
tft.drawText(ILI9225_LCD_WIDTH / 1.8, ILI9225_LCD_HEIGHT / 1.1, "Happy: " + outPutHappy);
}
void dieGraphic() {
rgb = COLOR_GRAY;
tft.fillCircle(80, 100, 30, rgb);
tft.drawText(ILI9225_LCD_WIDTH / 3.3, ILI9225_LCD_HEIGHT / 1.4, "I'm dead :(");
tft.drawText(ILI9225_LCD_WIDTH / 1.8, ILI9225_LCD_HEIGHT / 1.1, "Happy: 00 ", COLOR_GRAY);
tft.drawText(ILI9225_LCD_WIDTH / 11, ILI9225_LCD_HEIGHT / 1.1, "Health: 00", COLOR_GRAY);
}
void resetGame() {
tft.clear();
health = 99;
happy = 99;
caseState = 0;
counterState = 0;
}
interface.ino
void interface() {
switch (caseState) {
case 0:
if (potState == 9) caseState = 0;
if (potState >= 2 ) {
tft.drawRectangle(20, 20, 70, 40, COLOR_BLACK);
tft.drawRectangle(85, 20, 135, 40, COLOR_WHITE);
if (buttonState == HIGH) {
caseState = 2;
}
} else if (potState == 0) {
tft.drawRectangle(20, 20, 70, 40, COLOR_WHITE);
tft.drawRectangle(85, 20, 135, 40, COLOR_BLACK);
if (buttonState == HIGH) {
caseState = 1;
}
}
tft.drawText(ILI9225_LCD_WIDTH / 6, ILI9225_LCD_HEIGHT / 8, "Feed ");
tft.drawText(ILI9225_LCD_WIDTH / 1.8, ILI9225_LCD_HEIGHT / 8, "Play");
break;
case 1:
if (potState == 9) caseState = 0;
if (potState >= 2) {
tft.drawRectangle(85, 20, 135, 40, COLOR_WHITE);
tft.drawRectangle(20, 20, 70, 40, COLOR_BLACK);
if (buttonState == HIGH && health < 99) {
if (health <= 87) health += 10;
if (health > 87) health += 1;
}else if(health >= 99){
health = 99;
}
} else if (potState == 0) {
tft.drawRectangle(85, 20, 135, 40, COLOR_BLACK);
tft.drawRectangle(20, 20, 70, 40, COLOR_WHITE);
if (buttonState == HIGH && health < 99) {
health += 1;
} else if (health >= 99) {
health == 99;
}
}
tft.drawText(ILI9225_LCD_WIDTH / 6, ILI9225_LCD_HEIGHT / 8, "Apple");
tft.drawText(ILI9225_LCD_WIDTH / 1.8, ILI9225_LCD_HEIGHT / 8, "Milk");
break;
case 2:
if (potState == 9) caseState = 0;
if (potState >= 2 ) {
tft.drawRectangle(20, 20, 70, 40, COLOR_BLACK);
tft.drawRectangle(85, 20, 135, 40, COLOR_WHITE);
if (buttonState == HIGH && happy < 99) {
if (happy <= 92) happy += 5;
if (happy > 92) happy += 1;
}else if(happy >= 99){
happy = 99;
}
} else if (potState == 0) {
tft.drawRectangle(20, 20, 70, 40, COLOR_WHITE);
tft.drawRectangle(85, 20, 135, 40, COLOR_BLACK);
if (buttonState == HIGH && happy < 99) {
if (happy <= 96) happy += 2;
if (happy > 96) happy += 1;
}else if(happy >= 99){
happy = 99;
}
}
tft.drawText(ILI9225_LCD_WIDTH / 6, ILI9225_LCD_HEIGHT / 8, "Fetch");
tft.drawText(ILI9225_LCD_WIDTH / 1.8, ILI9225_LCD_HEIGHT / 8, "Pet ");
break;
case 3:
tft.drawText(ILI9225_LCD_WIDTH / 6, ILI9225_LCD_HEIGHT / 8, "RESTART:");
tft.drawText(ILI9225_LCD_WIDTH / 1.8, ILI9225_LCD_HEIGHT / 8, "GO! ");
tft.drawRectangle(20, 20, 70, 40, COLOR_BLACK);
tft.drawRectangle(85, 20, 135, 40, COLOR_WHITE);
if (buttonState == HIGH) {
resetGame();
}
break;
}
}
Rendering
Low-health warning

The pet is unhappy (I need to play with it more)

The pet died
