Project 21 8*16 dot matrix-game project
1.Project instruction
We could play games through Max development board. Can you imagine that? Let’s get started.
2.Project Principle
Game 1: gluttonous snake Press two buttons on max board, the gluttonous snake moves clockwise and anticlockwise.
Game 2: Break the bricks Press buttons simultaneously to start.
3.Project circuit

4.Project code1
#include <Wire.h>
#include <Keyestudio_GFX.h>
#include <Keyestudio_LEDBackpack.h>
// Button pin
const int buttonRightPin = 2;
const int buttonLeftPin = 3;
int* buttonPin;
int* buttonState;
// Game constants
// buttons
const int RIGHTBUTTON = 0;
const int LEFTBUTTON = 1;
// direction
const int TOP = 0;
const int RIGHT = 1;
const int BOTTOM = 2;
const int LEFT = 3;
// Snake
const int MAX_SNAKE_LENGTH = 100;
// Variables
//Keyestudio_8x8matrix matrix = Keyestudio_8x8matrix(); // Display
Keyestudio_8x16matrix matrix = Keyestudio_8x16matrix();
int direction = TOP; // direction of movement
int snakeX[MAX_SNAKE_LENGTH]; // X-coordinates of snake
int snakeY[MAX_SNAKE_LENGTH]; // Y-coordinates of snake
int snakeLength = 1; // nr of parts of snake
boolean buttonRead = false; // is button already read in this loop
unsigned long prevTime = 0; // for gamedelay (ms)
unsigned long delayTime = 500; // Game step in ms
int fruitX, fruitY;
unsigned long fruitPrevTime = 0;
unsigned long fruitBlinkTime = 1000/250;
int fruitLed = LED_ON;
void setup()
{
Serial.begin(9600);
Serial.println("Snake is started");
randomSeed(analogRead(0));
// Init led matrix
matrix.begin(0x70);
// init buttons
int buttonpins[] = {buttonRightPin, buttonLeftPin};
initButtons(buttonpins, 2);
// init snake
snakeX[0] = 4;
snakeY[0] = 7;
for(int i=1; i<MAX_SNAKE_LENGTH; i++)
{
snakeX[i] = snakeY[i] = -1;
}
makeFruit();
}
void loop()
{
checkButtons();
unsigned long currentTime = millis();
if(currentTime - prevTime >= delayTime)
{
nextstep();
buttonRead = false;
prevTime = currentTime;
}
draw();
}
void initButtons(int pinNumbers[], int length)
{
Serial.println("initButtons");
// Copy PIN numbers
buttonPin = new int[length];
for(int i=0; i<length; i++)
{
buttonPin[i] = pinNumbers[i];
}
// Initialize button state
buttonState = new int[length];
for(int i=0; i<length; i++)
{
buttonState[i] = LOW;
}
for(int i=0; i<length; i++)
{
Serial.print(buttonPin[i]);
Serial.print(buttonState[i]);
}
}
boolean buttonClicked(int index)
{
// current state
int state = digitalRead(buttonPin[index]);
boolean buttonClick = false;
// button has pressed
if(buttonState[index] == HIGH)
{
if(state == LOW)
{
buttonClick = true;
}
}
buttonState[index] = state;
return buttonClick;
}
void checkButtons()
{
if(!buttonRead){
int currentDirection = direction;
if(buttonClicked(LEFTBUTTON))
{
direction--;
if(direction < 0)
{
direction = LEFT;
}
}
else if(buttonClicked(RIGHTBUTTON))
{
direction++;
if(direction > 3)
{
direction = TOP;
}
}
buttonRead = (currentDirection != direction);
}
}
void draw()
{
matrix.clear();
drawSnake();
drawFruit();
matrix.writeDisplay();
}
void drawSnake()
{
for(int i=0; i<snakeLength; i++)
{
matrix.drawPixel(snakeX[i], snakeY[i], LED_ON);
}
}
void drawFruit()
{
if(inPlayField(fruitX, fruitY))
{
unsigned long currenttime = millis();
if(currenttime - fruitPrevTime >= fruitBlinkTime)
{
fruitLed = (fruitLed == LED_ON) ? LED_OFF : LED_ON;
fruitPrevTime = currenttime;
}
matrix.drawPixel(fruitX, fruitY, fruitLed);
}
}
boolean inPlayField(int x, int y)
{
return (x>=0) && (x<8) && (y>=0) && (y<16);
}
void nextstep()
{
for(int i=snakeLength-1; i>0; i--)
{
snakeX[i] = snakeX[i-1];
snakeY[i] = snakeY[i-1];
}
switch(direction)
{
case TOP:
snakeY[0] = snakeY[0]-1;
break;
case RIGHT:
snakeX[0] = snakeX[0]+1;
break;
case BOTTOM:
snakeY[0] = snakeY[0]+1;
break;
case LEFT:
snakeX[0]=snakeX[0]-1;
break;
}
if((snakeX[0] == fruitX) && (snakeY[0] == fruitY))
{
snakeLength++;
if(snakeLength < MAX_SNAKE_LENGTH)
{
makeFruit();
}
else
{
fruitX = fruitY = -1;
}
}
}
void makeFruit()
{
int x, y;
x = random(0, 7);
y = random(0, 15);
while(isPartOfSnake(x, y))
{
x = random(0, 7);
y = random(0, 15);
}
fruitX = x;
fruitY = y;
}
boolean isPartOfSnake(int x, int y)
{
for(int i=0; i<snakeLength-1; i++)
{
if((x == snakeX[i]) && (y == snakeY[i]))
{
return true;
}
}
return false;
}
5.Project code2
#include <Wire.h>
#include "Keyestudio_LEDBackpack.h"
#include "Keyestudio_GFX.h"
#include "Breakout.h"
Keyestudio_8x16matrix matrix = Keyestudio_8x16matrix();
Breakout breakout;
int count = 0;
void setup()
{
Serial.begin(9600);
Serial.println("8x16 LED Matrix Test");
pinMode(L_PIN, INPUT);
pinMode(R_PIN, INPUT);
matrix.begin(0x70); // pass in the address
matrix.setBrightness(0);
}
void loop()
{
// action depends on game state - idealy the state should be a part of the Breakout class or a seperate logic class
switch(state)
{
// setup game
case SETUP:
breakout.restart();
breakout.speed = START_SPEED;
state = START;
break;
case START:
// ready to start the game, changed to PLAY if the action button is pushed.
// Change here if paddle should be able to move before you shoot the first ball and start the game.
checkActions();
if(actions == SEL)
{
state = PLAY;
}
break;
case LOST:
// game lost
breakout.lost();
reDraw();
blink(10, 100);
breakout.restart();
breakout.speed = START_SPEED;
state = START;
break;
case WON:
// game won
breakout.won();
reDraw();
blink(10, 100);
breakout.restart();
state = START;
break;
case PLAY:
// game in play
{
if(count > breakout.speed)
{
checkControls();
breakout.play(controls);
count = 0;
if(breakout.bricks == 128)
{
state = WON;
}
if(breakout.ball.y == 7)
state = LOST;
}
delay(20);
count++;
}
}
reDraw();
}
void reDraw(){
for(int i = 0; i < 8; i++){
for(int j = 0; j < 16; j++){ //change 8 into 16
if(breakout.level[i][16-j-1] != 'E'){
matrix.drawPixel(i,j,1);
}
else
matrix.drawPixel(i,j,0);
}
}
matrix.writeDisplay();
}
void checkActions()
{
int count = 0;
while(count < 5 && (!digitalRead(R_PIN))&&(!digitalRead(L_PIN)))
{
count++;
}
if(count > 4)
{
actions = SEL;
return;
}
actions = NO;
}
void checkControls()
{
int count = 0;
while(count < 5 && (!digitalRead(L_PIN)))
{
count++;
}
if(count > 4)
{
controls = LEFT;
return;
}
count = 0;
while(count < 5 && (!digitalRead(R_PIN)))
{
count++;
}
if(count > 4)
{
controls = RIGHT;
return;
}
controls = NONE;
}
void blink(int times, int wait)
{
for(int i = 0; i < times; i++){
matrix.setBrightness(2);
matrix.writeDisplay();
delay(wait);
matrix.setBrightness(0);
matrix.writeDisplay();
delay(wait);
}
}