Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
ea3632326b
|
|||
|
5b763a33bc
|
+5
-8
@@ -3,20 +3,17 @@
|
|||||||
#include "joystick.hpp"
|
#include "joystick.hpp"
|
||||||
#include "display.hpp"
|
#include "display.hpp"
|
||||||
#include "menu.hpp"
|
#include "menu.hpp"
|
||||||
|
#include "pet.hpp"
|
||||||
#define ACTION_INTERVAL 60000 // 1 minute
|
#define ACTION_INTERVAL 60000 // 1 minute
|
||||||
#define MAXIMUM_STAT 100
|
#define MAXIMUM_STAT 100
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool dead;
|
Pet pet;
|
||||||
bool menuOpen;
|
|
||||||
|
|
||||||
int hunger;
|
|
||||||
int joy;
|
|
||||||
int energy;
|
|
||||||
int cleanliness;
|
|
||||||
|
|
||||||
uint64_t lastActionTime;
|
uint64_t lastActionTime;
|
||||||
bool shouldClear;
|
|
||||||
|
bool isMenuOpen;
|
||||||
|
bool shouldClearDisplay;
|
||||||
} GameState;
|
} GameState;
|
||||||
|
|
||||||
class Game {
|
class Game {
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Arduino.h>
|
||||||
|
#define MAXIMUM_STAT 100
|
||||||
|
|
||||||
|
class Pet {
|
||||||
|
public:
|
||||||
|
Pet();
|
||||||
|
bool isAlive;
|
||||||
|
|
||||||
|
void updateHunger(int8_t delta);
|
||||||
|
void updateJoy(int8_t delta);
|
||||||
|
void updateEnergy(int8_t delta);
|
||||||
|
void updateCleanliness(int8_t delta);
|
||||||
|
String getReasonForDeath() const;
|
||||||
|
private:
|
||||||
|
int8_t hunger;
|
||||||
|
int8_t joy;
|
||||||
|
int8_t energy;
|
||||||
|
int8_t cleanliness;
|
||||||
|
String reasonForDeath;
|
||||||
|
};
|
||||||
+42
-44
@@ -2,14 +2,10 @@
|
|||||||
|
|
||||||
Game::Game() : joystick(), display(), menu() {
|
Game::Game() : joystick(), display(), menu() {
|
||||||
state = (GameState) {
|
state = (GameState) {
|
||||||
.dead = false,
|
.pet = Pet(),
|
||||||
.menuOpen = false,
|
|
||||||
.hunger = 0,
|
|
||||||
.joy = 100,
|
|
||||||
.energy = 100,
|
|
||||||
.cleanliness = 100,
|
|
||||||
.lastActionTime = 0,
|
.lastActionTime = 0,
|
||||||
.shouldClear = false,
|
.isMenuOpen = false,
|
||||||
|
.shouldClearDisplay = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
String items[] = {
|
String items[] = {
|
||||||
@@ -32,14 +28,14 @@ void Game::begin() {
|
|||||||
|
|
||||||
void Game::update() {
|
void Game::update() {
|
||||||
// If the pet is dead, we don't need to update its state
|
// If the pet is dead, we don't need to update its state
|
||||||
if (state.dead) {
|
if (!state.pet.isAlive) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isPressed = joystick.isPressed();
|
bool isPressed = joystick.isPressed();
|
||||||
|
|
||||||
// If the menu is open, we don't need to update the pet's state
|
// If the menu is open, we don't need to update the pet's state
|
||||||
if (state.menuOpen) {
|
if (state.isMenuOpen) {
|
||||||
JoystickDirection direction = joystick.getDirection();
|
JoystickDirection direction = joystick.getDirection();
|
||||||
if (menu.updateCurrentItem(direction)) {
|
if (menu.updateCurrentItem(direction)) {
|
||||||
forceUpdate("Menu navigation");
|
forceUpdate("Menu navigation");
|
||||||
@@ -47,7 +43,7 @@ void Game::update() {
|
|||||||
|
|
||||||
// If the joystick is pressed, execute the current menu item
|
// If the joystick is pressed, execute the current menu item
|
||||||
if (isPressed) {
|
if (isPressed) {
|
||||||
state.menuOpen = false;
|
state.isMenuOpen = false;
|
||||||
// Based on the current menu item, perform the corresponding action
|
// Based on the current menu item, perform the corresponding action
|
||||||
switch (menu.getCurrentItemIndex()) {
|
switch (menu.getCurrentItemIndex()) {
|
||||||
case 0:
|
case 0:
|
||||||
@@ -70,7 +66,7 @@ void Game::update() {
|
|||||||
|
|
||||||
// If the joystick is pressed and the menu is not open, open the menu
|
// If the joystick is pressed and the menu is not open, open the menu
|
||||||
if (isPressed) {
|
if (isPressed) {
|
||||||
state.menuOpen = true;
|
state.isMenuOpen = true;
|
||||||
forceUpdate("Opening menu");
|
forceUpdate("Opening menu");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -78,74 +74,76 @@ void Game::update() {
|
|||||||
// Update the pet's stats based on the time elapsed since the last action
|
// Update the pet's stats based on the time elapsed since the last action
|
||||||
uint64_t currentTime = millis();
|
uint64_t currentTime = millis();
|
||||||
if (currentTime - state.lastActionTime >= ACTION_INTERVAL) {
|
if (currentTime - state.lastActionTime >= ACTION_INTERVAL) {
|
||||||
state.hunger += 10;
|
state.pet.updateHunger(10);
|
||||||
state.joy -= 5;
|
state.pet.updateJoy(-5);
|
||||||
state.energy -= 5;
|
state.pet.updateEnergy(-5);
|
||||||
state.cleanliness -= 5;
|
state.pet.updateCleanliness(-5);
|
||||||
|
|
||||||
state.lastActionTime = currentTime;
|
state.lastActionTime = currentTime;
|
||||||
|
|
||||||
forceUpdate("Time-based stat update");
|
forceUpdate("Time-based stat update");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the pet has died from any of the conditions
|
|
||||||
bool starvedToDeath = state.hunger >= MAXIMUM_STAT;
|
|
||||||
bool diedOfBoredom = state.joy <= -MAXIMUM_STAT;
|
|
||||||
bool diedOfExhaustion = state.energy <= -MAXIMUM_STAT;
|
|
||||||
bool diedOfFilth = state.cleanliness <= -MAXIMUM_STAT;
|
|
||||||
|
|
||||||
state.dead = starvedToDeath || diedOfBoredom || diedOfExhaustion || diedOfFilth;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::render() {
|
void Game::render() {
|
||||||
if (state.shouldClear) {
|
// Clear display if needed, and if the menu is open, redraw it
|
||||||
|
if (state.shouldClearDisplay) {
|
||||||
display.clear();
|
display.clear();
|
||||||
state.shouldClear = false;
|
state.shouldClearDisplay = false;
|
||||||
|
|
||||||
if (state.menuOpen) {
|
if (state.isMenuOpen) {
|
||||||
display.drawMenu(menu);
|
display.drawMenu(menu);
|
||||||
Serial.println("Rendering menu");
|
Serial.println("Rendering menu");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.menuOpen) {
|
// If the menu is open, we don't need to render the pet's stats
|
||||||
|
if (state.isMenuOpen) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.dead) {
|
// If the pet is dead, display a message and return
|
||||||
display.getLCD().print("Your pet has died.");
|
if (!state.pet.isAlive) {
|
||||||
|
String buffer[4] = {
|
||||||
|
"Your pet has died",
|
||||||
|
state.pet.getReasonForDeath(),
|
||||||
|
"Reset the device",
|
||||||
|
"to start over"
|
||||||
|
};
|
||||||
|
|
||||||
|
display.drawBuffer(buffer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
display.getLCD().setCursor(0, 0);
|
|
||||||
display.getLCD().print("H: " + String(state.hunger));
|
|
||||||
display.getLCD().setCursor(0, 1);
|
|
||||||
display.getLCD().print("J: " + String(state.joy));
|
|
||||||
display.getLCD().setCursor(0, 2);
|
|
||||||
display.getLCD().print("E: " + String(state.energy));
|
|
||||||
display.getLCD().setCursor(0, 3);
|
|
||||||
display.getLCD().print("C: " + String(state.cleanliness));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::forceUpdate(String reason) {
|
void Game::forceUpdate(String reason) {
|
||||||
if (!state.shouldClear) {
|
if (!state.shouldClearDisplay) {
|
||||||
Serial.println("Forcing update: " + reason);
|
Serial.println("Forcing update: " + reason);
|
||||||
state.shouldClear = true;
|
state.shouldClearDisplay = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::feed() {
|
void Game::feed() {
|
||||||
state.hunger += 20;
|
if (state.pet.isAlive) {
|
||||||
|
state.pet.updateHunger(-20);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::play() {
|
void Game::play() {
|
||||||
state.joy += 20;
|
if (state.pet.isAlive) {
|
||||||
|
state.pet.updateJoy(20);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::sleep() {
|
void Game::sleep() {
|
||||||
state.energy += 20;
|
if (state.pet.isAlive) {
|
||||||
|
state.pet.updateEnergy(20);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::clean() {
|
void Game::clean() {
|
||||||
state.cleanliness += 20;
|
if (state.pet.isAlive) {
|
||||||
|
state.pet.updateCleanliness(20);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+68
@@ -0,0 +1,68 @@
|
|||||||
|
#include "pet.hpp"
|
||||||
|
|
||||||
|
Pet::Pet()
|
||||||
|
: isAlive(true), hunger(0), joy(100), energy(100), cleanliness(100), reasonForDeath("") {}
|
||||||
|
|
||||||
|
void Pet::updateHunger(int8_t delta) {
|
||||||
|
hunger += delta;
|
||||||
|
|
||||||
|
if (hunger < 0) {
|
||||||
|
isAlive = false;
|
||||||
|
reasonForDeath = "starvation";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hunger > MAXIMUM_STAT) {
|
||||||
|
isAlive = false;
|
||||||
|
reasonForDeath = "overfeeding";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pet::updateJoy(int8_t delta) {
|
||||||
|
joy += delta;
|
||||||
|
|
||||||
|
if (joy < 0) {
|
||||||
|
isAlive = false;
|
||||||
|
reasonForDeath = "depression";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (joy > MAXIMUM_STAT) {
|
||||||
|
isAlive = false;
|
||||||
|
reasonForDeath = "overstimulation";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pet::updateEnergy(int8_t delta) {
|
||||||
|
energy += delta;
|
||||||
|
|
||||||
|
if (energy < 0) {
|
||||||
|
isAlive = false;
|
||||||
|
reasonForDeath = "exhaustion";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (energy > MAXIMUM_STAT) {
|
||||||
|
isAlive = false;
|
||||||
|
reasonForDeath = "overresting";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pet::updateCleanliness(int8_t delta) {
|
||||||
|
cleanliness += delta;
|
||||||
|
|
||||||
|
if (cleanliness < 0) {
|
||||||
|
isAlive = false;
|
||||||
|
reasonForDeath = "disease";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cleanliness > MAXIMUM_STAT) {
|
||||||
|
isAlive = false;
|
||||||
|
reasonForDeath = "overcleaning";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String Pet::getReasonForDeath() const {
|
||||||
|
return reasonForDeath;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user