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);
  }
}