Tamaguino

(Original design by Alojz Jakob)

The Tamaguino is an Arduino spin-off of the classic Tamagotchi, which was a toy introduced in the 90s that allowed users to pick a virtual pet and take responsibility for feeding, playing with, and teaching it.
This Tamagotchi system then had consequences for neglecting the pet, and the virtual dinosaur, cat or other strange or wonderful digital animal could die if the tasks weren't performed on a regular basis, although if you managed to keep your Tamagotchi alive, you would get to help it grow, age and interact with the virtual world around it.

The Tamaguino is a project by Alojz Jakob, released for free under the GNU - General Public License. Using an Arduino, an OLED display, a buzzer, some buttons, a few wires, and some coding of course, Aljoz managed to bring our childhood back to life. After learning about this project, we just knew we had to make one, and with the following guide, you now you can too!

Material Quantity
Arduino Pro Mini 1
4cm x 6cm prototyping PCB 1
LiPo rechargeable battery 720 mAh 1
Micro USB LiPo charging circuit 1
128x64 OLED Display 1
Buzzer 1
Push Buttons 3
10K Resistors 3
Jumper wires 9
Small on/off switch 1
Soldering iron Optional
Solder Optional
Tamaguino case Optional

Diagram

Instruction

  1. Solder the bottom row of your button to the bottom row of your PCB as shown in the image below. Your bottom row of pins for your buttons will all be grounded The image above shows how you can ground your buttons without clutter around the GND pin on your Pro Mini
  2. Solder your resistors to the slots next to each of your button's signal pins as shown in the image below, and bridge the solder to your button pins. The image above shows where you can solder your buttons as well as the resistors for an easy layout.
  3. Next you will solder your Pro Mini to the OTHER SIDE of the PCB, try to place your Pro mini about 3 rows above the top pins of your buttons, solder at pin 7, 8, 9, A4, A5, GND and VCC as shown in the image below. The image above shows placement of the Pro Mini as well as highlights the pins for the OLED.
  4. You will now solder the resistors connected to your top signal pins to the respective pins for the code, we used pin 7, 8 and 9 on our Pro Mini
  5. Solder your OLED display to the PCB just above the buttons, so that your OLED pins peak out just above your Pro Mini – as shown by the orange circle in the image above.
  6. Stick down your LiPo charging module to the top of your PCB.
  7. With your basic components now attached to the PCB, you can start wiring. Solder a wire from pin A4 to the SDA pin on your OLED (shown in blue on the diagram and orange in the images)
  8. Solder a wire from pin A5 to SCL pin on your OLED (shown in yellow in the diagram and red in the images)
  9. Connect GND on your OLED to GND on your mini, and then connect VCC to VCC.
  10. You can now solder your buzzer onto your board as shown in the image. Solder one pin to pin 6 and the other to GND.
  11. On your LiPo charging module, solder one wire from OUT- to GND, and then solder another wire from OUT+ to one side of your switch – as shown in the image below.
  12. Solder the red wire (V) to B+ on your charging module and the brown/black wire (G) to B- as shown in the image below.
  13. Finally, ground the other side of your switch by connecting a GND pin to the GND pin on the microcontroller.

Code

The original code for this project can be found at Alojz Jakob's Tamaguino page we have modified the code to save the stats of our dinosaur with a save button. The stats are saved on the EEPROM of our Arduino Pro Mini. You can find our editted version of the code below.

Tamaguino_EEPROM DOWNLOAD


/* Tamaguino
 by Alojz Jakob <http://jakobdesign.com>

 ********** TAMAGUINO ***********
 * Tamagotchi clone for Arduino *
 ********************************

*/

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <EEPROM.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

const int button1Pin = 9;
const int button2Pin = 8; 
const int button3Pin = 7; 

const int sound = 6; 

int button1State = 0;
int button2State = 0;
int button3State = 0;
int hi_address = 0;
int hunger_address=2;
int happiness_address=3;
int health_address =4;
int discipline_address=5;
int weight_address=6;
int age_address=7;

// splash 48x26
const unsigned char splash1 [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x39, 0xc0, 0x00, 
0x00, 0x00, 0x00, 0x39, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 
0x00, 0x00, 0x00, 0x00, 0x07, 0xb9, 0xce, 0x78, 0x0f, 0xc0, 0x0f, 0xf9, 0xcf, 0xfc, 0x1f, 0xe0, 
0x1f, 0xf9, 0xcf, 0xfe, 0x3f, 0xf0, 0x3c, 0x79, 0xcf, 0x1e, 0x38, 0x78, 0x38, 0x39, 0xce, 0x0e, 
0x70, 0x38, 0x38, 0x39, 0xce, 0x0e, 0x70, 0x38, 0x38, 0x39, 0xce, 0x0e, 0x70, 0x38, 0x38, 0x39, 
0xce, 0x0e, 0x70, 0x38, 0x38, 0x39, 0xce, 0x0e, 0x70, 0x38, 0x3c, 0x79, 0xce, 0x0e, 0x78, 0x70, 
0x1f, 0xf9, 0xce, 0x0e, 0x3f, 0xf0, 0x0f, 0xf9, 0xce, 0x0e, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x10, 0x25, 0x37, 0x53, 0x90, 0xe1, 0xb8, 0x29, 0x22, 
0x51, 0xd0, 0x93, 0x90, 0x19, 0x22, 0x52, 0x50, 0x92, 0x10, 0x11, 0x23, 0x73, 0xd0, 0xf1, 0x98, 
0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
};
//splash dino 80x40
const unsigned char splash2 [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x1f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xff, 0xe0, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 
0xe1, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x3e, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x5e, 0xc1, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x80, 0x2f, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x01, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x07, 0xf4, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0xe0, 0x1f, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 
0xaa, 0xbc, 0x7f, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x55, 0x5f, 0xff, 0xa0, 0x00, 0x00, 
0x00, 0x00, 0x00, 0xea, 0xaa, 0xaf, 0xff, 0x40, 0x00, 0x00, 0x00, 0x00, 0x03, 0xd5, 0x55, 0xff, 
0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0xab, 0xae, 0xbf, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x1f, 0x5f, 0xdf, 0xff, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xee, 0xfb, 0x6f, 0xf4, 0x00, 
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf7, 
0xff, 0xff, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xa0, 0x00, 0x00, 0x00, 
0x00, 0x1f, 0xff, 0xff, 0xff, 0xfd, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdf, 0xff, 0xfe, 0xfe, 
0x80, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xef, 0xef, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 
0x9f, 0xdf, 0xff, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x1f, 0xa1, 0xfc, 0x7f, 0x80, 0x00, 
0x0f, 0xff, 0xff, 0xe0, 0x1f, 0xb0, 0x03, 0xbf, 0x80, 0x00, 0x1f, 0xff, 0x80, 0x00, 0x0f, 0xc0, 
0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
};


