Virtual Tamaguino - Tamagotchi Arduino Clone Mixed in VBB © MIT

Try out the cool Tamaguino Dino Virtual Pet Tamagotchi pet clone for the Arduino the easy way. With mixed reality virtual hardware by VBB!

  • 2,742 views
  • 0 comments
  • 8 respects

Components and supplies

Apps and online services

About this project

Introducing Virtual Breadboard Avatar for Arduino UNO

Virtual Breadboard is a platform for virtualizing the hardware your microcontrollers need to run their firmware applications.

Virtual Avatars interface your micro in-circuit mixing virtual and real hardware.

The VBBMicro-K42A328P is a VBB Avatar for the Arduino UNO and drops into the socket of the UNO replacing the DIP28 ATMega328P.

Virtualizing Tamaguino

Tamguino is a Tamagotchi clone for Arduino developed by Alojz Jakob and released for free under the GNU General Public License.

Here is the original project Original Tamaguino Project

The Tamagotchi is the original Virtual Pet and Tamaguino enthusiastically reproduces it's features for the Arduino. All you need is to make the hardware.

Your Virtual Virtual Pet

For VBB users with the VBB Avatar for Arduino you can easily virtualize the hardware instead to help you get started while your parts arrive or as a starting point for your own mods or to just play around with for fun.

VBB Built-in Example

Even easier than making your own Virtual Hardware is using Virtual Hardware already created by someone else!

Tamaguino is a built VBB example! Just open and run.

The Full Tutorial

Here's how to roll you own though. The full tutorial walks you through creating the virtual hardware from scratch.

Tutorial Highlights

Why Tamagotchi clone?

Alojz say's

When I was a kid and went to primary school, something happened. Invasion of cool egg-shaped digital pets! Everyone had one. Some had original Bandai toys, some had cheap chinese copies (which were better!) After some time I became interested in programming, and since then I was obsessed with building virtual pet of my own.

Successfully Ported to Arduino

The hard work paid off and Alojz successfully ported his earlier linux/vb6 versions to fit the ATMega328 device used on the Arduino UNO and Pro Mini 328. Amazing work.

Changes to work with Virtual Hardware

Alojz original project uses an I2C SSD1306 OLED but VBB only supports an SPI SSD1306 OLED ( as at v1.2.28 ) so a few tweaks were needed

  • Changed the Adafruit driver constructor to use SPI version
  • Changed the Pin definitions

The project built! at 99% ( only just ) with the latest Adafruit libraries ( SSD1306 v2.0.2 and Adafruit GFX 1.7.0 )

You can download the edited sketch from the attachment section below.

VBB Avatar for Arduino

The VBB Avatar replaces the DIP ATmega328p in circuit with a smaller SMD version of the ATmega328p and the VBB Avatar interface chip on a pin compatible DIP28 chip module.

It might be SMD but it's still an ATmega328 so the firmware is 100% compatible plus it runs at real-time - because it's the real micro of course!

Mixed with Real Audio

VBB doesn't support virtualized audio yet ( as at v1.2.28 ) so we use a real speaker. This is a feature not a bug! It's impossible to simulate every single component you will ever need but with Avatars you can mix real components with virtual ones.

Mixed Reality

This is the big idea behind the VBB Avatar concept. You can use virtual hardware for all the advantages it brings but not be dependent on every single component being available.

It's the solution to what I call the 9 out of 10 problem

.. which means a simulation is useless unless you have 10 out of 10 components.. but in a real world project there is almost always at least one component missing and this has held back VBB for years.

Avatars solve this problem.

It is expected most VBB projects will have one or two real components and the use of the speaker is a good example of this.

Wiring Up Part I

Drag and drop the OLED 128x64 SSD1306 component and Arduino Uno Avatar and wire up for SPI. If you are new to VBB you might want to watch the video to see how this is done step by step.

The Arduino Uno Avatar connects to the real Arduino Uno + VBB Avatar chip so you need to select the COM port it connects on. Mine was COM5

Programming the Onboard ATmega328

