Arduino Gaming: Play Deathstar vs X-Wing

My First Experience Playing Games on the Arduino

Ready for some Arduino gaming? Here’s a simple game for the Arduino and Mini-OLED called Deathstar Vs X-Wing. Well, I love Star Wars so this should be a fun project.

The aim is to defeat the Deathstar while piloting an X-wing. “Great! sound perfect”

Components:

To follow along with this guide, you will need the following components:

  • Arduino board (e.g., Arduino Uno, Arduino Nano, etc.)
  • Mini OLED display with compatible interface (I2C)
  • Tactile Switches (X3)
  • Buzzer (X1)
  • Jumper wires
  • Breadboard

Let's Build!

The Circuit:

Assemble your components in the exact same way as shown in the diagram below.

mini game build diagram

The Code:

Holy Cow! This was some bumpy spaghetti code, I have restructured it the best I could, I don’t understand half of it, as a lot is in Lithuanian. I added variables for the buttons and the sound effects, so you can alter the Arduino pins if you need to. Also, I declared the screen size for the 128×64 OLED display as the game was far too big for this screen. But I got it working in the end.

If you’re missing any libraries, you can install them from the Libraries Manager under the IDE’s Tools menu. To learn how to do this you can follow our guide here: How to Install Arduino Libraries

/*********************************************************************
This is an example for our Monochrome OLEDs based on SSD1306 drivers
  Pick one up today in the adafruit shop!
  ------> http://www.adafruit.com/category/63_98
This example is for a 128x32 size display using I2C to communicate
3 pins are required to interface (2 I2C and one reset)
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada  for Adafruit Industries.
BSD license, check license.txt for more information
All text above, and the splash screen must be included in any redistribution
*********************************************************************/
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Fonts/FreeSans9pt7b.h> //#include <Fonts/FreeSans12pt7b.h>
#define OLED_RESET 4 #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 Adafruit_SSD1306 display(128, 64, &Wire, OLED_RESET); int Music=9; int UP=11; int DOWN=12; int FIRE=3; const int c = 261; const int d = 294; const int e = 329; const int f = 349; const int g = 391; const int gS = 415; const int a = 440; const int aS = 455; const int b = 466; const int cH = 523; const int cSH = 554; const int dH = 587; const int dSH = 622; const int eH = 659; const int fH = 698; const int fSH = 740; const int gH = 784; const int gSH = 830; const int aH = 880; const unsigned char PROGMEM dioda16 [] = { 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x3F, 0xF0, 0x3C, 0x00, 0x3C, 0x00, 0xFF, 0x00, 0x7F, 0xFF, 0x7F, 0xFF, 0xFF, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x1F, 0xF0, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00 }; const unsigned char PROGMEM storm [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x07, 0x80, 0x01, 0xE0, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x20, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x30, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x60, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x01, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xD7, 0xFF, 0xFF, 0xE1, 0x00, 0x01, 0xBF, 0xFC, 0x1F, 0xFA, 0x80, 0x01, 0xBF, 0xF1, 0xCF, 0xFA, 0x80, 0x01, 0x3F, 0xC2, 0x37, 0xF7, 0x80, 0x01, 0xEF, 0x9C, 0x01, 0xE7, 0xC0, 0x01, 0xE0, 0x70, 0x06, 0x06, 0x80, 0x01, 0xE0, 0xC0, 0x03, 0x06, 0x80, 0x01, 0xFF, 0x80, 0x01, 0xFF, 0x80, 0x01, 0xF8, 0x00, 0x00, 0x1D, 0xC0, 0x03, 0x70, 0x00, 0x80, 0x0C, 0x60, 0x05, 0xB0, 0x07, 0xF0, 0x08, 0x90, 0x09, 0x10, 0x1F, 0xF8, 0x09, 0xD0, 0x0B, 0x90, 0x1F, 0x7C, 0x03, 0xF0, 0x0F, 0xC0, 0xFC, 0x0F, 0x07, 0x90, 0x0D, 0x43, 0xC0, 0x03, 0x07, 0x90, 0x05, 0x64, 0x00, 0x00, 0xCF, 0x10, 0x07, 0xFC, 0x00, 0x00, 0x26, 0x10, 0x01, 0x80, 0x00, 0x00, 0x10, 0x20, 0x01, 0x00, 0x00, 0x00, 0x0E, 0x40, 0x01, 0x80, 0x07, 0xF0, 0x01, 0x80, 0x00, 0x80, 0x07, 0xC8, 0x00, 0x80, 0x00, 0x80, 0x0B, 0xE8, 0x00, 0x80, 0x00, 0x87, 0x97, 0xE9, 0xE0, 0x80, 0x00, 0x87, 0xDF, 0xEF, 0xA0, 0x80, 0x00, 0x4B, 0xFF, 0xFF, 0xA0, 0x80, 0x00, 0x6B, 0xDF, 0xFB, 0xA3, 0x00, 0x00, 0x24, 0x97, 0xE8, 0x24, 0x00, 0x00, 0x1E, 0x1F, 0xC0, 0x2C, 0x00, 0x00, 0x07, 0xF8, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00 };
void setup() { pinMode(FIRE,INPUT_PULLUP); //shoot pinMode(UP,INPUT_PULLUP); //up pinMode(DOWN,INPUT_PULLUP); //down pinMode(Music,OUTPUT); //sound display.begin(SSD1306_SWITCHCAPVCC, 0x3C); display.display(); display.clearDisplay(); display.setTextSize(0); display.drawBitmap(6, 11,storm, 48,48, 1); display.setFont(&FreeSans9pt7b); display.setTextColor(WHITE); display.setCursor(65,14); display.println("xWing"); display.setFont(); display.setCursor(65,17); display.setTextSize(0); display.println("vs"); display.setCursor(0,0); float voltaza=readVcc()/1000; display.println(voltaza);; display.setFont(&FreeSans9pt7b); display.setCursor(65,39); display.println("Death"); display.setFont(); display.setCursor(65,42); display.println("star "); display.setTextSize(0); display.setCursor(65,55); display.println("by Danko"); display.setCursor(65,20); display.display(); display.setFont(); beep(a, 500); beep(a, 500); beep(a, 500); beep(f, 350); beep(cH, 150); beep(a, 500); beep(f, 350); beep(cH, 150); beep(a, 650); delay(500); delay(500); } int metx=0; int mety=0; int postoji=0; int nep=8; int smjer=0; int go=0; int rx=95; int ry=0; int rx2=95; int ry2=0; int rx3=95; int ry3=0; int bodovi=0; int brzina=3; //speed of bullet int bkugle=1; int najmanja=600; int najveca=1200; int promjer=10; int rx4=95; int ry4=0; int zivoti=5; int poc=0; int ispaljeno=0; int nivo=1; int centar=95; unsigned long pocetno=0; unsigned long odabrano=0; unsigned long trenutno=0; unsigned long nivovrije=0; int poz=30;
void loop() { if(go==0){ display.clearDisplay(); display.drawPixel(50,30,1); display.drawPixel(30,17,1); display.drawPixel(60,18,1); display.drawPixel(55,16,1); display.drawPixel(25,43,1); display.drawPixel(100,43,1); display.drawPixel(117,52,1); display.drawPixel(14,49,1); display.drawPixel(24,24,1); display.drawPixel(78,36,1); display.drawPixel(80,57,1); display.drawPixel(107,11,1); display.drawPixel(150,11,1); display.drawPixel(5,5,1); display.drawPixel(8,7,1); display.drawPixel(70,12,1); display.drawPixel(10,56,1); display.drawPixel(70,25,1); if(poc==0){ pocetno=millis(); odabrano= random(400,1200); poc=1; } trenutno=millis(); //nivoi if((trenutno-nivovrije)>50000){ nivovrije=trenutno; nivo=nivo+1; brzina=brzina+1; //brizna neprijateljevog metka if ( nivo % 2 == 0 ){ bkugle=bkugle+1; promjer=promjer-1; } najmanja=najmanja-50; najveca=najveca-50; } if((odabrano+pocetno)<trenutno){ poc=0; ispaljeno=ispaljeno+1; if(ispaljeno==1){ rx=95; ry=nep;} if(ispaljeno==2){ rx2=95; ry2=nep;} if(ispaljeno==3){ rx3=95; ry3=nep; } if(ispaljeno==4){ rx4=95; ry4=nep; } } if(ispaljeno>0){ display.drawCircle(rx,ry,2,1); rx=rx-brzina; } if(ispaljeno>1){ display.drawCircle(rx2,ry2,1,1); rx2=rx2-brzina; } if(ispaljeno>2){ display.drawCircle(rx3,ry3,4,1); rx3=rx3-brzina; } if(ispaljeno>3){ display.drawCircle(rx4,ry4,2,1); rx4=rx4-brzina; } if(digitalRead(12)==0 && poz>=2){ poz=poz-2; } if(digitalRead(11)==0&& poz<=46){ poz=poz+2;} if(digitalRead(3)==0 && postoji==0){ postoji=1; metx=6; mety=poz+8; tone(Music,1200,20); } if(postoji==1){ metx=metx+8 ; display.drawLine(metx,mety,metx+4,mety,1); } display.drawBitmap(4, poz,dioda16, 16,16, 1); display.fillCircle(centar,nep,promjer,1); display.fillCircle(centar+2,nep+3,promjer/3,0); display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(33,57); display.println("score:"); display.setCursor(68,57); display.println(bodovi); display.setCursor(33,0); display.println("lives:"); display.setCursor(68,0); display.println(zivoti); display.setCursor(110,0); display.println("L:"); display.setCursor(122,0); display.println(nivo); display.setCursor(108,57); display.println(trenutno/1000); display.display(); if(metx>128)postoji=0; if(smjer==0){ nep=nep+bkugle;} else{ nep=nep-bkugle;} if(nep>=(64-promjer)) smjer=1; if(nep<=promjer) smjer=0; if(mety>=nep-promjer && mety<=nep+promjer) if(metx>(centar-promjer)&&metx<(centar+promjer)) { metx=-20; tone(Music,500,20); bodovi=bodovi+1; postoji=0; } int pozicija=poz+8; if(ry>=pozicija-8 && ry<=pozicija+8) if(rx<12&&rx>4) { rx=95; ry=-50; tone(Music,100,100); zivoti=zivoti-1; } if(ry2>=pozicija-8 && ry2<=pozicija+8) if(rx2<12&&rx2>4){ rx2=-50; ry2=-50; tone(Music,100,100); zivoti=zivoti-1; } if(ry3>=pozicija-8 && ry3<=pozicija+8) if(rx3<12&&rx3>4){ rx3=-50; ry3=-50; tone(Music,100,100); zivoti=zivoti-1; } if(ry4>=pozicija-8 && ry4<=pozicija+8) if(rx4<12&&rx4>4){ rx4=200; ry4=-50; ispaljeno=0; tone(Music,100,100); zivoti=zivoti-1; } if(rx4<1){ ispaljeno=0; rx4=200;} if(zivoti==0) go=1; } if(go==1){ if(zivoti==0){ tone(Music,200,300); delay(300); tone(Music,250,200); delay(200); tone(Music,300,300); delay(300); zivoti=5; } display.clearDisplay(); display.setFont(); display.setTextSize(2); display.setTextColor(WHITE); display.setCursor(7,10); display.println("GAME OVER!"); display.setTextSize(1); display.setCursor(7,30); display.println("score:"); display.setCursor(44,30); display.println(bodovi); display.setCursor(7,40); display.println("level:"); display.setCursor(44,40); display.println(nivo); display.setCursor(7,50); display.println("time(s):"); display.setCursor(60,50); display.println(trenutno/1000); display.display(); if(digitalRead(3)==0){ tone(Music,280,300); delay(300); tone(Music,250,200); delay(200); tone(Music,370,300); delay(300); ponovo(); } } } void ponovo(){ metx=0; mety=0; postoji=0; nep=8; smjer=0; go=0; rx=95; ry=0; rx2=95; ry2=0; rx3=95; ry3=0; bodovi=0; brzina=3; //brizna neprijateljevog metka bkugle=1; najmanja=600; najveca=1200; promjer=12; rx4=95; ry4=0; zivoti=5; poc=0; ispaljeno=0; nivo=1; pocetno=0; odabrano=0; trenutno=0; nivovrije=0; } long readVcc() { // Read 1.1V reference against AVcc // set the reference to Vcc and the measurement to the internal 1.1V reference #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) ADMUX = _BV(MUX5) | _BV(MUX0); #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) ADMUX = _BV(MUX3) | _BV(MUX2); #else ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); #endif delay(2); // Wait for Vref to settle ADCSRA |= _BV(ADSC); // Start conversion while (bit_is_set(ADCSRA,ADSC)); // measuring uint8_t low = ADCL; // must read ADCL first - it then locks ADCH uint8_t high = ADCH; // unlocks both long result = (high<<8) | low; result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000 return result; // Vcc in millivolts } void beep(int note, int duration){ //Play tone on buzzerPin tone(Music, note, duration); delay(duration); noTone(Music); delay(50); }

Upload the Code:

Normally I’d recommend studying the code, but a lot of it is Lithuanian. Open your Arduino IDE then copy and paste the code below to a new sketch. Upload the code to your Arduino board and get ready to destroy the Deathstar.

Conclusion

Playing a game on an Arduino with a mini-OLED display is a delightful blend of creativity and technology. This compact setup offers endless opportunities for designing and enjoying your own custom games. Whether you’re creating retro classics or entirely new experiences, the synergy between Arduino and OLED displays provides an immersive and hands-on gaming adventure that showcases the magic of DIY electronics. So, dive into the world of gaming on Arduino and watch your imagination come to life on that tiny, mesmerizing screen.

“Special Thanks to Danko for creating and sharing this project!”

Happy Gaming!

Recommendations:

The Elegoo Super Starter Kit

If you don’t already own any Arduino hardware, we highly recommend this kit as it has everything you need to start programming with Arduino. You can find out more about this kit, including a list of its components here: Elegoo Super Starter Kit

You can find this kit on Amazon here: Elegoo Super Starter Kit

The 0.96-inch Mini-OLED Display

We highly recommend this mini-OLED bundle of five 0.96-inch OLED displays. We have bought these before and they all worked perfectly. You can read more about the mini-OLED here: Mini-OLED

You can find this bundle on Amazon here: OLED Displays

Elegoo Nano (Arduino Compatible)

We have bought these Nano boards many times and can highly recommend them. There are three Nano boards in this pack making them a total bargain for everyone.

You can find this pack on Amazon here: Arduino Nano

 

Luke Barber

Hello, fellow tech enthusiasts! I'm Luke, a passionate learner and explorer in the vast realms of technology. Welcome to my digital space where I share the insights and adventures gained from my journey into the fascinating worlds of Arduino, Python, Linux, Ethical Hacking, and beyond. Armed with qualifications including CompTIA A+, Sec+, Cisco CCNA, Unix/Linux and Bash Shell Scripting, JavaScript Application Programming, Python Programming and Ethical Hacking, I thrive in the ever-evolving landscape of coding, computers, and networks. As a tech enthusiast, I'm on a mission to simplify the complexities of technology through my blogs, offering a glimpse into the marvels of Arduino, Python, Linux, and Ethical Hacking techniques. Whether you're a fellow coder or a curious mind, I invite you to join me on this journey of continuous learning and discovery.

Leave a Reply

Your email address will not be published. Required fields are marked *

Verified by MonsterInsights