Make Game With Arduino Mega
Create a Video Game with Arduino Mega and joypad.
Supplies
Materials to be used:
1) Arduino Mega
2) Breadboard
3) Resistors
4) A Joy for Arduino
5) A click button
6) Connection wires
7) Socket for RCA (AV)
8) A box to create a Joy pad
9) An RCA (AV) cable to connect Arduino to your TV
Libraries to use:
1) TvOut library to connect Arduino to TV via RCA (AV)
2) TimerThree library to manage 3 timer for sound effects
Game Code:
1) A game code (provided in the listing)
Assembly Hardware
The drawing shows the connections to be made, which as you can see are very simple.
Take:
1 x 10k Resistor
1 x 470k Resistor
1 x 1k Resistor
2 RCA Connectors (Video/Audio)
1 Switch Button
1 x 2-axis joystick (x/y)
1 Mega Arduino
Everything must be mounted on the breadboard as shown in the drawing above.
Below you can download the Fritzing file of the project.
Downloads
Library
First download the Avamander TVout library from your favorite IDE, the classic Arduino 1.6/1.8, Arduino 2.0 or, and this is what I usually use, the "Visual Micro" for Visual Studio.
This is the GitHub link to download the library.
Remember that inside the TVout folder in Arduino Libraries, on your disk, you have to bring out the TVoutfonts folder. Look for this folder inside TVout and read the file "README.md"
Download the TimerThree library that will be used for the sound effects here's the GitHub link.
From this link you can download the project for Visual Micro on GitHub.
Software (Platform)
A part of the sketch that runs the Platformer game.
TIMSK3 = 0b00000001;//###### ENABLE INTERRUPT TIMER 3 (attiva interrupt timer 3)
//######
mxstart = analogRead(ASSE_X);
//Serial.println(mstart); return;
if (mxstart > 510) { xhero += 1; if (xhero > 100) { xhero = 100; } }
if (mxstart < 490) { xhero -= 1; if (xhero < 2) { xhero = 2; } }
mxend = mxstart;
//###### LINEE LIVELLO
for (byte t = 13; t <= 103; t += 15) { TV.draw_line(0, t, 103, t, WHITE); }
//###### BUCHI LIVELLO
for (uint8_t t = 0; t < 6; t++) {
for (uint8_t t1 = 0; t1 < 4; t1++) {
xdel = mbuco[t][t1];
if (xdel > 0) { TV.draw_line(xdel, (t * 15) + 13, xdel + 5, (t * 15) + 13, BLACK); }
}
}
//###### PORTA
porta(97, endlevel);
//###### CROCE (CROSS)
for (uint8_t t = 0; t < maxobj; t++) {
if (objlive[t]) {
//TV.draw_rect((xobj[t] + 1) - wdobjcol[t] / 2, (yobj[t] - 1) - hgobjcol[t] / 2, wdobjcol[t], hgobjcol[t], WHITE);
croce(xobj[t], yobj[t], WHITE);
}
}
//###### CUORE (HEART)
if (lifelive) {
//TV.draw_rect(xlife - wdlifecol / 2, (ylife + 1) - hglifecol / 2, wdlifecol, hglifecol, WHITE);
cuore(xlife, ylife, WHITE);
}
TIMSK3 = 0b00000000;//###### DISABLE INTERRUPT TIMER 3 (disattiva interrupt timer 3)
//###### MOSTER
for (uint8_t t = 0; t < totmos; t++) {
moster(oxmos[t], oymos[t], posmoster[t], nxmos, BLACK);
xmos[t] += psxmos[t];
if (xmos[t] > oxmos[t]) { posmoster[t] = 1; }
else if (xmos[t] < oxmos[t]) { posmoster[t] = 0; }
if (xmos[t] > dsmos[t] || xmos[t] < lsmos[t]) { psxmos[t] = -psxmos[t]; }
moster(xmos[t], ymos[t], posmoster[t], nxmos, WHITE);
oxmos[t] = xmos[t]; oymos[t] = ymos[t];
}
//###### EXPLOSION
if (liveexp) {
explosion(oxexp, oyexp, BLACK);
explosion(xexp, yexp, WHITE);
}
oxexp = xexp;
oyexp = yexp;
//###### SCORE GAME
printScore(0, 105, score, 0);
//###### ENERGY HERO
TV.draw_rect(52, 105, 50, 4, WHITE, BLACK);
TV.draw_rect(52, 106, energy, 2, WHITE, WHITE);
//######
hero(oxhero, yhero, poshero, BLACK);
//######
uint8_t btnslt = digitalRead(BUTTON_ONE_PIN);
if (btnslt && !btnPress) {
if (slt == false) {
slt = true; yslt = yhero; psslt = -.5; btnPress = true;
effect(5);
}
}
else if (!btnslt) { btnPress = false; }
//###### COLLISIONE
if (slt) {
yhero += psslt;
if (yhero < yslt - 15) { psslt = .5; }
if (psslt > 0) {
if (!TV.get_pixel(xhero - 1, yhero + 6) && !TV.get_pixel(xhero, yhero + 6) && !TV.get_pixel(xhero + 1, yhero + 6)) {
slt = false;
}
}
}
else {
//###### COLLISIONE
if (!TV.get_pixel(xhero - 1, yhero + 6) && !TV.get_pixel(xhero, yhero + 6) && !TV.get_pixel(xhero + 1, yhero + 6)) {
slt = false;
yhero += 1;
}
}
//###### HERO
if (xhero > oxhero) { poshero = 1; }
else if (xhero < oxhero) { poshero = 0; }
hero(xhero, yhero, poshero, WHITE);
oxhero = xhero;
//###### HERO COLLISION MOSTER
for (uint8_t t = 0; t < totmos; t++) {
if ((xmos[t] - 1) + wdmoscol[t] / 2 > xhero - wdherocol / 2 && (xmos[t] - 1) - wdmoscol[t] / 2 < xhero + wdherocol / 2 &&
(ymos[t] - 1) + hgmoscol[t] / 2 > (yhero + 2) - hgherocol / 2 && (ymos[t] - 1) - hgmoscol[t] / 2 < (yhero + 2) + hgherocol / 2) {
energyHero(-.1);
effect(0);
}
}
//###### HERO COL OBJECT
for (uint8_t t = 0; t < maxobj; t++) {
if (objlive[t]) {
if ((xobj[t] + 1) + wdobjcol[t] / 2 > xhero - wdherocol / 2 && (xobj[t] + 1) - wdobjcol[t] / 2 < xhero + wdherocol / 2 &&
(yobj[t] - 1) + hgobjcol[t] / 2 > yhero - hgherocol / 2 && (yobj[t] - 1) - hgobjcol[t] / 2 < yhero + hgherocol / 2) {
croce(xobj[t], yobj[t], BLACK);
objlive[t] = false;
score += 10;
endobj -= 1;
if (endobj == 0) { endlevel = true; }
xexp = xobj[t]; yexp = yobj[t]; liveexp = true;
effect(3);
}
}
}
//###### HERO COL LIFE (CUORE)
if (lifelive) {
//TV.draw_rect(xlife - wdlifecol / 2, (ylife + 1) - hglifecol / 2, wdlifecol, hglifecol, WHITE);
if (xlife + wdlifecol / 2 > xhero - wdherocol / 2 && xlife - wdlifecol / 2 < xhero + wdherocol / 2 &&
(ylife - 2) + hglifecol / 2 > yhero - hgherocol / 2 && (ylife - 2) - hglifecol / 2 < yhero + hgherocol / 2) {
cuore(xlife, ylife, BLACK);
lifelive = false;
energyHero(1);
score += 100;
xexp = xlife; yexp = ylife; liveexp = true;
effect(4);
}
}
//###### HERO COL DOOR END LEVEL
if (endlevel) {
if (xhero + wdherocol / 2 > 100 && xhero - wdherocol / 2 < 103 && yhero < 9) {
level += 1;
TV.clear_screen();
//###### PRINT LEVEL
printLevel(level);
//######
effect(6);
unsigned long tmlev = millis();
while (millis() - tmlev <= 2000)
{
TIMSK3 = 0b00000000;//disattiva interrupt timer 3
TV.delay_frame(1);
TIMSK3 = 0b00000001;//attiva interrupt timer 3
}
//######
TV.clear_screen();
//###### END LEVEL
currPosLevel += 1;
if (currPosLevel >= endLevelEarth) {
//######
if (PlatformSpace == 0) {
//######
PlatformSpace = 1;
//######
SeletTypeStartGame();
return;
}
}
//###### GENERATORE DI SPAZI NELLA MAPPA
generaMappa();
//###### GENERATORE MOSTRI
generaMostri();
generaoggetti();
btnPress = false;
endlevel = false;
//###### START HERO
xhero = 5;
yhero = 85;
slt = false;
}
}
Software (Space)
A part of the sketch that runs the Space game.
TIMSK3 = 0b00000001;//###### ENABLE INTERRUPT TIMER 3 (attiva interrupt timer 3)
//###### PREPARA TERRA
vi += pvi;
if (pvi > 0 && vi >= ovi + vl) {
vl = random(20) + 1;
ovi = vi;
if (vi - vl < 5) { pvi = 0.25; }
else { pvi = -0.25; }
}if (pvi < 0 && vi <= ovi - vl) {
vl = random(20) + 1;
ovi = vi;
if (vi + vl > 50) { pvi = -0.25; }
else { pvi = 0.25; }
}
//######
mystart = analogRead(ASSE_Y);
if (mystart > 510) { yhero += 1; if (yhero > 100) { yhero = 100; } }
if (mystart < 490) { yhero -= 1; if (yhero < 0) { yhero = 0; } }
myend = mystart;
//######
mxstart = analogRead(ASSE_X);
if (mxstart > 510) { xhero += 1; if (xhero > 100) { xhero = 100; } }
if (mxstart < 490) { xhero -= 1; if (xhero < 2) { xhero = 2; } }
mxend = mxstart;
TIMSK3 = 0b00000000;//###### DISABLE INTERRUPT TIMER 3 (disattiva interrupt timer 3)
//###### FIRE BUTTON
uint8_t btnslt = digitalRead(BUTTON_ONE_PIN);
if (btnslt && !btnPress) {
fire += 1;
if (fire > 4) { fire = 0; }
if (fireon[fire] == false) {
fireon[fire] = true; xfire[fire] = xhero + 2; yfire[fire] = yhero + 1; btnPress = true;
oxfire[fire] = xfire[fire]; oyfire[fire] = yfire[fire];
effect(2);
}
}
else if (!btnslt) { btnPress = false; }
//###### FIRE MOVE
for (uint8_t t = 0; t < 5; t++) {
if (fireon[t]) {
TV.set_pixel(oxfire[t], oyfire[t], BLACK);
xfire[t] += 1;
if (xfire[t] >= 102 || TV.get_pixel(xfire[t], yfire[t])) { fireon[t] = false; oxfire[0] = 0; oyfire[0] = 0; }
//###### COLLISION FIRE WITH ALIEN
for (uint8_t t1 = 0; t1 < totAlien; t1++) {
if (liveastro[t1]) {
if (xfire[t] > xalien[t1] - 2 && xfire[t] < (xalien[t1] - 2) + 4 && yfire[t] > yalien[t1] && yfire[t] < yalien[t1] + 4) {
liveastro[t1] = false;
xexp = xalien[t1];
yexp = yalien[t1];
fireon[t] = false;
liveexp = true;
score += 50;
energyHero(.2);
effect(4);
}
}
}
//###### COLLISION FIRE WITH MISSILE
for (uint8_t t1 = 0; t1 < totmiss; t1++) {
if (livemiss[t1]) {
if (xfire[t] > xmiss[t1] - 1 && xfire[t] < (xmiss[t1] - 1) + 2 && yfire[t] > ymiss[t1] - 3 && yfire[t] < (ymiss[t1] - 3) + 5) {
livemiss[t1] = false;
xexp = xmiss[t1];
yexp = ymiss[t1];
fireon[t] = false;
liveexp = true;
score += 10;
effect(3);
}
}
}
}
}
//###### HERO BLACK
astro(oxhero, 1 + oyhero, BLACK);
//###### ALIEN
for (uint8_t t = 0; t < totAlien; t++) {
if (liveastro[t]) {
alien(oxalien[t], oyalien[t], nxmove, BLACK);
if (iniastro[t] == 1) { pxalien[t] -= .2; }
if (pxalien[t] <= 70 && iniastro[t] == 1) { iniastro[t + 1] = 1; }
if (pxalien[t] <= 60 && iniastro[t] == 1) { iniastro[t] = 2; iniastro[t + 1] = 1; }
if (iniastro[t] == 2) { a[t] += 1; if (a[t] > 156) { a[t] = 0; } }
if (iniastro[t] > 0) {
xalien[t] = pxalien[t] + 20 * fcos[a[t]];
yalien[t] = pyalien[t] + 20 * fsin[a[t]];
}
//###### COLLISION ASTRO WITH HERO
if (xhero > xalien[t] - 2 && xhero<(xalien[t] - 2) + 4 && yhero > yalien[t] && yhero < yalien[t] + 4) {
energyHero(-.5);
effect(0);
}
}
}
//##### FINE ALIEN
endAlien = true;
for (uint8_t t = 0; t < totAlien; t++) { if (liveastro[t] && iniastro[t] > 0) { endAlien = false; } }
//###### MISSILE
endmiss = true;
for (uint8_t t = 0; t < totmiss; t++) {
if (livemiss[t]) {
endmiss = false;
xmiss[t] -= psmiss[t]; if (xmiss[t] <= 0) { xmiss[t] = 102; psmiss[t] = 1; startmiss[t] = 30 + random(10) * 5; }
if (xmiss[t] == 102) { ymiss[t] = (103 - vi) - 3; }
if (xmiss[t] <= startmiss[t]) {
ymiss[t] -= (float)random(40, 100) / 100; psmiss[t] = (float)random(50, 100) / 100;
}
missile(oxmiss[t], oymiss[t], 0, BLACK);
//###### COLLISION MISSILE WITH HERO
if (xhero > xmiss[t] - 1 && xhero<(xmiss[t] - 1) + 2 && yhero>ymiss[t] - 3 && yhero < (ymiss[t] - 3) + 5) {
energyHero(-1);
effect(0);
}
}
}
//###### FINE EARTH SPACE
if (endLevelEarthSpace > 0) {
endAlien = false;
endmiss = false;
currPosEarthSpace++;
if (currPosEarthSpace >= endLevelEarthSpace) { endAlien = true; endLevelEarthSpace = 0; }
}
//###### FINE ALIEN/MISSILE
if ((endAlien && astromiss == 0) || (endmiss && astromiss == 1)) {
//###### END LEVEL
currPosLevel++;
if (currPosLevel >= endLevelSpace) {
level += 1;
TV.clear_screen();
//######
printLevel(level);
//######
effect(6);
unsigned long tmlev = millis();
while (millis() - tmlev <= 2000)
{
TIMSK3 = 0b00000000;//###### DISABLE INTERRUPT TIMER 3 (disattiva interrupt timer 3)
TV.delay_frame(1);
TIMSK3 = 0b00000001;//###### ENABLE INTERRUPT TIMER 3 (attiva interrupt timer 3)
}
//######
TV.clear_screen();
//######
if (PlatformSpace == 1) {
//######
PlatformSpace = 0;
//######
SeletTypeStartGame();
return;
}
}
spaceearth = random(0, 3);//###### DECIDE QUALE MODELLO SI SPAZIO TERRA
callnext();
}
//###### EXPLOSION
if (liveexp) { explosion(oxexp, oyexp, BLACK); }
//###### TERRAIN (TERRENO)
switch (spaceearth)
{
case 0:
if (random(0, 2) == 0) {
//###### ABOVE (SOPRA)
TV.draw_line(103, 0, 103, vi, WHITE);
}
else {
//###### ABOVE CRINE (SOPRA STORTO)
TV.draw_line(103, 0, 100, vi, WHITE);
}
break;
case 1:
if (random(0, 2) == 0) {
//###### UNDER (SOTTO)
TV.draw_line(103, 103 - vi, 103, 103, WHITE);
}
else {
//###### CRINE UNDER (SOTTO STORTO)
TV.draw_line(103, 103 - vi, 100, 103, WHITE);
}
break;
case 2:
//###### ABOVE/UNDER CRINE ROAD (SOPRA/SOTTO STRADA STORTA)
TV.draw_line(103, 0, 100, vi, WHITE);
TV.draw_line(100, vi + 20, 103, 103, WHITE);
break;
default:
break;
}
//###### SCORE GAME
printScore(1, 105, score, 1);
//###### ENERGY HERO
TV.draw_line(52, 105, 52, 109, BLACK);
TV.draw_rect(53, 105, 50, 4, WHITE, BLACK);
TV.draw_rect(53, 106, energy, 2, WHITE, WHITE);
//###### SCROLLING
TV.shift(1, LEFT);
//###### FIRE
for (uint8_t t = 0; t < 5; t++) {
if (fireon[t]) {
TV.set_pixel(xfire[t], yfire[t], WHITE);
oxfire[t] = xfire[t];
oyfire[t] = yfire[t];
}
}
//###### HERO WHITE
astro(xhero, 1 + yhero, WHITE);
//###### ALIEN
for (uint8_t t = 0; t < totAlien; t++) {
if (liveastro[t]) {
//TV.draw_rect(xalien[t], yalien[t], 4, 4, WHITE);
if (iniastro[t] > 0) {
alien(xalien[t], yalien[t], nxmove, WHITE);
oxalien[t] = xalien[t];
oyalien[t] = yalien[t];
}
}
}
//###### MISSILE
for (uint8_t t = 0; t < totmiss; t++) {
if (livemiss[t]) {
missile(xmiss[t], ymiss[t], 0, WHITE);
oxmiss[t] = xmiss[t];
oymiss[t] = ymiss[t];
}
}
//###### EXPLOSION
if (liveexp) { explosion(xexp, yexp, WHITE); }
oxexp = xexp;
oyexp = yexp;
oxhero = xhero;
oyhero = yhero;
//###### COLLISION HERO WITH EARTH
//TV.set_pixel(xhero + 2, 1 + yhero, WHITE);
if (TV.get_pixel(xhero + 2, yhero + 1)) {
energyHero(-1);
yhero -= 10; if (yhero <= 0) { yhero = 0; }
effect(0);
}
else if (TV.get_pixel(xhero + 2, yhero)) {
energyHero(-1);
yhero += 10; if (yhero >= 100) { yhero = 100; }
effect(0);
}
}
Final Sketch
Here you can find the final sketch in Arduino *.ino format.