Arduino Starfield
1. Overview
Starfield is a simple arcade videogame for arduino and TV-Out library. The goal is to avoid the asteroids as long as you can. Each time one asteroid hits your rocket, you will lose energy (E). If you manage to survive for more than a minute you will go to another level.
The connection between arduino and the TV requires only a few components (resistores) since TV OUT library does most of the hard job by software.
To install and learn more about how this awsome library works, please follow the link:
http://code.google.com/p/arduino-tvout/downloads/list
There is an Arduino-based video game system, Hackvision. from nootropicdesign
Although I was not able to try this project on hackvision (I dont have any unit with me), I wrote the code to be fully compatible with it ( please, let me know and tell me how it went in case you did it).
Thanks to Michael for testing the game and add it to hackvision games page 🙂
Here is a short preview from the game running on my old green phosphor monitor. I shot it with my cellphone, so image quality is not very high.
2. Materials
1xArduino board
Resistors: 1×330,1x1k,1×470
2xRCA cable, one for video and the other for the audio.
4xpush Buttons
1xBreadboard
Jump wires
3. The Circuit
If you cant find RCA female plugs, then simple grab an two old audio RCA cable and cut them.
The game will run even if you dont have the audio connected (nor the buttons).
The lastpicture shows the project deployed on a breadboard. Note that in this version the audio connections are not installed.
4. Code for Arduino
– Download the project files and program your arduino. Remember, if your TV system is NTSC you should comment the PAL statement and uncomment NTSC line in first section of the program.
Project Files
The game code is available below for a sneak preview
/* Mário Vairinhos 2012 This software is free. You may distribute, copy or modify as long as you give me credits. */ #include <TVout.h> #include <fontALL.h> #include "rocket.h" TVout TV; #define TVSYSTEM _PAL //#define TVSYSTEM _NTSC #define SCREENWIDTH 128 #define SCREENHEIGHT 96 #define SCREENWIDTH2 64 #define SCREENHEIGHT2 48 #define ASTEROIDS 18 // pin controls #define BT_UP 4 #define BT_DOWN 5 #define BT_LEFT 3 #define BT_RIGHT 2 #define BEEP TV.tone(1046,200); // globals int asteroidsX[ASTEROIDS]; int asteroidsY[ASTEROIDS]; int asteroidsZ[ASTEROIDS]; float meX, meY,meZ=0; float screenX,screenY; float myspeed; int level; int energy; int tick; int seconds; int frames; byte gameState=0; //(0-startLevel,1-run,2-gameOver,3 win) void setup() { //init TV library TV.begin(TVSYSTEM, SCREENWIDTH, SCREENHEIGHT); TV.select_font(font4x6); TV.delay_frame(60); TV.clear_screen(); // setup pullup resistors pinMode(BT_UP ,INPUT);digitalWrite(BT_UP ,HIGH); pinMode(BT_DOWN ,INPUT);digitalWrite(BT_DOWN ,HIGH); pinMode(BT_LEFT ,INPUT);digitalWrite(BT_LEFT ,HIGH); pinMode(BT_RIGHT,INPUT);digitalWrite(BT_RIGHT,HIGH); level=0; gameState=0; } // game's state void loop() { switch (gameState){ case 0: startLevel(); break; case 1: run(); break; case 2: run(); break; case 3: win(); break; } } // static vars byte startLev=0; byte ry,rdy; void startLevel(){ // random asteroids once if (startLev==0){ BEEP meX=100;meY=0;meZ=0;startLev=1;ry=20;rdy=1; for(int i=0;i<ASTEROIDS;i++){asteroidsX[i]=random(130,230);asteroidsY[i]=random(1,95);asteroidsZ[i]=random(1,5);} } // render the screen // and move the rocket tempo(); frames++; if (frames>2){ TV.clear_screen(); frames=0; ry+=rdy; if (ry>20) rdy=-1; if (ry<5) rdy=1; TV.bitmap(25,ry,rocket,1,72,40); drawLevel(); } // move the asteroids for(int i=0;i<ASTEROIDS;i++){ asteroidsX[i]-=asteroidsZ[i]; if(asteroidsX[i]<=1) asteroidsX[i]=130; if (asteroidsX[i]<128 && asteroidsX[i]>0) TV.set_pixel(asteroidsX[i],asteroidsY[i],1); } // check user input if ((digitalRead(BT_LEFT) ==LOW) && (digitalRead(BT_RIGHT) ==LOW)){ initLevel(); gameState=1; startLev=0; clicka(); } // after 60 seconds on inactivity, start the level anyway if (seconds>60) initLevel(); TV.delay_frame(1); } void clicka(){ BEEP TV.delay(200); TV.invert(); TV.delay(200); TV.clear_screen(); } void win(){ level++; gameState=0; startLev=0; } void run() { tempo(); // every 3 frames clear te screen // and render the cockpit // every frame render the asteroids frames++; if (frames>3){ frames=0; TV.clear_screen(); drawCockpit(); if (gameState==2){ drawGameOver(); if (seconds>10){ gameState=0; level=1; } } } // user input if (digitalRead(BT_LEFT) ==LOW){meX-=1+level/3;} if (digitalRead(BT_RIGHT)==LOW){meX+=1+level/3;} if (digitalRead(BT_UP) ==LOW){meY-=1+level/3;} if (digitalRead(BT_DOWN)==LOW){meY+=1+level/3;} // collision for(int i=0;i<ASTEROIDS;i++){ if (asteroidsZ[i]<20){ if (abs(asteroidsX[i]-meX)+abs(asteroidsY[i]-meY)<=25){ if (gameState==1){ beepCrash(); TV.fill(2); energy--; } } respawn(i,meX,meY,800,i*20+5,0); } asteroidsZ[i]-=myspeed; } renderAsteroids(); if (energy<=0){ gameState=2; energy=1; seconds=0; } if (seconds>100){ win(); } } void initLevel(){ TV.noTone(); myspeed=10+level*2; //3 energy=5; tick=0; seconds=0; meX=0; meY=0; meZ=0; for(int i=0;i<ASTEROIDS;i++){ respawn(i,meX,meY,1000,120,600); } gameState=1; startLev=0; } void respawn(int index,int ox, int oy,int oz,int radius,int radiusZ){ asteroidsX[index]=ox+random(-radius,+radius); asteroidsY[index]=oy+random(-radius,+radius); asteroidsZ[index]=oz+random(radiusZ); } void get2dFrom3d(float coordX,float coordY,float coordZ){ coordX=coordX-meX; coordY=coordY-meY; coordZ=coordZ-meZ; if (coordZ==0) coordZ=0.1; screenX=(float(coordX)/float(coordZ))*SCREENWIDTH; screenY=(float(coordY)/float(coordZ))*SCREENHEIGHT; } void renderAsteroids(){ float x1,radius; int vx,vy; for(int i=0;i<ASTEROIDS;i++){ get2dFrom3d(asteroidsX[i],asteroidsY[i],asteroidsZ[i]); radius=2200/(asteroidsZ[i]<<2); vx=SCREENWIDTH2+screenX; vy=SCREENHEIGHT2+ screenY; if (vx<(SCREENWIDTH-radius-1) && vx>(radius+1) && vy<(SCREENHEIGHT-radius-1) && vy>(radius+1)){ TV.draw_circle(vx,vy,radius,1,1); } } TV.delay_frame(1); } void tempo(){ tick++; if (tick>30){ tick=0; seconds++; } } void drawCockpit(){ TV.select_font(font4x6); byte x=43;byte y=71; TV.print_char(x,y,'E'); TV.draw_rect (x+6,y+1,energy*2 ,4 ,1,1); TV.draw_rect (x+5,y+0,12 ,5 ,1); x=65;y=71; TV.print_char(x,y,'T'); TV.draw_rect (x+6,y+1 ,seconds/10 ,4 ,1,1); TV.draw_rect (x+5,y ,12 ,5 ,1); TV.draw_line(20,SCREENHEIGHT,40,SCREENHEIGHT-16,1); TV.draw_line(SCREENWIDTH-20,SCREENHEIGHT,SCREENWIDTH-40,SCREENHEIGHT-16,1); TV.draw_rect(40,SCREENHEIGHT-16-12,SCREENWIDTH-40-40,12,1); TV.draw_line(0,SCREENHEIGHT-16-12-30,40,SCREENHEIGHT-16-12,1); TV.draw_line(SCREENWIDTH,SCREENHEIGHT-16-12-30,SCREENWIDTH-40,SCREENHEIGHT-16-12,1); TV.print_char(55,84,'L'); TV.print_char(60,84,'E'); TV.print_char(65,84,'V'); TV.print_char(72,84,level+48); } void drawLevel(){ byte x,y; x=30;y=50; TV.select_font(font8x8); TV.print(x+15,y,"LEVEL"); TV.print(byte(level+48)); TV.select_font(font4x6); TV.print(x,y+10,"press LEFT & RIGHT"); } void drawGameOver(){ TV.select_font(font8x8); TV.print(30,30,"GAME OVER"); TV.delay_frame(1); } void beepCrash(){ TV.tone(random(60,100),150); } }
I was trying to load the game but I get error upon error, you use something special?
no, nothing special 😦 Can you please, describe the error? several people did build it without reporting any issues
Is there a way I can contact you by email? I have a question about this project
sure, send it to: mariovairinhos@gmail.com
I’m developing a user-friendly TVOUT console, and I’m looking for launch titles
You post very interesting content here. Your website deserves much
bigger audience. It can go viral if you give it initial boost, i know very useful service that can help you, just
search in google: svetsern traffic tips
Hello,
My name is janvier and i have started a new community called Duino’s Playground.
This is a community driven website where people can post, share and discuss there arduino projects.
However, we are looking for Arduino projects we can use on our website.
In the future we are looking into tutorials and such.
I would like to ask if we can use your projects for our website.
All credits and copyrights will be posted to the original owners. (Backlinks)
Our website is: http://www.duinosplayground.com
Dont forget to sign up at our forums at http://www.duinosplayground.com/community/
There you can post your projects and share them with all the membes.
If you like to know more about this, please send me an email back to this email address or community@duinosplayground.com.
Thanks for taking time on this email.
With friendly
greetings Janvier
Owner of http://www.duinosplayground.com
Pingback: La console de jeu monochrome ! – Sivigik
Nice job!
hi, I did my version of the game
https://maquinaslibres.noblogs.org/juego-8bit-la-capi-capitana-interestelar-en-la-nube-de-asteroides/
Cool Bazzzzza, i love it 🙂
Pingback: Juego 8bit: La capi, Capitana Interestelar en la nube de asteroides – Maquinas Libres
Now it can download for GNU/linux and Window
https://bazza.itch.io/lacapi