// front grass 32x10
const unsigned char grass_front [] PROGMEM = {
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x08, 0x89, 0xc0, 0x48, 0x5c, 0x50, 0x84, 
0x9c, 0x48, 0x50, 0x22, 0x88, 0x80, 0x44, 0x22, 0x40, 0x84, 0x2e, 0x21, 0x49, 0x24, 0xa4, 0xb1, 
};
//grass 2 (dino walking on) 4x8
const unsigned char grass [] PROGMEM = {
0xff, 0xee, 0xbb, 0x55, 0xaa, 0x11, 
};

//trees
const unsigned char trees [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x10, 0x05, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x15, 0x00, 
0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x40, 0x00, 0x55, 0x40, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x15, 0x04, 0x40, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x02, 0xa0, 0x00, 0x00, 0x01, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 
0x00, 0x28, 0x84, 0x24, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x40, 0x00, 0x82, 0x00, 
0x00, 0x01, 0x10, 0x00, 0x04, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 
0x41, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x40, 0x00, 0x88, 0x82, 0x40, 0x91, 0x04, 0x24, 
0x41, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x44, 0x44, 0x11, 0x04, 0x10, 0x11, 0x04, 0x01, 0x00, 0x00, 
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 
0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x10, 0x00, 0x80, 0x00, 0x00, 0x08, 0x00, 0x04, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x20, 0x00, 0x01, 0x00, 
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 
};

const unsigned char mountains [] PROGMEM = {
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 
0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 
0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 
0x03, 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 
0x07, 0x74, 0x07, 0x80, 0x10, 0x00, 0x00, 0x80, 0x00, 0x06, 0x80, 0x00, 0x00, 0x00, 0x00, 0xd5, 
0x0e, 0xc2, 0x0d, 0xc0, 0x28, 0x01, 0x01, 0xc1, 0x00, 0x1f, 0x40, 0x00, 0x00, 0x00, 0x01, 0x28, 
0x1d, 0x13, 0x1b, 0x60, 0x54, 0x03, 0x83, 0xa3, 0x80, 0x36, 0x20, 0x00, 0x00, 0x00, 0x06, 0xd0, 
0x3a, 0x41, 0xb4, 0x30, 0xe2, 0xcc, 0xf7, 0x57, 0xc0, 0xd8, 0x10, 0x00, 0x00, 0x00, 0x19, 0x20, 
0x68, 0x84, 0x49, 0x19, 0xa1, 0x36, 0x5d, 0x2a, 0xa1, 0xa0, 0x10, 0x00, 0x00, 0x00, 0xe6, 0x40, 
0xd2, 0x10, 0xa4, 0x0c, 0x80, 0x8c, 0x1a, 0x15, 0x57, 0x40, 0x88, 0x00, 0x00, 0x1f, 0x38, 0x80, 
0x49, 0x08, 0x00, 0x06, 0x02, 0xc0, 0x24, 0x18, 0x0b, 0x80, 0x05, 0x0b, 0x8c, 0xe0, 0x23, 0x00, 
0xa0, 0x20, 0x00, 0x11, 0x00, 0x00, 0x48, 0x84, 0x84, 0x02, 0x20, 0x5d, 0xf3, 0x00, 0xcd, 0xc0, 
0x50, 0x00, 0x04, 0x04, 0x01, 0x44, 0x00, 0x00, 0x08, 0x00, 0x00, 0x30, 0x04, 0x07, 0x10, 0x20, 
0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x40, 0x40, 0x00, 0x10, 
0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x01, 0x11, 0x01, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x20, 0x02, 
};


const unsigned char cloud2 [] PROGMEM = {
0x04, 0x70, 0x18, 0x00, 0x6e, 0xfb, 0x7c, 0xee, 0xff, 0xff, 0xfd, 0xff, 0x6f, 0xfb, 0x38, 0xee, 
0x07, 0x70, 0x52, 0x00, 
};



// walking sprites
// walk right
const unsigned char dinoWalk0 [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x60, 0x00, 
0x00, 0x00, 0x1f, 0xf1, 0xf0, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xb8, 0x00, 0x00, 0x00, 0x7b, 0xff, 
0xfc, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd8, 0x00, 0x00, 0x03, 0xff, 0x7f, 0xe0, 0x00, 0x00, 0x0f, 
0xf7, 0xde, 0x00, 0x00, 0x00, 0x7f, 0xf8, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x7a, 0x00, 0x00,
};
const unsigned char dinoWalk1 [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x60, 0x00, 
0x00, 0x00, 0x1f, 0xf1, 0xf0, 0x00, 0x00, 0x00, 0x37, 0xff, 0xb8, 0x00, 0x00, 0x00, 0x7f, 0xff, 
0xfc, 0x00, 0x00, 0x00, 0xff, 0x7f, 0xd8, 0x00, 0x00, 0x03, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x0f, 
0xbf, 0xda, 0x00, 0x00, 0x00, 0x7f, 0xf8, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, 0x00, 0x00, 
};
const unsigned char dinoWalk2 [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x60, 0x00, 
0x00, 0x00, 0x1b, 0xf1, 0xf0, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xb8, 0x00, 0x00, 0x00, 0x7f, 0x7f, 
0xfc, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd8, 0x00, 0x00, 0x03, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x0f, 
0xbf, 0xfa, 0x00, 0x00, 0x00, 0x7f, 0x78, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x5e, 0x00, 0x00,
};
// walk left
const unsigned char dinoWalk3 [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0xe0, 0x00, 0x00, 
0x00, 0x0f, 0x8f, 0xf8, 0x00, 0x00, 0x00, 0x1d, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xde, 
0x00, 0x00, 0x00, 0x1b, 0xff, 0xff, 0x00, 0x00, 0x00, 0x07, 0xfe, 0xff, 0xc0, 0x00, 0x00, 0x00, 
0x7b, 0xef, 0xf0, 0x00, 0x00, 0x00, 0x3c, 0x1f, 0xfe, 0x00, 0x00, 0x00, 0x5e, 0x3d, 0x00, 0x00,  
};
const unsigned char dinoWalk4 [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0xe0, 0x00, 0x00, 
0x00, 0x0f, 0x8f, 0xf8, 0x00, 0x00, 0x00, 0x1d, 0xff, 0xec, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 
0x00, 0x00, 0x00, 0x1b, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 
0x5b, 0xfd, 0xf0, 0x00, 0x00, 0x00, 0x3c, 0x1f, 0xfe, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x00, 0x00, 
};
const unsigned char dinoWalk5 [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0xe0, 0x00, 0x00, 
0x00, 0x0f, 0x8f, 0xd8, 0x00, 0x00, 0x00, 0x1d, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x3f, 0xfe, 0xfe, 
0x00, 0x00, 0x00, 0x1b, 0xff, 0xff, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 
0x5f, 0xfd, 0xf0, 0x00, 0x00, 0x00, 0x3c, 0x1e, 0xfe, 0x00, 0x00, 0x00, 0x7a, 0x2f, 0x00, 0x00,
};


