// 01/04/2023 GerrysTech-ArcadeGame-1.3
#include <LedControl.h> // include the LedControl library
// define the pin connections
const int DIN_PIN = 11;
const int CS_PIN = 10;
const int CLK_PIN = 13;
// Define the pins where the buttons are connected
const int BUTTON_FIRE = 2;
const int BUTTON_FORWARD = 3;
const int BUTTON_UP = 4;
const int BUTTON_LEFT = 5;
const int BUTTON_DOWN = 6;
const int DEBOUNCEMS = 200;
const int MISSILE_SPEED = 50;
const int ENEMY_SPEED = 100;
const int ENEMY_WIDTH = 4;
const int ENEMY_HEIGHT = 4;
bool spaceship[4][4] = {
{ 1, 0, 0, 0 },
{ 1, 1, 1, 0 },
{ 1, 1, 1, 1 },
{ 1, 1, 1, 0 }
};
bool enemy[ENEMY_WIDTH][ENEMY_HEIGHT] = {
{ 0, 1, 1, 0 },
{ 1, 0, 1, 1 },
{ 1, 1, 1, 1 },
{ 1, 1, 1, 1 }
};
const bool O[5][5] = {
{ 0, 1, 1, 1, 0 },
{ 1, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 1 },
{ 0, 1, 1, 1, 0 }
};
const bool V[5][5] = {
{ 1, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 1 },
{ 0, 1, 0, 1, 0 },
{ 0, 1, 0, 1, 0 },
{ 0, 0, 1, 0, 0 }
};
const bool E[5][5] = {
{ 1, 1, 1, 1, 1 },
{ 1, 0, 0, 0, 0 },
{ 1, 1, 1, 0, 0 },
{ 1, 0, 0, 0, 0 },
{ 1, 1, 1, 1, 1 }
};
const bool R[5][5] = {
{ 1, 1, 1, 1, 0 },
{ 1, 0, 0, 0, 1 },
{ 1, 1, 1, 1, 0 },
{ 1, 0, 0, 1, 0 },
{ 1, 0, 0, 0, 1 }
};
// create a new instance of the LedControl class
LedControl lc = LedControl(DIN_PIN, CLK_PIN, CS_PIN, 4);
int spaceShipX = 0;
int spaceShipY = 0;
int enemyX = 28;
int enemyY = 4;
bool missleFired = false;
int missileX = -1; // initialize missileX outside of loop()
int missileY = -1;
// initialize lastButtonPressTime for each button
unsigned long lastButtonPressTime[5] = { DEBOUNCEMS, DEBOUNCEMS, DEBOUNCEMS, DEBOUNCEMS, DEBOUNCEMS
};
unsigned long lastMissileMovedTime = 0;
unsigned long lastenemyMovedTime = 0;
bool enemySpawned = false;
int enemySprite = 0;
void setup()
{
initGame();
// initialize the LED module
lc.shutdown(0, false); // turn on the module
lc.setIntensity(0, 8); // set the brightness to 8 (adjust as needed)
lc.clearDisplay(0); // clear the display
// Initialize the serial communication for debugging purposes
Serial.begin(9600);
// Set the button pins as inputs
pinMode(BUTTON_FIRE, INPUT_PULLUP);
pinMode(BUTTON_FORWARD, INPUT_PULLUP);
pinMode(BUTTON_UP, INPUT_PULLUP);
pinMode(BUTTON_LEFT, INPUT_PULLUP);
pinMode(BUTTON_DOWN, INPUT_PULLUP);
Serial.println("Started");
fillDisplay();
delay(1000);
clearDisplay();
drawSpaceship(spaceShipX, spaceShipY);
}
void loop()
{
drawSpaceship(spaceShipX, spaceShipY);
processButtons();
moveMissile();
if (enemySpawned == false)
{
spawnEnemy();
}
moveEnemy();
if (checkCollision(spaceShipX, spaceShipY, 3, 3, enemyX, enemyY, ENEMY_WIDTH - 1, ENEMY_HEIGHT - 1))
{
Serial.println("spaceship and enemy collided!");
drawOver();
while (1)
{
if (digitalRead(BUTTON_FIRE) == LOW)
{
initGame();
break;
}
}
}
if (checkCollision(enemyX, enemyY, ENEMY_WIDTH - 1, ENEMY_HEIGHT - 1, missileX, missileY, 0, 0))
{
Serial.println("missile and enemy collided!");
eraseEnemy(enemyX, enemyY);
enemyX = -4; // enemy has reached the edge, so set it to inactive
enemySpawned = false;
setPixel(missileX, missileY, false); // draw new missile position
missileX = -1;
}
}
void initGame()
{
fillDisplay();
delay(1000);
clearDisplay();
spaceShipX = 0;
spaceShipY = 0;
enemyX = 28;
enemyY = 4;
missleFired = false;
missileX = -1; // initialize missileX outside of loop()
missileY = -1;
enemySpawned = false;
}
void drawLetter(int x, const bool letter[5][5])
{
for (int x1 = 0; x1 < 5; x1++)
{
for (int y1 = 0; y1 < 5; y1++)
{
if (letter[y1][x1])
{
setPixel(x + x1, y1 + 1, true);
}
}
}
}
void clearDisplay()
{
for (int i = 0; i < 32; i++)
{
for (int j = 0; j < 8; j++)
{
setPixel(i, j, false);
}
}
}
void fillDisplay()
{
for (int j = 0; j < 8; j++)
{
for (int i = 0; i < 32; i++)
{
setPixel(i, j, true);
}
}
}
void drawOver()
{
// clear the display
clearDisplay();
// draw the letters for "Over" one by one
int x = 4;
drawLetter(x, O);
x += 6; // leave space between letters
drawLetter(x, V);
x += 6;
drawLetter(x, E);
x += 6;
drawLetter(x, R);
}
bool checkCollision(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2)
{
if (x1 + w1 < x2 || x1 > x2 + w2 || y1 + h1 < y2 || y1 > y2 + h2)
{
// no collision
return false;
}
else
{
// collision detected
return true;
}
}
void spawnEnemy()
{
enemyX = 32;
enemyY = random(1, 4);
enemySpawned = true;
}
void moveEnemy()
{
// update missile position if one is active
if (enemyX >= -4)
{
if (millis() - lastenemyMovedTime > ENEMY_SPEED)
{
eraseEnemy(enemyX, enemyY);
setPixel(enemyX, enemyY, false); // erase old enemy position
if (enemyX > -4)
{
enemyX -= 1; // move enemy to the left
setPixel(enemyX, enemyY, true); // draw new enemy position
}
else
{
enemyX = -4; // enemy has moved off the screen, so set it to inactive
enemySpawned = false;
}
drawEnemy(enemyX, enemyY);
lastenemyMovedTime = millis();
}
}
}
void moveMissile()
{
// update missile position if one is active
if (missileX >= 0)
{
if (millis() - lastMissileMovedTime > MISSILE_SPEED)
{
setPixel(missileX, missileY, false); // erase old missile position
if (missileX < 31)
{
missileX += 1; // move missile to the right
setPixel(missileX, missileY, true); // draw new missile position
}
else
{
missileX = -1; // missile has reached the edge, so set it to inactive
}
lastMissileMovedTime = millis();
}
}
}
void processButtons()
{
if (digitalRead(BUTTON_FIRE) == LOW && millis() - lastButtonPressTime[0] > DEBOUNCEMS)
{
//Serial.println("Pressed Button FIRE");
if (missileX < 0)
{
// only fire missile if one isn't already active
eraseSpaceship(spaceShipX, spaceShipY);
missileX = spaceShipX + 3; // set missile starting position at spaceship nose
missileY = spaceShipY + 2;
drawSpaceship(spaceShipX, spaceShipY);
}
lastButtonPressTime[0] = millis(); // update lastButtonPressTime for button 0
}
if (digitalRead(BUTTON_FORWARD) == LOW && millis() - lastButtonPressTime[1] > DEBOUNCEMS)
{
//Serial.println("Pressed Button FORWARD");
eraseSpaceship(spaceShipX, spaceShipY);
spaceShipX += 1; // move right
drawSpaceship(spaceShipX, spaceShipY);
lastButtonPressTime[1] = millis(); // update lastButtonPressTime for button 1
}
if (digitalRead(BUTTON_UP) == LOW && millis() - lastButtonPressTime[2] > DEBOUNCEMS)
{
//Serial.println("Pressed Button UP");
eraseSpaceship(spaceShipX, spaceShipY);
if (spaceShipY > 0)
{
spaceShipY -= 1; // move up
}
drawSpaceship(spaceShipX, spaceShipY);
lastButtonPressTime[2] = millis(); // update lastButtonPressTime for button 2
}
if (digitalRead(BUTTON_LEFT) == LOW && millis() - lastButtonPressTime[3] > DEBOUNCEMS)
{
//Serial.println("Pressed Button LEFT");
eraseSpaceship(spaceShipX, spaceShipY);
if (spaceShipX > 0)
{
spaceShipX -= 1; // move left
}
drawSpaceship(spaceShipX, spaceShipY);
lastButtonPressTime[3] = millis(); // update lastButtonPressTime for button 3
}
if (digitalRead(BUTTON_DOWN) == LOW && millis() - lastButtonPressTime[4] > DEBOUNCEMS)
{
//Serial.println("Pressed Button DOWN");
eraseSpaceship(spaceShipX, spaceShipY);
if (spaceShipY < 4)
{
spaceShipY += 1; // move up
}
drawSpaceship(spaceShipX, spaceShipY);
lastButtonPressTime[4] = millis(); // update lastButtonPressTime for button 4
}
}
void setPixel(int x, int y, bool state)
{
x = 31 - x;
int module = x / 8; // determine which module the LED is in (0-3)
int moduleX = x % 8; // determine the x position within the module (0-7)
int realX = moduleX + (module *8); // determine the real x position across all modules (0-31)
// print the values to the serial monitor for debugging purposes
/*
Serial.print("Setting LED at (");
Serial.print(x);
Serial.print(", ");
Serial.print(y);
Serial.print(") in module ");
Serial.print(module);
Serial.print(", x = ");
Serial.println(moduleX);
*/
lc.setLed(module, y, moduleX, state); // set the LED in the correct module
}
void drawEnemy(int x, int y)
{
for (int i = 0; i < ENEMY_WIDTH; i++)
{
for (int j = 0; j < ENEMY_HEIGHT; j++)
{
setPixel(x + i, y + j, enemy[j][i]);
}
}
}
void eraseEnemy(int x, int y)
{
for (int i = 0; i < ENEMY_WIDTH; i++)
{
for (int j = 0; j < ENEMY_HEIGHT; j++)
{
setPixel(x + i, y + j, false);
}
}
}
void drawSpaceship(int x, int y)
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
setPixel(x + i, y + j, spaceship[j][i]);
}
}
}
void eraseSpaceship(int x, int y)
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
setPixel(x + i, y + j, false);
}
}
}