Das Spiel Snake auf einer 8x8 LED Matrix (dual color - red-green)
Bilder
Sourcecode
// ************************************************** // 3 x 74HC595 & ULN2803 mit 8x8 Matrix red/green // **************************************************
include <TimerOne.h>
include <MsTimer2.h>
include <Bounce.h>
define COLS 8
define ROWS 8
define MATRIX COLS * ROWS
byte col = 0; byte row = 0; long rowoutput; long redoutput; long greenoutput; long redoutputrow; long greenoutputrow; int matrix[MATRIX]; int snake[MATRIX]; int newsnake[MATRIX]; int snakehead = 0; int oldsnakehead = 0; int snaketail = 0; int startingpoint = 15; int direction = 1; boolean buttonPressed = false;
int applecaught = 0; int apple = -1; int applecount = 0;
int empty = 0; int red = 1; int green = 2; int orange = 3;
int button1 = 7; // Left int button2 = 5; // Up int button3 = 6; // Down int button4 = 8; // Right
//Pin connected to ST_CP of 74HC595 int latchPin = 10; //Pin connected to SH_CP of 74HC595 int clockPin = 12; //Pin connected to DS of 74HC595 int dataPin = 11; // RESET Pin int outputEnablePin = 9;
int moveSpeed = 200; unsigned long lastMillis = 0;
// Scroll text String msg = " "; int msgIndex = 0; int alphabetIndex = 0; int i = 0; bool scrollNow = false; bool scrollOnce = false;
const byte alphabets[][6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // leer
0x7E, 0x89, 0x91, 0xA1, 0x7E, 0x00, // 0
0x00, 0x41, 0xFF, 0x01, 0x00, 0x00, // 1
0x43, 0x85, 0x89, 0x91, 0x61, 0x00, // 2
0x42, 0x81, 0x91, 0x91, 0x6E, 0x00, // 3
0x18, 0x28, 0x48, 0xFF, 0x08, 0x00, // 4
0xF2, 0x91, 0x91, 0x91, 0x8E, 0x00, // 5
0x1E, 0x29, 0x49, 0x89, 0x86, 0x00, // 6
0x80, 0x8F, 0x90, 0xA0, 0xC0, 0x00, // 7
0x6E, 0x91, 0x91, 0x91, 0x6E, 0x00, // 8
0x70, 0x89, 0x89, 0x8A, 0x7C, 0x00, // 9
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // leer
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // leer
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // leer
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // leer
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // leer
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // leer
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // leer
0x7F, 0x88, 0x88, 0x88, 0x7F, 0x00, // A
0xFF, 0x91, 0x91, 0x91, 0x6E, 0x00, // B
0x7E, 0x81, 0x81, 0x81, 0x42, 0x00, // C
0xFF, 0x81, 0x81, 0x42, 0x3C, 0x00, // D
0xFF, 0x91, 0x91, 0x91, 0x81, 0x00, // E
0xFF, 0x90, 0x90, 0x90, 0x80, 0x00, // F
0x7E, 0x81, 0x89, 0x89, 0x4E, 0x00, // G
0xFF, 0x10, 0x10, 0x10, 0xFF, 0x00, // H
0x81, 0x81, 0xFF, 0x81, 0x81, 0x00, // I
0x06, 0x01, 0x01, 0x01, 0xFE, 0x00, // J
0xFF, 0x18, 0x24, 0x42, 0x81, 0x00, // K
0xFF, 0x01, 0x01, 0x01, 0x01, 0x00, // L
0xFF, 0x40, 0x30, 0x40, 0xFF, 0x00, // M
0xFF, 0x40, 0x30, 0x08, 0xFF, 0x00, // N
0x7E, 0x81, 0x81, 0x81, 0x7E, 0x00, // O
0xFF, 0x88, 0x88, 0x88, 0x70, 0x00, // P
0x7E, 0x81, 0x85, 0x82, 0x7D, 0x00, // Q
0xFF, 0x88, 0x8C, 0x8A, 0x71, 0x00, // R
0x61, 0x91, 0x91, 0x91, 0x8E, 0x00, // S
0x80, 0x80, 0xFF, 0x80, 0x80, 0x00, // T
0xFE, 0x01, 0x01, 0x01, 0xFE, 0x00, // U
0xF0, 0x0C, 0x03, 0x0C, 0xF0, 0x00, // V
0xFF, 0x02, 0x0C, 0x02, 0xFF, 0x00, // W
0xC3, 0x24, 0x18, 0x24, 0xC3, 0x00, // X
0xE0, 0x10, 0x0F, 0x10, 0xE0, 0x00, // Y
0x83, 0x85, 0x99, 0xA1, 0xC1, 0x00, // Z
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // leer
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // leer
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // leer
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // leer
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // leer
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // leer
0x06, 0x29, 0x29, 0x29, 0x1F, 0x00, // a
0xFF, 0x09, 0x11, 0x11, 0x0E, 0x00, // b
0x1E, 0x21, 0x21, 0x21, 0x12, 0x00, // c
0x0E, 0x11, 0x11, 0x09, 0xFF, 0x00, // d
0x0E, 0x15, 0x15, 0x15, 0x0C, 0x00, // e
0x08, 0x7F, 0x88, 0x80, 0x40, 0x00, // f
0x30, 0x49, 0x49, 0x49, 0x7E, 0x00, // g
0xFF, 0x08, 0x10, 0x10, 0x0F, 0x00, // h
0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, // i
0x02, 0x01, 0x21, 0xBE, 0x00, 0x00, // j
0xFF, 0x04, 0x0A, 0x11, 0x00, 0x00, // k
0x00, 0x81, 0xFF, 0x01, 0x00, 0x00, // l
0x3F, 0x20, 0x18, 0x20, 0x1F, 0x00, // m
0x3F, 0x10, 0x20, 0x20, 0x1F, 0x00, // n
0x0E, 0x11, 0x11, 0x11, 0x0E, 0x00, // o
0x3F, 0x24, 0x24, 0x24, 0x18, 0x00, // p
0x10, 0x28, 0x28, 0x18, 0x3F, 0x00, // q
0x1F, 0x08, 0x10, 0x10, 0x08, 0x00, // r
0x09, 0x15, 0x15, 0x15, 0x02, 0x00, // s
0x20, 0xFE, 0x21, 0x01, 0x02, 0x00, // t
0x1E, 0x01, 0x01, 0x02, 0x1F, 0x00, // u
0x1C, 0x02, 0x01, 0x02, 0x1C, 0x00, // v
0x1E, 0x01, 0x0E, 0x01, 0x1E, 0x00, // w
0x11, 0x0A, 0x04, 0x0A, 0x11, 0x00, // x
0x00, 0x39, 0x05, 0x05, 0x3E, 0x00, // y
0x11, 0x13, 0x15, 0x19, 0x11, 0x00, // z
0x44, 0x02, 0x12, 0x02, 0x44, 0x00 // { -> smile
};
const byte numbers[][3] = { 0x3E, 0x22, 0x3E, // 0
0x12, 0x3E, 0x02, // 1
0x2E, 0x2A, 0x3A, // 2
0x2A, 0x2A, 0x3E, // 3
0x38, 0x08, 0x3E, // 4
0x3A, 0x2A, 0x2E, // 5
0x3E, 0x2A, 0x2E, // 6
0x20, 0x20, 0x3E, // 7
0x3E, 0x2A, 0x3E, // 8
0x3A, 0x2A, 0x3E, // 9
};
Bounce bouncer1 = Bounce(button1, 10); Bounce bouncer2 = Bounce(button2, 10); Bounce bouncer3 = Bounce(button3, 10); Bounce bouncer4 = Bounce(button4, 10); int button1value = LOW; int button2value = LOW; int button3value = LOW; int button4value = LOW;
// initialization void setup() {
//set pins to output because they are addressed in the main loop
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
digitalWrite(latchPin, LOW);
pinMode(outputEnablePin, OUTPUT);
digitalWrite(outputEnablePin, LOW);
randomSeed(analogRead(5));
// buttons to input
pinMode(button1, INPUT);
pinMode(button2, INPUT);
pinMode(button3, INPUT);
pinMode(button4, INPUT);
// Enable internal pullup resistors
digitalWrite(button1, HIGH);
digitalWrite(button2, HIGH);
digitalWrite(button3, HIGH);
digitalWrite(button4, HIGH);
// Timer1 controls output on displays
Timer1.initialize(2000);
Timer1.attachInterrupt(outputDisplay);
// Timer2 scrolls text
MsTimer2::set(120, scroll);
MsTimer2::start();
buttonPressed = false;
}
// called by timer1 void outputDisplay() {
if (col >= COLS)
col = 0;
greenoutputrow = 0;
redoutputrow = 0;
for (int i=0; i<ROWS; i++)
{
int value = matrix[col*ROWS+i];
switch(value) {
case 1: redoutput = 1 << i; greenoutput = 0; break; case 2: redoutput = 0; greenoutput = 1 << i; break; case 3: redoutput = 1 << i; greenoutput = 1 << i; break; default: redoutput = 0; greenoutput = 0; break;
}
redoutputrow += redoutput;
greenoutputrow += greenoutput;
}
rowoutput = (1 << col);
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, rowoutput);
shiftOut(dataPin, clockPin, MSBFIRST, greenoutputrow);
shiftOut(dataPin, clockPin, MSBFIRST, redoutputrow);
digitalWrite(latchPin, HIGH);
col++;
}
// called by timer2 void scroll() {
if (!scrollNow)
return;
for (int m=1; m<COLS; m++)
{
for(int n=0; n<ROWS; n++)
matrix[n*ROWS+m-1] = matrix[n*ROWS+m];
}
if (msgIndex >= msg.length())
scrollNow = false;
for (int j=0; j<COLS; j++)
{
int bit = 0;
if (bitRead(alphabets[alphabetIndex][i], COLS-j-1))
bit = green;
matrix[j*ROWS+(COLS-1)] = bit;
}
i++;
if (i > 5)
{
msgIndex++;
alphabetIndex = msg.charAt(msgIndex) - 47;
if (alphabetIndex < 0)
alphabetIndex = 0;
i = 0;
}
}
// Create empty snake void resetSnake() {
// Create empty snake
for (int i=0; i<MATRIX; i++)
{
snake[i] = -1;
newsnake[i] = -1;
}
clearMatrix();
// Add starting dot
matrix[startingpoint] = orange;
snakehead = startingpoint;
snake[0] = snakehead;
generateApple();
matrix[apple] = green;
direction = 1;
applecount = 0;
}
// Moves snake void moveSnake() {
if (millis() - lastMillis >= moveSpeed)
{
oldsnakehead = snakehead;
switch(direction) {
case 0: // up if ((snakehead - ROWS) < 0) snakehead += (ROWS * (COLS - 1)); else snakehead -= ROWS; break; case 1: // right if ((snakehead - (snakehead % ROWS)) == (((snakehead+1) - (snakehead+1) % ROWS))) snakehead += 1; else snakehead = snakehead - (ROWS - 1); // to start of row break; case 2: // down if ((snakehead + ROWS) > ((ROWS * COLS - 1))) snakehead = snakehead % ROWS; else snakehead += ROWS; break; case 3: // left if (snakehead == 0) // exception for topleft, pixel 0 snakehead += (ROWS - 1); else
{
if ((snakehead - (snakehead % ROWS)) == (((snakehead-1) - (snakehead-1) % ROWS)))
snakehead -= 1;
else
snakehead += (ROWS - 1); // end of row
}
break; default: // wtf? break;
}
// Check if we have the apple
if (snakehead == apple)
{
// Got it! // generateApple(); applecaught = 1;
}
for (int i=1; i<MATRIX; i++)
{
if (snake[i] == snakehead) endGame();
}
newsnake[0] = snakehead;
for(int n=0; n<MATRIX-1; n++)
{
if (snake[n] == -1)
{
snaketail = snake[n-1]; if (applecaught == 0) newsnake[n] = -1; // undo last, we are moving on break; } newsnake[n+1] = snake[n];
}
for(int m=0; m<MATRIX; m++) {
snake[m] = newsnake[m];
}
if (applecaught == 1)
{
generateApple(); applecaught = 0;
applecount++;
}
updateMatrix();
lastMillis = millis();
}
}
// Update snake in matrix void updateMatrix() {
clearMatrix();
for (int i=1; i<MATRIX; i++) {
if (snake[i] == -1)
break;
matrix[snake[i]] = red;
}
matrix[snakehead] = orange;
matrix[apple] = green;
}
// Clear matrix (all LEDs off) void clearMatrix() {
// Clear matrix
for (int i=0; i<MATRIX; i++) {
matrix[i] = 0;
}
}
// Generate random positon for apple void generateApple() {
apple = random(MATRIX);
for (int n=0; n<MATRIX; n++)
{
if (snake[n] == apple)
generateApple();
}
}
// Show number of catched apples void showResult() {
clearMatrix();
String msg = String(applecount);
if (msg.length() == 1)
msg = '0' + msg;
int leftNumber = msg.charAt(0) - 48;
int rightNumber = msg.charAt(1) - 48;
for (int i=0; i<3; i++)
for(int j=0; j<ROWS; j++)
{
int bit = 0;
if (bitRead(numbers[leftNumber][i], ROWS-j-1))
bit = red;
matrix[j*COLS+i] = bit;
}
for (int i=0; i<3; i++)
for(int j=0; j<ROWS; j++)
{
int bit = 0;
if (bitRead(numbers[rightNumber][i], ROWS-j-1))
bit = red;
matrix[j*COLS+5+i] = bit;
}
}
// Game over void endGame() {
delay(500);
apple = -1;
for (int i=0; i<COLS; i++)
{
for (int n=0; n<ROWS; n++)
matrix[n + (i * ROWS)] = green;
delay(200);
}
delay(1000);
showResult();
delay(5000);
resetSnake();
}
void loop() {
bouncer1.update();
bouncer2.update();
bouncer3.update();
bouncer4.update();
if (bouncer1.read() == LOW) {
if (button1value == HIGH) {
buttonPressed = true;
if (direction != 1)
direction = 3; //LEFT
}
}
button1value = bouncer1.read();
if (bouncer2.read() == LOW) {
if (button2value == HIGH) {
buttonPressed = true;
if (direction != 2)
direction = 0; // UP
}
}
button2value = bouncer2.read();
if (bouncer3.read() == LOW) {
if (button3value == HIGH) {
buttonPressed = true;
if (direction != 0)
direction = 2; // DOWN
}
}
button3value = bouncer3.read();
if (bouncer4.read() == LOW) {
if (button4value == HIGH) {
buttonPressed = true;
if (direction != 3)
direction = 1; // RIGHT
}
}
button4value = bouncer4.read();
if (scrollOnce == false)
{
scrollOnce = true;
msg = "Welcome ";
msgIndex = 0;
alphabetIndex = msg.charAt(msgIndex) - 47;
i = 0;
scrollNow = true;
}
if (scrollNow == false)
{
if (apple == -1)
resetSnake();
moveSnake();
}
if (buttonPressed && scrollNow)
{
scrollOnce = true;
scrollNow = false;
buttonPressed = false;
}
}
Video