The VBB Avatar for Arduino has an onboard ATmega328 which can be programmed directly using the Arduino IDE but because the Avatar interface shares the serial port it can be easier to let VBB program the device so VBB can manage swapping the serial port.

This is done by exporting a HEX file from the Arduino IDE and dragging and dropping the hex file onto the Arduino Uno Avatar in VBB.

This also be done at runtime otherwise you would have to stop the VBB virtualization, use the Arduino IDE to download the new firmware and then restart VBB. This is managed for you when you drag and drop the HEX file into VBB instead.

Random Buttons

The Tamaguino runs without any buttons. But it makes random button presses as the pins are floating. Amusing but not very practical. Well at least we know the OLED works!

Wiring Up Part II

Next add the buttons. I used pulldown resistors on pins 2, 3, 4 which are different pins than the original. Hence the sketch also had to be changed to use these new pins.

One thing to note is when using analog signals with Avatars you should mark up input pins with the digital markup pin.

Ready to Play with your Virtual Virtual Pet

Now I just have to figure out how to play??

Tips

  • Left button escapes out of the menu
  • Right button enters the menu and also 'jumps' while playing the game
  • Middle button executes the current menu option

Mod

Use this is a beginning. Create new creatures and features, different graphics, make it harder or easier.

Enjoy!

Code

TamaguinoArduino
/* 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>

 
//#define OLED_RESET 4
//Adafruit_SSD1306 display(OLED_RESET);
 
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for SSD1306 display connected using software SPI (default case):
#define OLED_MOSI  11
#define OLED_CLK   13
#define OLED_DC    9
#define OLED_CS    10
#define OLED_RESET 8
 
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,  &SPI, OLED_DC, OLED_RESET, OLED_CS);

const int LEDPin = 5;

const int button1Pin = 2;
const int button2Pin = 3; 
const int button3Pin = 4; 

const int sound = 6; 

int button1State = 0;
int button2State = 0;
int button3State = 0;
 
// 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 48x26
const unsigned char splash1_packed [] PROGMEM = {
0x00,0xA0,0x01,0x86,0x18,0x41,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,
0x15,0xFF,0xFF,0xFF,0x08,0x00,0x39,0xC0,0x39,0xC0,0x39,0xC0,0x38,0x38,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,0x02,0x10,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,0x80,
};
*/

 
//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",
    //"something",
    NULL
  },
};

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

float hunger=100;
float happiness=100;
float health=100;
float discipline=100;
float weight=1;
float age=0;

//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 = 0;
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,
};

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

  pinMode(LEDPin,OUTPUT);

  randomSeed(analogRead(0));
   
 if(!display.begin(SSD1306_SWITCHCAPVCC)) {
    for(;;); // Don't proceed, loop forever
  }
  
  //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.0000025;

    //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(LEDPin,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==HIGH){
      
      // 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==HIGH){
      
      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==HIGH){
      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;
            newHiScore=true;
          }
          if(happiness+15<100){
            happiness+=15;
          }else{
            happiness=100;
          }
          health-=1;
          if(weight-score*0.0025>5){
            weight-=score*0.0025;
          }
          
          
        }
      }
      
      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);
...

This file has been truncated, please download it to see its full contents.

Schematics

Tamaguino VBB Breadboard
Note the pin-outs have changed compared to the original Tamaguino and a SPI OLED is used in place of an I2C version.
Schematic ok9yjylo4c

Comments

Similar projects you might like

Tamaguino Update with Huge OLED

Project tutorial by Alojz Jakob

  • 2,323 views
  • 1 comment
  • 6 respects

Arduino Game By LCD

Project tutorial by Mohammed Magdy

  • 61,828 views
  • 57 comments
  • 194 respects

Arduino Pong Game - OLED Display

Project tutorial by Nick Koumaris

  • 12,238 views
  • 2 comments
  • 22 respects

Handheld Gaming Console | Arduboy Clone

Project tutorial by Neeraj Rane

  • 4,323 views
  • 4 comments
  • 20 respects

Existential Crisis - Arduino Role-Playing Game Simulator

Project showcase by Cory Potter

  • 1,212 views
  • 0 comments
  • 4 respects
Add projectSign up / Login