Gamuino, an Arduino-powered coin game

Yesterday I finally finished my first bigger Arduino project: The goal in the game is to stop one of the three flashing dots to the upper-left corner, which will give some payout. As of now I say "some", because I wasn't smart enough to include 3. solenoid to the payout system. As a result from that, the amount of payout you get depends on amount of coins in the system (more coins, more payout).

The code inside Arduino is nothing special, but if somebody asks, I'll post it too.

I'm sorry about blurry image, I wasn't able to get anything better.

Couldn't edit, so I'll post a reply. Yesterday I added two more gamemodes, and I'm planning another one. I think I might have enough time at the weekend to post a video of my machine in action.

(Edit unavailable) Update: Uploaded a video to Youtube. The video shows all four different game modes and payout system as well. Please check it at:http://www.youtube.com/watch?v=V4QANmangm0

Here’s some more information that I was asked for at: http://blog.makezine.com/archive/2008/09/arduino_coinop_game_pelik.html
So, I’ve included another feature into my gaming machine, a keno( a kind of lottery, you know)-machine. The keno system gives a (rather) randomly 8 numbers, or dots, for that matter, every one second. It stops changing numbers after a pushbutton is pressed, and gives 13 more more dots, the winning dots. Then the system counts the number of the dots which are common between player’s and machine’s rows. If there’s enough common dots, the machine gives a payout equal to the amount of right dots. Since the numbers are given (quite) randomly, I’ve included a code snippet which double checks if there are two or more dots in player’s or machine’s row sharing one coordinate in the matrix. If it finds one, (eg. your row would have only 7 dots, not 8 like it should) it gives another coordinates for one of the two dots in same place and checks them too. All this happens before player sees any of his/her numbers. It’s not perfect system, but I have played about 300 rounds of my keno and never saw only 7 dots in my row.

The other four game modes should become quite clear on the video.

There’s also a nice memory for intros in my system; it will show intros only once before getting to the desired game mode, not every time you enter to mode selection and choose the same mode you played earlier.

Btw, the name ‘Pelikone’ means ‘A game machine’ in finnish.

Edit: Individual letters are no more shown in the beginning (like on the video), since I replaced them with a scrolling text.

And here’s my way badly commented code. It has over 860 lines and compiles to 13874 bytes, and since I hadn’t commented it when I coded it, it would be too tough task to do completely. I added some comments to it, though. For clearance, I’ll say that here: I have wired my system so that it needs a coin to register any push button pushes. It’s possible to reduce the size of my sketch significantly, and I tried to include sounds into it, but they sounded so bad that I removed them.

//Code by Timo Herva, timo.herva@gmail.com
#include <Matrix.h>

#include <binary.h>
#include <Sprite.h>