/* --------- GAME SPRITES ---------- */
const unsigned char dinoJump [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x60, 0x00, 
0x00, 0x00, 0x1f, 0xf1, 0xf0, 0x00, 0x00, 0x00, 0x3b, 0xff, 0xb8, 0x00, 0x00, 0x00, 0x7f, 0xdf, 
0xfc, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd8, 0x00, 0x00, 0x03, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x0f, 
0xff, 0xfe, 0x00, 0x00, 0x00, 0x7d, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x07, 0x80, 0x00, 

};

const unsigned char obstacle1 [] PROGMEM = {
0x00, 0x00, 0x1e, 0x00, 0x2f, 0x00, 0x5e, 0x80, 0x5f, 0xc0, 0xb7, 0xc0, 
};

const unsigned char obstacle2 [] PROGMEM = {
0x14, 0x00, 0x08, 0x00, 0x52, 0x00, 0x34, 0x00, 0x69, 0x40, 0xf0, 0x80, 
};

const unsigned char poop [] PROGMEM = {
0x80, 0x88, 0x01, 0x81, 0x02, 0xe0, 0x27, 0x10, 0x0b, 0xf0, 0x1c, 0x08, 
};


#define WALKSIZE 6
//const unsigned char* const dinoWalk[WALKSIZE] PROGMEM = {
const unsigned char* dinoWalk[WALKSIZE] = {
      //dinoWalk0,dinoWalk0,dinoWalk1,dinoWalk1,dinoWalk2,dinoWalk2,
      //dinoWalk3,dinoWalk3,dinoWalk4,dinoWalk4,dinoWalk5,dinoWalk5
      dinoWalk0,dinoWalk1,dinoWalk2,
      dinoWalk3,dinoWalk4,dinoWalk5
    };
int walkPos=0;
int walkXPos=0;
bool walkAnimReverse=false;
bool walkRight=false;
int walkDirOffset=2;



// EATING

const unsigned char eating1 [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 
0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xe0, 0x00, 0x00, 0x00, 
0x7f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x01, 0xff, 0xff, 0xfc, 0x00, 
0x00, 0x03, 0x7c, 0x7f, 0xfe, 0x00, 0x00, 0x02, 0xf9, 0xff, 0xfe, 0x00, 0x00, 0x0c, 0xf3, 0xff, 
0xff, 0x00, 0x00, 0x1f, 0xf4, 0x7f, 0xff, 0x80, 0x00, 0x7f, 0xf0, 0x7f, 0xff, 0xc0, 0x00, 0xff, 
0xf8, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xe0, 
0x1f, 0xe7, 0xff, 0xe0, 0xff, 0xe0, 0x3f, 0xdf, 0xff, 0xde, 0xff, 0xf0, 0x7f, 0xbf, 0xff, 0xbf, 
0x7f, 0xf0, 0x7f, 0x7f, 0xfe, 0x77, 0xbf, 0xf8, 0x7f, 0x7f, 0xf9, 0xf7, 0xbf, 0xfc, 0x3f, 0xff, 
0xe7, 0xef, 0xbf, 0xfe, 0x5f, 0xfe, 0x1f, 0x1f, 0xbf, 0xff, 0x67, 0xf1, 0xf9, 0x1f, 0xbf, 0xff, 
0x38, 0x0f, 0xe8, 0x3f, 0xbf, 0xff, 0x1f, 0xff, 0xe0, 0x3f, 0xbf, 0xff, 0x0e, 0xfe, 0x40, 0xbf, 
0x6f, 0xff, 0x04, 0x54, 0x00, 0xff, 0x57, 0xff, 0x00, 0x10, 0x01, 0xfe, 0xab, 0xff, 0x00, 0x18, 
0x01, 0xfd, 0x55, 0xff, 0x00, 0x18, 0x05, 0xfa, 0xaa, 0xff, 0x00, 0x1d, 0x27, 0xf1, 0x55, 0x5f, 
0x00, 0x0f, 0x7f, 0xe0, 0xaa, 0xaf, 0x00, 0x07, 0xff, 0x80, 0x55, 0x57, 0x00, 0x03, 0xfe, 0x00, 
0x2a, 0xab, 0x00, 0x01, 0xf0, 0x00, 0x15, 0x55, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xaa, 0x00, 0x00, 
0x00, 0x00, 0x05, 0x55, 0x00, 0x00, 0x00, 0x00, 0x02, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 

};
const unsigned char eating2 [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 
0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xe0, 0x00, 0x00, 0x00, 
0x7f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x01, 0xff, 0xff, 0xfc, 0x00, 
0x00, 0x03, 0x7c, 0x7f, 0xfe, 0x00, 0x00, 0x02, 0xf9, 0xff, 0xfe, 0x00, 0x00, 0x0c, 0xf3, 0xff, 
0xff, 0x00, 0x00, 0x1f, 0xf4, 0x7f, 0xff, 0x80, 0x00, 0x7f, 0xf0, 0x7f, 0xff, 0xc0, 0x00, 0xff, 
0xf8, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xe0, 
0x1f, 0xe7, 0xff, 0xe0, 0xff, 0xe0, 0x3f, 0xdf, 0xff, 0xde, 0xff, 0xf0, 0x7f, 0xbf, 0xff, 0xbf, 
0x7f, 0xf0, 0x7f, 0x7f, 0xfe, 0x77, 0xbf, 0xf8, 0x7f, 0x7f, 0xf9, 0xf7, 0xbf, 0xfc, 0x3f, 0xff, 
0xe7, 0xef, 0xbf, 0xfe, 0x5f, 0xfe, 0x1f, 0x1f, 0xbf, 0xff, 0x67, 0xf1, 0xf9, 0x1f, 0xbf, 0xff, 
0x38, 0x0f, 0xe8, 0x3f, 0xbf, 0xff, 0x1f, 0xff, 0xe1, 0x7f, 0x3f, 0xff, 0x0e, 0xfe, 0x41, 0xfe, 
0xef, 0xff, 0x04, 0xd4, 0x0b, 0xfd, 0x57, 0xff, 0x00, 0xd4, 0x0f, 0xfa, 0xab, 0xff, 0x00, 0x60, 
0x9f, 0xf5, 0x55, 0xff, 0x00, 0x75, 0xff, 0xca, 0xaa, 0xff, 0x00, 0x3f, 0xff, 0x05, 0x55, 0x5f, 
0x00, 0x1f, 0xfc, 0x02, 0xaa, 0xaf, 0x00, 0x07, 0xc0, 0x01, 0x55, 0x57, 0x00, 0x00, 0x00, 0x00, 
0xaa, 0xab, 0x00, 0x00, 0x00, 0x00, 0x15, 0x55, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xaa, 0x00, 0x00, 
0x00, 0x00, 0x05, 0x55, 0x00, 0x00, 0x00, 0x00, 0x02, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 

};
const unsigned char eating3 [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 
0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xe0, 0x00, 0x00, 0x00, 
0x7f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x01, 0xff, 0xff, 0xfc, 0x00, 
0x00, 0x03, 0x7c, 0x7f, 0xfe, 0x00, 0x00, 0x02, 0xf9, 0xff, 0xfe, 0x00, 0x00, 0x0c, 0xf3, 0xff, 
0xff, 0x00, 0x00, 0x1f, 0xf4, 0x7f, 0xff, 0x80, 0x00, 0x7f, 0xf0, 0x7f, 0xff, 0xc0, 0x00, 0xff, 
0xf8, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xe0, 
0x1f, 0xe7, 0xff, 0xe0, 0xff, 0xe0, 0x3f, 0xdf, 0xff, 0xde, 0xff, 0xf0, 0x7f, 0xbf, 0xff, 0xbf, 
0x7f, 0xf0, 0x7f, 0x7f, 0xfe, 0x77, 0xbf, 0xf8, 0x7f, 0x7f, 0xf9, 0xf7, 0xbf, 0xfc, 0x3f, 0xff, 
0xe7, 0xef, 0xbf, 0xfe, 0x5f, 0xfe, 0x1f, 0xdf, 0xbf, 0xff, 0x67, 0xf1, 0xff, 0x3f, 0xbf, 0xff, 
0x38, 0x0f, 0xfc, 0xff, 0xbf, 0xff, 0x1f, 0xff, 0xf3, 0xff, 0x3f, 0xff, 0x0f, 0xff, 0xcf, 0xfe, 
0xef, 0xff, 0x00, 0x38, 0x3f, 0xf9, 0x57, 0xff, 0x07, 0x83, 0xff, 0xea, 0xab, 0xff, 0x01, 0xff, 
0xfe, 0x15, 0x55, 0xff, 0x00, 0xff, 0xf0, 0x0a, 0xaa, 0xff, 0x00, 0x3f, 0xc0, 0x05, 0x55, 0x5f, 
0x00, 0x00, 0x00, 0x02, 0xaa, 0xaf, 0x00, 0x00, 0x00, 0x05, 0x55, 0x57, 0x00, 0x00, 0x00, 0x02, 
0xaa, 0xab, 0x00, 0x00, 0x00, 0x01, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 
0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 

};


const unsigned char* eating[4] = {
      eating1,eating2,eating3,eating2
    };

//const unsigned char apple0 [] PROGMEM = {
const unsigned char apple [] PROGMEM = {
0x00, 0x01, 0xf0, 0x00, 0x07, 0xe0, 0x00, 0x0f, 0xe0, 0x3f, 0x1f, 0xc0, 0x00, 0xdf, 0x80, 0x00, 
0x20, 0x00, 0x0f, 0xd7, 0xf0, 0x3f, 0xff, 0xfc, 0x7f, 0xff, 0xfe, 0x78, 0xff, 0xfe, 0xf0, 0x7f, 
0xff, 0xe0, 0x7f, 0xff, 0xe0, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xfe, 0x7f, 0xff, 0xfe, 0x3f, 0xff, 0xfc, 0x1f, 
0xff, 0xf8, 0x0f, 0xff, 0xf0, 0x07, 0xc3, 0xe0, 
};


const unsigned char steak [] PROGMEM = {
0x0f, 0xe0, 0x00, 0x3f, 0xf8, 0x00, 0x31, 0xfe, 0x00, 0x6e, 0x7f, 0x00, 0xd1, 0x7f, 0x80, 0xa0, 
0xbf, 0x80, 0xa0, 0xbf, 0xc0, 0xa0, 0xbf, 0xc0, 0xd1, 0x3f, 0xc0, 0xae, 0xff, 0xe0, 0xd1, 0xff, 
0xe0, 0xef, 0xff, 0xe0, 0x77, 0xff, 0xf0, 0x7b, 0xff, 0xd0, 0x3d, 0xff, 0x78, 0x1e, 0xf9, 0xfe, 
0x0f, 0x67, 0xff, 0x07, 0x7f, 0xff, 0x03, 0x9f, 0xfc, 0x03, 0xc3, 0xf9, 0x01, 0xf8, 0xc3, 0x00, 
0xff, 0x1e, 0x00, 0x1f, 0xfe, 0x00, 0x01, 0xfc, 
};



//ground
int grassXPos=0;
float treesXPos=-20;
//sky
float couldsXPos=0;
const int sunRadius=3;
bool sunOrMoon = false;
const int moonShadow=2;
float sunXPos=-2*sunRadius;
//clouds
const int cloud1Width=32;
float cloud1XPos=display.width()+cloud1Width;


int stars [6][2];




// menus
bool menuOpened = false;
int menu=0;
int subMenu=1;
bool menuDepth=false;
bool justOpened=false;
#define MENUSIZE 8
#define STRING_SIZE 11