Matrix mymatrix = Matrix(12, 11, 10);
//some important pins
int power = 7;
int push = 6;
int sole1 = 4;
int sole2 = 3;
//Arrays for your numbers in keno
int vary[] = {0, 1, 2, 3, 4, 5, 6, 7};
int varx[] = {0, 0, 0, 0, 0, 0, 0, 0};
//Arrays for machine's numbers in keno
int kenox[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int kenoy[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
//variables for other game modes
int valx1 = 0;
int valx2 = 0;
int valx3 = 0;
int valx4 = 0;
int valy1 = 0;
int valy2 = 0;
int valy3 = 0;
int valy4 = 0;
int xvar = 7;
//Should be quite clear
int kenopayout = 0;
int kenonumbers = 0;
int randomdelay = 0;
int delaytime = 100;
int leddelay = 100;
int multiply = 0;
//pin for a potentiometer
int analog = 3;
//250 lines of definitions for needed alphabet, numbers,...
Sprite arrow = Sprite(
  8, 8, 
  B00000000, 
  B01111100,
  B01100000,
  B01010000,
  B01001000,
  B01000100,
  B00000010,
  B00000001
);

Sprite line = Sprite(
  1, 8,
  B1,
  B1,
  B1,
  B1,
  B1,
  B1,
  B1,
  B1
);

Sprite hline = Sprite(
  8, 1,
  B11111111
);
//some badly named variables
int gamemode = 1;
int x = 8;
int x2 = 8;
int y2 = 0;
int y = 8;
int z = 0;
int q = 0;
int w = 0;
int m = 0;
int r = 0;
int t = 0;
int p = 0;
int u = 0;
int j = 0;
int keno = 0;

Sprite smiley = Sprite( 
  6, 5, 
  B010010,
  B010010,
  B000000,
  B100001,
  B011110
);

Sprite unsmiley = Sprite(
  6, 5,
  B010010,
  B010010,
  B000000,
  B011110,
  B100001
);

Sprite P = Sprite(
  5, 7,
  B11110,
  B10001,
  B10001,
  B11110,
  B10000,
  B10000,
  B10000
);

Sprite K = Sprite(
  5, 7,
  B10001,
  B10001,
  B10010,
  B10100,
  B11100,
  B10010,
  B10001
);

Sprite e = Sprite(
  5, 7,
  B00000,
  B01110,
  B10001,
  B11110,
  B10000,
  B10001,
  B01110
);

Sprite l = Sprite(
  1, 7,
  B1, 
  B1,
  B1,
  B1,
  B1,
  B1,
  B1
);

Sprite i = Sprite(
  1, 7,
  B0,
  B1,
  B0,
  B1,
  B1,
  B1,
  B1
);

Sprite k = Sprite(
  4, 7, 
  B1000,
  B1000,
  B1001,
  B1010,
  B1100,
  B1010,
  B1001
);

Sprite o = Sprite(
  5, 7, 
  B00000,
  B00000,
  B01110,
  B10001,
  B10001,
  B10001,
  B01110
);

Sprite n = Sprite(
  5, 7, 
  B00000,
  B00000,
  B10110,
  B11001,
  B10001,
  B10001,
  B10001
);

Sprite v = Sprite(
  5, 7,
  B00000,
  B00000,
  B10001,
  B10001,
  B01010,
  B01010,
  B00100
);

Sprite dot = Sprite(
  1, 7,
  B0,
  B0,
  B0,
  B0,
  B0,
  B0,
  B1
);

Sprite W = Sprite(
  7, 7,
  B1000001,
  B1000001,
  B1000001,
  B1001001,
  B0101010,
  B0110110,
  B0100010
);

Sprite r2 = Sprite(
  4, 7,
  B0000,
  B0000,
  B1011,
  B1100,
  B1000,
  B1000,
  B1000
);

Sprite linecut = Sprite(
  1, 5,
  B1,
  B1,
  B0,
  B1,
  B1
);

Sprite n5 = Sprite(
  5, 7,
  B11111,
  B10000,
  B11110,
  B10001,
  B00001,
  B10001,
  B01110
);

Sprite n4 = Sprite(
  5, 7,
  B00010,
  B00100,
  B01000,
  B10010,
  B11111,
  B00010,
  B00010
);

Sprite n3 = Sprite(
  5, 7,
  B01110,
  B10001,
  B00001,
  B00110,
  B00001,
  B10001,
  B01110
);

Sprite n2 = Sprite(
  5, 7, 
  B01110,
  B10001,
  B00001,
  B00010,
  B00100,
  B01000,
  B11111
);

Sprite n1 = Sprite(
  5, 7, 
  B00010,
  B00110,
  B01010,
  B00010,
  B00010,
  B00010,
  B00111
);

Sprite n0 = Sprite(
  5, 7, 
  B01110,
  B10001,
  B10001,
  B10001,
  B10001,
  B10001,
  B01110
);

…And there’s another part of my code:

void countDown() {
  mymatrix.write(1, 1, n3);
  delay(1000);
  mymatrix.write(1, 1, n2);
  delay(1000);
  mymatrix.write(1, 1, n1);
  delay(1000);
  mymatrix.write(1, 1, n0);
  delay(1000);
  mymatrix.clear();
  delay(1000); 
}
//One intro per game mode
void intro() {
  for (int i = 0; i < 50; i++) {
    mymatrix.write(x, y, arrow);
    mymatrix.write(x - 8, y - 8, arrow);
    delay(75);
    mymatrix.clear();
    if (x == 0 && y == 0) {
      x = 8;
      y = 8;
    }
    x--;
    y--;
  }
  delay(300);
}
//Scrolling text effect when turning machine on
void startUp() {
  for (int h = 70; h > 0; h--) {
    mymatrix.write(h - 62, 1, P);
    mymatrix.write(h - 56, 1, e);
    mymatrix.write(h - 50, 1, l);
    mymatrix.write(h - 48, 1, i);
    mymatrix.write(h - 46, 1, k);
    mymatrix.write(h - 41, 1, o);
    mymatrix.write(h - 35, 1, n);
    mymatrix.write(h - 29, 1, e);
    mymatrix.write(h - 19, 1, v);
    mymatrix.write(h - 13, 1, n2);
    mymatrix.write(h - 7, 1, dot);
    mymatrix.write(h - 5, 1, n0);
    delaytime = analogRead(analog);
    delay(delaytime);
    mymatrix.clear();
  }
}
//Another text scroll
void winner() {
  for (int h = 39; h > 0; h--) {
    mymatrix.write(h - 31, 1, W);
    mymatrix.write(h - 23, 1, i);
    mymatrix.write(h - 21, 1, n);
    mymatrix.write(h - 15, 1, n);
    mymatrix.write(h - 9, 1, e);
    mymatrix.write(h - 3, 1, r2);
    delay(100);
    mymatrix.clear();
  }
}
//Intros continues...
void intro2() {
  for (int i = 0; i < 24; i++) {
    mymatrix.write(y2, 0, line);
    mymatrix.write(y2 - 8, 0, line);
    delay(75);
    mymatrix.clear();
    if (y2 == 8) {
      y2 = 0;
    }
    y2++;
  }
  for (int i = 0; i < 24; i++) {
    mymatrix.write(0, x2, hline);
    mymatrix.write(0, x2 - 8, hline);
    delay(75);
    mymatrix.clear();
    if (x2 == 0) {
      x2 = 8;
    }
    x2--;
  }
  delay(300);
}

void intro3() {
  for (int i = 0; i < 8; i++) {
    for (int a = 0; a < 8; a++) {
      mymatrix.write(i, a, HIGH);
      delay(75);
      mymatrix.write(i, a, LOW);
    }
  }
}

void intro4() {
  mymatrix.write(3, 1, linecut);
  for (int i = 0; i < 5; i++) {
    for (int a = 7; a > -1; a--) {
      mymatrix.write(a, 3, HIGH);
      delay(50);
      mymatrix.write(a, 3, LOW);
    }
  }
}

void intro5() {
  for (int h = 32; h > 0; h--) {
    mymatrix.write(h - 24, 1, K);
    mymatrix.write(h - 18, 1, e);
    mymatrix.write(h - 12, 1, n);
    mymatrix.write(h - 6, 1, o);
    delaytime = analogRead(analog);
    delay(delaytime);
    mymatrix.clear();
  }
} 

void clearBlinkingLeds() {
  mymatrix.write(valx1, valy1, LOW);
  mymatrix.write(valx2, valy2, LOW);
  mymatrix.write(valx3, valy3, LOW);
}

void clearBlinkingLeds2() {
  mymatrix.write(valx1, valy1, LOW);
  mymatrix.write(valx2, valy2, LOW);
  mymatrix.write(valx3, valy3, LOW);
  mymatrix.write(valx4, valy4, LOW);
}
//A function which gives your keno numbers
void getNumbers() {
  for (int i = 0; i < 8; i++) {
    varx[i] = random(0, 8);
    vary[i] = random(0, 8);
    delay(10);
    if (i > 0) {//Double checking in case of same numbers
      for (int h = 0; h < i; h++) {
        if (varx[i] == varx[h] && vary[i] == vary[h]) {
          varx[i] = random(0, 8);
          vary[i] = random(0, 8);
        }
      }
      for (int h = 0; h < i; h++) {
        if (varx[i] == varx[h] && vary[i] == vary[h]) {
          varx[i] = random(0, 8);
          vary[i] = random(0, 8);
        }
      }
    }
    mymatrix.write(varx[i], vary[i], HIGH);
  }
}
// A function which gives machine's numbers
void getKeno() {
  for (int a = 0; a < 13; a++) {
    kenox[a] = random(0, 8);
    kenoy[a] = random(0, 8);
    if (a > 0) {//Double checking in case of same numbers
      for (int h = 0; h < a; h++) {
        if (kenox[a] == kenox[h] && kenoy[a] == kenoy[h]) {
          kenox[a] = random(0, 8);
          kenoy[h] = random(0, 8);
        }
      }
      for (int h = 0; h < a; h++) {
        if (kenox[a] == kenox[h] && kenoy[a] == kenoy[h]) {
          kenox[a] = random(0, 8);
          kenoy[h] = random(0, 8);
        }
      }
    }
  }
  delay(10);
}

void randomizeLeds() {
  valx1 = random(0, 8);
  valx2 = random(0, 8);
  valx3 = random(0, 8);
  valy1 = random(0, 8);
  valy2 = random(0, 8);
  valy3 = random(0, 8);
  delay(10);
  mymatrix.write(valx1, valy1, HIGH);
  mymatrix.write(valx2, valy2, HIGH);
  mymatrix.write(valx3, valy3, HIGH);
}

void randomizeLeds2() {
  valx1 = random(0, 8);
  valx2 = random(0, 8);
  valx3 = random(0, 8);
  valx4 = random(0, 8);
  valy1 = random(0, 8);
  valy2 = random(0, 8);
  valy3 = random(0, 8);
  valy4 = random(0, 8);
  delay(10);
  mymatrix.write(valx1, valy1, HIGH);
  mymatrix.write(valx2, valy2, HIGH);
  mymatrix.write(valx3, valy3, HIGH);
  mymatrix.write(valx4, valy4, HIGH);
}

void blinkLeds() {
  mymatrix.write(valx1, valy1, HIGH);
  mymatrix.write(valx2, valy2, HIGH);
  mymatrix.write(valx3, valy3, HIGH);
  mymatrix.write(valx4, valy4, HIGH);
}
//Two functions for payout
void payOut() {
  for (int a = 0; a < 2; a++) {
    digitalWrite(sole2, HIGH);
    delay(200);
    digitalWrite(sole2, LOW);
    delay(300);
  }
}

void payOut2() {
  digitalWrite(sole2, HIGH);
  delay(200);
  digitalWrite(sole2, LOW);
  delay(300);
}
//...And a function which takes the coin player inserted
void getMoney() {
  digitalWrite(sole1, HIGH);
  delay(1000);
  digitalWrite(sole1, LOW);
  delay(500);
}

…And third…

void doSmiley() {
  mymatrix.write(1, 1, smiley);
}

void doUnSmiley() {
  mymatrix.write(1, 1, unsmiley);
}

void setup() {
  pinMode(power, INPUT);
  pinMode(push, INPUT);
  pinMode(sole1, OUTPUT);
  pinMode(sole2, OUTPUT);
  mymatrix.clear();
  mymatrix.setBrightness(7);
}

void loop() {
  mymatrix.clear();
  while (r == 0) {
    startUp();
    r = 1;
  }
  if (digitalRead(power) == LOW) {
    if (gamemode == 1) {//game one
      if (q == 0) {
        intro();
        countDown();
        mymatrix.clear();
        delay(500);
        q = 1;
      }
      if (t == 0) {
        mymatrix.write(1, 1, n1);
        delay(1000);
        t = 1;
      }
      mymatrix.clear();
      delaytime = analogRead(analog);
      randomizeLeds();
      delay(delaytime);
      if (digitalRead(push) == LOW) {
        getMoney();
        clearBlinkingLeds();
        if ((valx1 == 0 && valy1 == 0) || (valx2 == 0 && valy2 == 0) ||
        (valx3 == 0 && valy3 == 0)) {
          p = 1; 
        }
        else {
          p = 0;
        }
        if (p == 1) {
          doSmiley();
          delay(1000);
          winner();
          payOut2();
          mymatrix.clear();
        }
        else {
          doUnSmiley();
          delay(1000);
          mymatrix.clear();
        }
        p =0;
      }
    }
    if (gamemode == 2) {//game two
      if (w == 0) {
        intro2();
        countDown();
        mymatrix.clear();
        delay(500);
        w = 1;
      }
      if (t = 0) {
        mymatrix.write(1, 1, n2);
        delay(1000);
        t = 1;
      }
      mymatrix.clear();
      randomizeLeds2();
      delay(100);
      clearBlinkingLeds2();
      if (digitalRead(push) == LOW) {
        for (int i = 0; i < 40; i++) {
          randomizeLeds2();
          multiply = i * 10;
          leddelay = 100 + multiply;
          delay(leddelay);
          clearBlinkingLeds2();
        }
        randomizeLeds2();
        for (int a = 0; a < 4; a++) {
          blinkLeds();
          delay(500);
          clearBlinkingLeds2();
          delay(500);
        }
        getMoney();
        if ((valx1 == valx2 && (valx2 == valx3 || valx2 == valx4)) ||
        ((valx1 == valx3 || valx2 == valx3) && valx3 == valx4) ||
        (valy1 == valy2 && (valy2 == valy3 || valy2 == valy4)) ||
        ((valy1 == valy3 || valy2 == valy3) && valy3 == valy4)) {
          p = 1;
        }
        else {
          p = 0;
        }
        if (p == 1) {
          doSmiley();
          delay(1000);
          winner();
          payOut();
          mymatrix.clear();
        }
        else {
          doUnSmiley();
          delay(1000);
          mymatrix.clear();
        }
        p = 0;
      }
    }
    if (gamemode == 3) {//game three
      if (m == 0) {
        intro3();
        countDown();
        mymatrix.clear();
        delay(500);
        m = 1;
      }
      if (t == 0) {
        mymatrix.write(1, 1, n3);
        delay(1000);
        mymatrix.clear();
        t = 1;
      }
      mymatrix.clear();
      for (int i = 0; i < 8; i++) {
        while (digitalRead(push) == HIGH) {
          u++;
          if (u == 8) {
            u = 0;
          }
          vary[i] = u;
          mymatrix.write(i, u, HIGH);
          delaytime = analogRead(analog)/15;
          if (delaytime < 15) delaytime = 15;
          delay(delaytime);
          mymatrix.write(i, u, LOW);
        }
        mymatrix.write(i, vary[i], HIGH);
        delay(500);
      }
      getMoney();
      delay(1000);
      if (vary[0] == vary[1] && vary[1] == vary[2] && vary[2] == vary[3] &&
      vary[3] == vary[4] && vary[4] == vary[5] && vary[5] == vary[6] &&
      vary[6] == vary[7]) {
        p = 1;
      }
      else {
        p = 0;
      }
      mymatrix.clear();
      if (p == 1) {
        doSmiley();
        delay(1000);
        winner();
        payOut();
      }
      if (p == 0) {
        doUnSmiley();
        delay(1000);
      }
      p = 0; 
    }
    if (gamemode == 4) {//game four
      if (j == 0) {
        intro4();
        countDown();
        mymatrix.clear();
        delay(500);
        j = 1;
      }
      if (t == 0) {
        mymatrix.write(1, 1, n4);
        delay(1000);
        mymatrix.clear();
        t = 1;
      }
      mymatrix.clear();
      mymatrix.write(3, 1, linecut);
      while (digitalRead(push) == HIGH) {
        xvar--;
        if (xvar == -1) {
          xvar = 7;
        }
        randomdelay = random(15, 80);
        mymatrix.write(xvar, 3, HIGH);
        delay(randomdelay);
        mymatrix.write(xvar, 3, LOW);
      }
      mymatrix.write(xvar, 3, HIGH);
      delay(1000);
      getMoney();
      mymatrix.clear();
      if (xvar == 3) {
        p = 1;
        xvar = 7;
      }
      else {
        p = 0;
      }
      if (p == 1) {
        doSmiley();
        delay(1000);
        winner();
        payOut();
        mymatrix.clear();
      }
      else {
        doUnSmiley();
        delay(1000);
        mymatrix.clear();
      }
      p = 0;
    }

…And finally, fourth part!

    if (gamemode == 5) {//And finally my favourite, keno
      if (keno == 0) {
        intro5();
        countDown();
        mymatrix.clear();
        delay(500);
        keno = 1;
      }
      if (t == 0) {
        mymatrix.write(1, 1, n5);
        delay(1000);
        mymatrix.clear();
        t = 1;
      }
      mymatrix.clear();
      getNumbers();
      delay(1000);
      if (digitalRead(push) == LOW) {
        getKeno();
        delay(500);
        for (int i = 0; i < 4; i++) {
          for (int a = 0; a < 13; a++) {
            mymatrix.write(kenox[a], kenoy[a], HIGH);
          }
          delay(500);
          for (int a = 0; a < 13; a++) {
            mymatrix.write(kenox[a], kenoy[a], LOW);
          }
          delay(500);
        }
        getMoney();
        mymatrix.clear();
        for (int s = 0; s < 13; s++) {
          for (int d = 0; d < 8; d++) {
            if (kenox[s] == varx[d] && kenoy[s] == vary[d]) {
              kenonumbers++;
              mymatrix.write(varx[d], vary[d], HIGH);
            }
          }
          delay(100);
        }
        delay(1000);
        mymatrix.clear();
        if (kenonumbers > 3) {
          kenopayout = kenonumbers - 2;
          winner();
          delay(500);
          mymatrix.clear();
          for (int f = 0; f < kenopayout; f++) {
            doSmiley();
            payOut2();
            delay(400);
          }
        }
        else if (kenonumbers == 3) {
          winner();
          delay(500);
          mymatrix.clear();
          doSmiley();
          payOut2();
        }
        else {
          doUnSmiley();
          delay(1000);
        }
        kenonumbers = 0;
      }
    }
  }
  else {//There happens the changing between the game modes
    if (digitalRead(push) == LOW) {
      gamemode++;
      t = 0;
      delay(500);
      if (gamemode == 6) {
        gamemode = 1;
      }
    }
    mymatrix.clear();
    if (gamemode == 1) {
      mymatrix.write(1, 1, n1);
    }
    else if (gamemode == 2) {
      mymatrix.write(1, 1, n2);
    }
    else if (gamemode == 3) {
      mymatrix.write(1, 1, n3);
    }
    else if (gamemode == 4) {
      mymatrix.write(1, 1, n4);
    }
    else {
      mymatrix.write(1, 1, n5);
    }
    delay(100);
  }
}

Quite massive set of coding, but it works, anyway.

It seems like I'm having a private thread... But anyway, here's a link to a video which shows how my keno machine works: http://www.youtube.com/watch?v=TSa0-t1CKW8 I apologize those nasty reflections shown on the video, I couldn't avoid them. The scrolling text -effect is much more fluid in reality, though.

We’re speechless ;D

^^ He he, at least it seems like it... :)