const char mainMenu[MENUSIZE][8][STRING_SIZE] PROGMEM = {
  {"food","apple","steak","water",NULL},
  {"game",NULL},
  {"sleep",NULL},
  {"clean",NULL},
  {"doctor",NULL},
  {"discipline",NULL},
  {"stats","hunger","happiness","health","discipline","weight","age",NULL},
  {"settings","sound", "save", NULL},
};

/* ------- PET STATS ------- */

float hunger= EEPROM.read(hunger_address);
float happiness= EEPROM.read(happiness_address);
float health=  EEPROM.read(health_address);
float discipline=  EEPROM.read(discipline_address);
float weight=  EEPROM.read(weight_address);
float age=  EEPROM.read(age_address);

//settings
bool soundEnabled=true;

int action=0;
int setting=0;

bool notification = false;
int notificationBlink=0;
bool dead=false;

bool sleeping=false;

//game
bool game=false;
bool paused=false;
bool gameOver=false;
int score = 0;
int hiScore = EEPROM.read(hi_address);
int level=0;
bool newHiScore = false;
bool jumping=false;
bool jumpUp=true;
int jumpPos=0;
bool obstacle1show = false;
bool obstacle2show = false;
int obstacle1XPos = 0;
int obstacle2XPos = 0;


float poopometer=0;
int poops [3] = {
  0,0,0,
};

#define ACTIVATED LOW

void setup() {
  pinMode(button1Pin, INPUT);
  pinMode(button2Pin, INPUT);
  pinMode(button3Pin, INPUT);

  digitalWrite(button1Pin, HIGH);
  digitalWrite(button2Pin, HIGH);
  digitalWrite(button3Pin, HIGH);
  // or just 
  // pinMode(button1Pin, INPUT_PULLUP)
  // etc

  pinMode(sound, OUTPUT);

  pinMode(13,OUTPUT);

  randomSeed(analogRead(0));

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();

  // splash
  display.setTextColor(WHITE);
  //display.println(F("jakobdesign presents")); 
  display.print(F(" jakobdesign presents")); 
  display.drawBitmap(15, 24, splash1 , 48, 26, WHITE);
  display.drawBitmap(48, 24, splash2 , 80, 40, WHITE);
  display.display();

  //splash tone

  tone(sound,500,200);
  delay(200);
  tone(sound,1000,200);
  delay(400);
  tone(sound,700,200);
  delay(200);
  tone(sound,1100,200);

  delay(2200);
  // end splash


  display.clearDisplay();
}



void loop() {

  button1State = digitalRead(button1Pin);
  button2State = digitalRead(button2Pin);
  button3State = digitalRead(button3Pin);
  //char* str = "";

  if(!dead){
    /* -------- MODIFY PET STATS -------- */
    // TODO: different gradients regarding to age
    if(sleeping){
      hunger-=0.00005;
      poopometer+=0.00005;
      if(happiness-0.0001>0){
        happiness-=0.0001;
      }
      health-=0.00005+countPoops()*0.0001;
      if(discipline-0.0001>0){
        discipline-=0.0001;
      }
    }else{
      hunger-=0.00025;
      poopometer+=0.00025;
      if(happiness-0.0002>0){
        happiness-=0.0002;
      }
      health-=0.0001+countPoops()*0.0001;
      if(discipline-0.0002>0){
        discipline-=0.0002;
      }
      //discipline-=0.02;
    }
    age+=0.000025;
    EEPROM.write(age_address, age);

    //diarrhea :) for testing
    //poopometer+=0.005;

    //health-=1;
    //health-=countPoops()*0.0001;
    //health-=countPoops()*0.05;

    if(poopometer>=10){
      poopometer=countPoops();
      poops[round(poopometer)]=random(20,display.width()+32);
      if(soundEnabled){
        tone(sound,200,50);
      }
      poopometer=0;
    }

    if((hunger>19.99975 && hunger<20.00025) || (happiness>19.9998 && happiness<20.0002) || (health>19.9999 && health<20.0001) && soundEnabled){
      if(soundEnabled){
        tone(sound,200,50);
      }
    }


    if(hunger<=20 || countPoops()>0 || happiness<=20 || health<=20){
      notification=true;  
    }
    if(hunger>20 && countPoops()==0 && happiness>20 && health>20){
      notification=false;  
      digitalWrite(13,LOW);
    }

    if(hunger<=0 || health<=0 || happiness<=0){
      dead=true;
      if(soundEnabled){
        tone(sound,500,500);
        delay(550);
        tone(sound,400,500);
        delay(550);
        tone(sound,300,600);
      }
    }


    display.clearDisplay();
    display.setCursor(0,0);


    /* ------- BUTTON PRESS ACTIONS ------- */

    /* ------- BUTTON 1 - MENU ------- */
    if(button1State==ACTIVATED){

      // JUMP IN GAME
      if(game){

        if(!jumping && !paused){
          if(soundEnabled){
            tone(sound,200,50);
          }
          jumping=true;
        }

      }else{
        // MENU

        if(soundEnabled){
          tone(sound,300,80);
        }

        if(!menuOpened){
          menuOpened=true;
        }else{
          if(menuDepth){

            if((const char*)pgm_read_word(&(mainMenu[menu][subMenu+1]))==NULL){
              subMenu=1;
            }else{
              ++subMenu;
            }
            setting=100*(menu+1)+subMenu;
          }else{
            if(menu==MENUSIZE-1){
              menu=0;
            }else{
              ++menu;
            }

            if((const char*)pgm_read_word(&(mainMenu[menu][1]))!=NULL){
              subMenu=1;

              justOpened=true;
            }
            setting=100*(menu+1)+subMenu;
          }
        }

        delay(60);

      }

    }
    /* ------- BUTTON 2 - SELECT ------- */
    if(button2State==ACTIVATED){

      if(game){
        if(!gameOver){
          paused=!paused;
          if(soundEnabled){
            tone(sound,600,80);
          }
          delay(60);
        }

      }else{

        if(soundEnabled){
          tone(sound,600,80);
        }

        if(menuOpened){

          if(subMenu!=1 && (const char*)pgm_read_word(&(mainMenu[menu][1][0]))!=NULL){
            action=100*(menu+1)+subMenu; 
          }
          if(subMenu==1 && (const char*)pgm_read_word(&(mainMenu[menu][1][0]))==NULL){
            action=100*(menu+1)+subMenu;
          }
          if(subMenu==1 && (const char*)pgm_read_word(&(mainMenu[menu][1][0]))!=NULL && menuDepth){
            action=100*(menu+1)+subMenu; 
          }
          if((const char*)pgm_read_word(&(mainMenu[menu][1][0]))!=NULL){
            setting=100*(menu+1)+subMenu;
            menuDepth=true;
          }

        }else{
          action=NULL;

          menuOpened=true;
          menuDepth=true;
          subMenu=1;
          menu=6;
          action=701;
          setting=701;
        }
        justOpened=false;

        delay(60);

      }

    }
    /* ------- BUTTON 3 - BACK ------- */
    if(button3State==ACTIVATED){
      if(soundEnabled){
        tone(sound,1000,80);
      }

      if(game || gameOver){
        walkPos=0;
        walkXPos=0;
        walkAnimReverse=false;
        walkRight=true;
        walkDirOffset=0;
        treesXPos=-20;
        grassXPos=0;
        obstacle1show=false;
        obstacle2show=false;
        jumping=false;
        jumpPos=0;
        jumpUp=true;
        game=false;
        score=0;
        newHiScore=false;
        gameOver=false;
        level=0;
        paused=false;
      }else{
        if(!menuDepth){
          menuOpened=false;
          menu=0;
          setting=0;
        }else{
          menuDepth=false;
          setting=100*(menu+1)+1;
        }
        action=NULL;
        subMenu=1;
      }


      delay(60);
    }



    /* ------- SCENERY AND WALKING ------- */

    //draw sun
    sunXPos+=0.1;
    if(sunXPos>display.width()+2*sunRadius){
      sunXPos=-2*sunRadius;
      sunOrMoon=!sunOrMoon;
    }
    if(sleeping) {sunOrMoon=true;}

    if(sleeping){
      sunOrMoon=true;
    }

    if(!sunOrMoon){
      display.fillCircle(sunXPos,2*sunRadius,sunRadius,WHITE);
    }else{
      display.fillCircle(sunXPos,2*sunRadius,sunRadius,WHITE);
      display.fillCircle(sunXPos-moonShadow,2*sunRadius,sunRadius,BLACK);
      //if(walkPos == 5){
      if(round(cloud1XPos) % 5 == 0){
        for(int i=0;i<6;i++){
          stars[i][0]=random(0,display.width());
          stars[i][1]=random(0,10);
        }
      }else{
        for(int i=0;i<6;i++){

          display.drawPixel(stars[i][0],stars[i][1],WHITE);
        }
      }
    }

    //cloud 1
    cloud1XPos-=0.3;
    if(cloud1XPos<-cloud1Width){
      cloud1XPos=display.width()+cloud1Width;
    }
    display.drawBitmap(cloud1XPos, 5, cloud2 , cloud1Width, 5, WHITE);


    //mountains
    display.drawBitmap(0, 7, mountains , 128, 16, WHITE);

    //walk and move ground perspective

    if(game){


      /* ------ GAME -----*/
      level=round(score/10);

      if(jumping && !gameOver && !paused){
        if(jumpUp){
          jumpPos=jumpPos+1+level;
          if(jumpPos>=12){
            jumpUp=false;
          }
        }else{
          //jumpPos--;
          jumpPos=jumpPos-1-level;
          if(jumpPos<=0){
            jumpUp=true;
            jumping=false;
            if(soundEnabled){
              tone(sound,100,50);
            }
            score+=1;
          }
        }
      }


      if(!gameOver && !paused){
        if(walkAnimReverse){
          walkPos-=1;
          if(walkPos==-1){walkPos=0; walkAnimReverse=false;}
        }else{
          walkPos+=1;
          if(walkPos==3){walkPos=2; walkAnimReverse=true;}
        }



        walkXPos+=2;
        grassXPos+=4;
        treesXPos=treesXPos+1+level;
        obstacle1XPos=obstacle1XPos+2+level;
        obstacle2XPos=obstacle2XPos+2+level;


        if(!jumping && 
            (
              (obstacle1show && display.width()-obstacle1XPos>=20 && display.width()-obstacle1XPos<=46)
              || 
              (obstacle2show && display.width()-obstacle2XPos>=20 && display.width()-obstacle2XPos<=46)
            )
          ){
          gameOver=true;
          jumping=true;
          jumpPos=-2;
          if(soundEnabled){
            tone(sound,500,40);
            delay(50);
            tone(sound,350,40);
            delay(50);
            tone(sound,200,60);
          }

          if(score>hiScore){
            hiScore=score;
            EEPROM.write(hi_address, hiScore);
            newHiScore=true;
          }
          if(happiness+15<100){
            happiness+=15;
          }else{
            happiness=100;
          }
          health-=1;
          if(weight-score*0.0025>5){
            weight-=score*0.0025;
            EEPROM.write(weight_address, weight);
          }


        }
      }

      if(walkXPos==display.width()){
        walkXPos=0;
      }
      if(grassXPos==display.width()){grassXPos=0;}
      if(treesXPos==display.width()){treesXPos=-128;}

      if(jumping){
        display.drawBitmap(10, 26-jumpPos, dinoJump , 48, 24, WHITE);
      }else{
        display.drawBitmap(10, 26, dinoWalk[walkPos] , 48, 24, WHITE);
      }

      for(int i=0;i<display.width()/4+1;i++){
        display.drawBitmap(-walkXPos+i*8, 50, grass , 8, 6, WHITE);
      }


      // obstacles 1

      if(obstacle1XPos-16>=display.width()){
        obstacle1XPos=0;
        obstacle1show=false;
      }
      if(!obstacle1show && random(1,10)==1 && obstacle2XPos > 40){
        obstacle1show = true;
        obstacle1XPos=0;
      }
      if(obstacle1show){
        display.drawBitmap(display.width()-obstacle1XPos, 44, obstacle1 , 16, 6, WHITE);
      }

      // obstacles 2
      if(obstacle2XPos-16>=display.width()){
        obstacle2XPos=0;
        obstacle2show=false;
      }
      if(!obstacle2show && random(1,10)==1 && obstacle1XPos > 40){
        obstacle2show = true;
        obstacle2XPos=0;
      }

      if(obstacle2show){
        display.drawBitmap(display.width()-obstacle2XPos, 44, obstacle2 , 16, 6, WHITE);
      }




      //draw front grass
      for(int i=0;i<display.width()/16+1;i++){
        display.drawBitmap(-grassXPos+i*32, 60, grass_front , 32, 8, WHITE);
      }
      //draw trees
      display.drawBitmap(-treesXPos, 23, trees , 112, 20, WHITE);

      if(!gameOver){
        display.setCursor(0,56);
        display.setTextColor(WHITE);
        display.print(F("lvl: "));
        display.print(level);
        display.setCursor(64,56);
        display.setTextColor(WHITE);
        display.print(F("pts: "));
        display.print(score);
      }

      if(paused && round(cloud1XPos)%2==0){
        display.fillRect(24,11,80,15,BLACK);
        display.fillRect(25,12,78,13,WHITE);
        display.setCursor(47,15);
        display.setTextColor(BLACK);
        display.println(F("PAUSED"));
      }

      /* ---------- END GAME ----------*/

    }else{

      /* ------ NO GAME -----*/
      if(!sleeping){
        display.drawBitmap(walkXPos, 26, dinoWalk[walkPos+walkDirOffset] , 48, 24, WHITE);
      }else{
        display.drawBitmap(walkXPos, 29, dinoWalk[walkPos+walkDirOffset] , 48, 24, WHITE);
        if(walkRight){
          if(round(cloud1XPos) % 3 ==0){
            display.setCursor(walkXPos+48,36);
            display.print(F("Z"));
          }else{
            display.setCursor(walkXPos+46,38);
            display.print(F("z"));
          }
        }else{
          if(round(cloud1XPos) % 3 ==0){
            display.setCursor(walkXPos-4,36);
            display.print(F("Z"));
          }else{
            display.setCursor(walkXPos-2,38);
            display.print(F("z"));
          }
        }
      }
      if(walkRight){
        if(!sleeping){
          walkXPos+=1;
          grassXPos+=2;
          treesXPos+=0.5;
        }
        if(walkXPos>80){walkRight=false; walkDirOffset=3;}
      }else{
        if(!sleeping){
          walkXPos-=1;
          grassXPos-=2;
          treesXPos-=0.5;
        }
        if(walkXPos<0){walkRight=true; walkDirOffset=0;}  
      }

      //draw grass (ground)
      for(int i=0;i<2*display.width()/4;i++){
        display.drawBitmap(-walkXPos+i*8, 50, grass , 8, 6, WHITE);
      }
      // draw poops
      for(int i=0; i<3; i++){
        if(poops[i]>0){
          display.drawBitmap(-walkXPos+poops[i], 44, poop , 16, 6, WHITE);
        }
      }
      //draw front grass
      for(int i=0;i<2*display.width()/16;i++){
        display.drawBitmap(-grassXPos+i*32, 56, grass_front , 32, 8, WHITE);
      }
      //draw trees
      display.drawBitmap(-treesXPos, 23, trees , 112, 20, WHITE);



      if(!sleeping){
        if(walkAnimReverse){
          --walkPos;
          if(walkPos==-1){walkPos=0; walkAnimReverse=false;}
        }else{
          ++walkPos;
          if(walkPos==3){walkPos=2; walkAnimReverse=true;}
        }
      }

    }


    /* ------- MENUS AND ACTIONS ------- */
    //render menu
    if(menuOpened and !game){
      display.fillRect(0,0,display.width(),30,BLACK);
      display.drawRect(0,0,display.width(),29,WHITE);
      display.fillRect(1,1,display.width()-2,27,BLACK);
      display.drawRect(0,0,display.width(),12,WHITE);
      display.setCursor(8,2);
      display.setTextSize(1);
      if(menuDepth){
        display.fillRect(0,0,display.width(),12,WHITE);
        display.fillRect(1,18,1,5,WHITE);
        display.fillRect(2,19,1,3,WHITE);
        display.fillRect(3,20,1,1,WHITE);
        display.setTextColor(BLACK,WHITE);
      }else{
        display.fillRect(1,3,1,5,WHITE);
        display.fillRect(2,4,1,3,WHITE);
        display.fillRect(3,5,1,1,WHITE);
        display.setTextColor(WHITE);
      }
      char oneItem [STRING_SIZE];
      memcpy_P (&oneItem, &mainMenu[menu][0], sizeof oneItem);
      //display.println(getItem(menu,0));
      display.println(oneItem);
      if(subMenu){
        display.setTextColor(WHITE);
        display.setCursor(8,16);
        char subItem [STRING_SIZE];
        memcpy_P (&subItem, &mainMenu[menu][subMenu], sizeof subItem);
        //display.println(getItem(menu,subMenu));
        display.println(subItem);
      }
    }

    //do actions

    if(action>0){


      if((action==101 || action==102 || action==103) && !sleeping && random(1,(11-round(discipline/10)))==1 ){
        //95-100 discipline = 100% chance to feed
        //85-95 discipline = 50% chance
        //75-85 discipline = 33.33% chance
        //65-75 discipline = 25% chance
        //55-65 discipline = 20% chance
        //45-55 discipline = 16.67% chance
        //35-45 discipline = 14.28% chance
        //25-35 discipline = 12.5% chance
        //15-25 discipline = 12.5% chance
        //5-15 discipline = 10% chance
        //0-5 discipline = 9% chance

        //animate eating

        display.fillRect(0,0,display.width(),display.height(),BLACK);
        for(int j=0;j<3;j++){
          for(int i=0; i<4; i++){
            display.clearDisplay();
            switch(action){
              case 101:
                //apple
                display.drawBitmap(50,40,apple,24,24,WHITE);
                if(j>0) display.fillCircle(76,54,12,BLACK);
                if(j==2) display.fillCircle(47,55,12,BLACK);
                break;
              case 102:
                //steak
                display.drawBitmap(50,40,steak,24,24,WHITE);
                if(j>0) display.fillCircle(76,59,13,BLACK);
                if(j==2) display.fillCircle(60,63,13,BLACK);
                break;
              case 103:
                //water ripples
                display.drawCircle(80,55,1+1*i,WHITE);
                display.drawCircle(80,55,5+2*i,WHITE);
                display.drawCircle(80,55,10+4*i,WHITE);
                break;


            }
            display.drawBitmap(80,24,eating[i],48,40,WHITE);
            delay(150);
            display.display();
          }
        }



        switch(action){
          //apple
          case 101:
            if(hunger+10>100){
              hunger=100;
              weight+=1;
            }else{
              hunger+=10;
            }
            if(health+1<=100){
              health+=1;
            }
            poopometer+=0.02;
            EEPROM.write(hunger_address, hunger);
            EEPROM.write(weight_address, weight);
            break;
          //steak
          case 102:
            if(hunger+20>100){
              hunger=100;
              weight+=2;
            }else{
              hunger+=20;
              weight+=1;
            }
            if(health-1>0){
              health-=1;
            }
            poopometer+=0.05;
            EEPROM.write(hunger_address, hunger);
            EEPROM.write(weight_address, weight);
            break;
          //water
          case 103:
            if(hunger+5<=100){
              hunger+=5;
            }
            poopometer+=0.01;
            EEPROM.write(hunger_address, hunger);
            EEPROM.write(weight_address, weight);
            break;

        }
      }else{
        if(action==101 || action==102 || action==103){
          if(soundEnabled){
            tone(sound,500,200);
            delay(250);
          }
        }
      }

      switch(action){
        case 201:
          //game
          if(!sleeping && health>20){
            game=true;
            walkPos=0;
            walkXPos=0;
            walkAnimReverse=false;
            walkRight=false;
            walkDirOffset=2;
            treesXPos=-20;
            grassXPos=0;
          }
          break;
        case 301:
          //sleep
            sleeping=!sleeping;
            if(!sleeping) {sunOrMoon=false;}else{
              for(int i=0;i<6;i++){
                stars[i][0]=random(0,display.width());
                stars[i][1]=random(0,10);
              }
            }

          break;
        case 401:
          //bath
            resetPoops();
          break;
        case 501:
          //doctor
            if(health<60){
              health=100;
              for(int i=0;i<5;i++){
                display.clearDisplay();
                if(i%2!=0){
                  display.fillRect(32,23,64,16,WHITE);
                  display.fillRect(56,0,16,64,WHITE);
                }
                display.display();
                EEPROM.write(health_address, health);
                delay(300);
              }
            }

          break;
        case 601:
          //discipline
          if(action==601 && !sleeping){
            if(discipline+12<=100){
              discipline+=12;
            }else{
              discipline=100;
            }
            if(happiness-3>0){
              happiness-=3;
            }
            delay(150);
            EEPROM.write(happiness_address, happiness);
            for(int i=0;i<5;i++){
              if(soundEnabled){
                tone(sound,200*i,100);
              }
              display.setCursor(100+3*i,32);
              display.print(F("!"));
              display.display();
              delay(150);
            }

          }
          break;

          case 801:
            soundEnabled=!soundEnabled;  
          break; 

          case 802:
            EEPROM.put(age_address,age);
            EEPROM.put(weight_address, (weight));
            EEPROM.write(hunger_address,hunger);
            EEPROM.write(discipline_address, discipline);
            EEPROM.write(happiness_address, happiness);
            EEPROM.write(health_address, health);
          break;
      }
      action=0;
    }

    //display settings
    if(setting>0 and !game){
      display.setCursor(8,16);
      if(setting==201){
        display.println(F("increase happiness"));
      }
      if(setting==301){
        display.println(F("get some rest"));
      }
      if(setting==401){
        display.println(F("keep it healthy"));
      }
      if(setting==501){
        display.println(F("when health is bad"));
      }
      if(setting==601){
        display.println(F("get smarter"));
      }
      if(setting==701 || setting==702 || setting==703 || setting==704){
        display.drawRect(70,17,52,7,WHITE);
      }
      if(setting==701){
        drawBar(hunger);
      }
      if(setting==702){
        drawBar(happiness);
      }
      if(setting==703){
        drawBar(health);
      }
      if(setting==704){
        drawBar(discipline);
      }
      if(setting==705 || setting==706 || setting==801){
        display.setCursor(80,16);
      }
      if(setting==705){
        //display.setCursor(80,16);
        display.print(weight,1);
        display.println(F(" t"));
      }
      if(setting==706){
        display.print(age,1);
        display.println(F(" y."));
        EEPROM.write(age_address, age);
      }
      if(setting==801){
        if(soundEnabled){
          display.println(F("on"));
        }else{
          display.println(F("off"));
        }
      }    
      if(setting==802){
      }
    }
    //display notification
    if(notification){
      ++notificationBlink;
      if(notificationBlink==10){
        notificationBlink=0;
      }
      if(notificationBlink!=1){
        display.drawRect(117,28,11,11,WHITE);
        display.setTextColor(WHITE);
        digitalWrite(13,LOW);
      }else{
        display.fillRect(117,28,11,11,WHITE);
        display.setTextColor(BLACK);
        digitalWrite(13,HIGH);
      }
      display.setCursor(120,30);
      display.println(F("!"));
      if(dead){
         digitalWrite(13,LOW);
      }
    }

    // GAME OVER
    if(gameOver){



      display.fillRect(15,11,98,43,BLACK);
      display.drawRect(16,12,96,41,WHITE);
      display.fillRect(16,12,96,13,WHITE);
      display.setCursor(36,15);
      display.setTextColor(BLACK);
      display.println(F("GAME OVER"));
      display.setTextColor(WHITE);
      display.setCursor(21,29);
      if(newHiScore){
        display.println(F("NEW HI-SCORE!"));
        display.setCursor(21,40);
      }else{
        display.println(F("SCORE:"));
        display.setCursor(21,40);
      }
      display.println(score);



    }

    display.display();

  }else{
    //dead...
    display.clearDisplay();
    display.setCursor(0,0);
    display.setTextColor(WHITE);
    display.println(F("Pet died...\n\nPress button 1\nto restart"));
    display.display();

    if(button1State==HIGH){
      if(soundEnabled){
        tone(sound,300,80);
        delay(200);
      }
      noTone(sound);
      asm volatile ("  jmp 0");
    }
  }
}









void drawBar(float value){
  display.fillRect(72,19,48*value/100,3,WHITE);
}

char* getItem(int menu, int index){
  char oneItem [STRING_SIZE];
  memcpy_P (&oneItem, &mainMenu[menu][index], sizeof oneItem);  
  return oneItem;
}

int countPoops(){
  int poopsCnt = 0;
  for(int i=0; i<3; i++){
    if(poops[i]>0){
      ++poopsCnt;
    }
  }
  return poopsCnt;
}

void resetPoops(){
  for(int i=0; i<3; i++){
    poops[i]=0;
  }
}