Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Manufacturing Technology >> Productieproces

Klassiek Asteroids-spel met Arduino Mega en MAX72XX LED-matrix

Onderdelen en benodigdheden

Arduino Mega 2560 1
MAX7219 Display Driver Shield (Maxim Integrated MAXREFDES99#) 1
Drukknoppen 12mm (SparkFun) 2
Buzzer (actief) 1
Breadboard 1

Over dit project

Een simpel, verslavend arcade-spel op een 8×8 LED-matrix (MAX72XX). Je bestuurt een ruimteschip (onderste rij) en moet vallende asteroïden ontwijken. Het spel wordt geleidelijk sneller. Bij botsing: explosie-animatie + geluid, daarna scoreweergave (overleeftijd in ticks). Druk op een knop om te herstarten.

Code

De complete, gecommentarieerde code (C/C++) is hieronder weergegeven. Het gebruikt de LedControl bibliotheek van Eberhard Fahle.

/*********************************************************
 * Asteroids Game - MAX72XX LED Matrix
 * (c) 2018 Joshua Weßner
 *********************************************************/
#include "LedControl.h"

// Pinout: DIN=12, CLK=11, LOAD=10, 1 device
LedControl lc = LedControl(12, 11, 10, 1);

// --- Globale variabelen ---
unsigned long delaytime = 1000;   // basis vertraging (wordt aangepast)
String scoreString;
int score = 0;
int hundreds = 0;
String scoreStr;
String scoreArr[3] = {"", "", ""};

int pinLeft = 2;
int pinRight = 3;
volatile unsigned long buttonPressed = 0;
int buttonDelay = 150;            // debounce
volatile bool gameOver = false;

int tick = 300;                   // spelsnelheid (ms)
int tickCounter = 1;
unsigned long now = 0;

int ship = 3;                     // startpositie ruimteschip (kolom 0-7)
int columns[8] = {0};             // 8 kolommen, waarde = rij (1-8) of 0=leeg
int randomInt;

// --- Setup ---
void setup() {
  gameOver = false;
  hundreds = 0;
  scoreArr[0] = scoreArr[1] = scoreArr[2] = "";
  score = 0;
  tick = 300;
  tickCounter = 1;
  ship = 3;
  now = millis();
  buttonPressed = millis();
  randomSeed(analogRead(15));
  for (int i = 0; i < 8; i++) columns[i] = 0;

  lc.shutdown(0, false);       // wake up
  lc.setIntensity(0, 1);       // helderheid (0-15)
  lc.clearDisplay(0);

  pinMode(pinLeft, INPUT_PULLUP);
  pinMode(pinRight, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pinLeft), left, FALLING);
  attachInterrupt(digitalPinToInterrupt(pinRight), right, FALLING);
}

// --- Interrupt handlers (met debounce) ---
void left() {
  if (millis() - buttonPressed > buttonDelay) {
    if (ship != 0) ship--; else ship = 7; // wrap-around
    lc.clearDisplay(0);
    buttonPressed = millis();
  }
  if (gameOver) { gameOver = false; setup(); }
}

void right() {
  if (millis() - buttonPressed > buttonDelay) {
    if (ship != 7) ship++; else ship = 0;
    lc.clearDisplay(0);
    buttonPressed = millis();
  }
  if (gameOver) { gameOver = false; setup(); }
}

// --- Main Loop ---
void loop() {
  if (millis() - now > tick) {
    // Elke tick: score++, snelheid++, nieuwe asteroïden, vallen laten
    score++;
    now = millis();

    if (tickCounter == 1) { // elke 4e tick
      tick = tick / 1.02;   // versnellen
      randomInt = random(0, 8);
      if (columns[randomInt] == 0) columns[randomInt] = 1; // nieuwe asteroïde bovenaan
    }
    if (tickCounter != 4) tickCounter++; else tickCounter = 1;

    // Asteroïden laten vallen
    for (int i = 0; i < 8; i++) {
      if (columns[i] == 10) columns[i] = 0; // onderin verdwenen
      if (columns[i] != 0) columns[i]++;    // een rij naar beneden
    }
    lc.clearDisplay(0);
  }

  // --- Weergave ---
  // Ruimteschip (onderste rij = 7)
  lc.setLed(0, 7, ship, true);

  // Asteroïden (2 LED's hoog voor betere zichtbaarheid)
  for (int i = 0; i < 8; i++) {
    if (columns[i] > 0) {
      lc.setLed(0, columns[i] - 2, i, true);
      lc.setLed(0, columns[i] - 3, i, true);
    }
  }

  // --- Botsing detectie ---
  // Schip op rij 7, asteroïde bereikt rij 9 of 10 (visualisatie 2 LED's hoog)
  if (columns[ship] == 10 || columns[ship] == 9) {
    lc.clearDisplay(0);
    // Explosie animatie
    for (int i = 0; i < 4; i++) {
      lc.setLed(0, 7, ship + i, true);
      lc.setLed(0, 7, ship - i, true);
      lc.setLed(0, 7 - i, ship + i, true);
      lc.setLed(0, 7 - i, ship - i, true);
      lc.setLed(0, 7 - 1.5 * i, ship, true);
      // Explosie geluid
      unsigned long time = millis();
      int randomSound = 1000;
      while (millis() - time <= 250) {
        randomSound--;
        tone(9, random(randomSound, 1000));
      }
      lc.clearDisplay(0);
      noTone(9);
    }
    delay(500);

    // --- Score tonen op matrix (max 2 digits, 99) ---
    scoreStr = String(score);
    scoreArr[0] = scoreStr.charAt(0);
    scoreArr[1] = scoreStr.charAt(1);
    scoreArr[2] = scoreStr.charAt(2);

    if (score < 100) {
      for (int i = 0; i < 2; i++) {
        drawDigit(scoreArr[i], 1 + i * 4);
      }
    } else {
      // Alleen laatste 2 digits + honderdtallen als stippen
      for (int i = 1; i < 3; i++) {
        drawDigit(scoreArr[i], 1 + (i - 1) * 4);
      }
      for (int i = 1; i <= 9; i++) {
        if (scoreArr[0] == String(i)) hundreds = i;
      }
      for (int i = 1; i <= hundreds; i++) {
        lc.setLed(0, 0, i - 1, true);
        lc.setLed(0, 1, i - 1, true);
        delay(200);
      }
    }
    gameOver = true;
    while (gameOver) { /* wacht op knop (interrupt herstart) */ }
  }
}

// --- Cijfer-tekenfuncties (3 kolommen breed) ---
void drawDigit(String d, int pos) {
  if (d == "0") draw0(pos);
  else if (d == "1") draw1(pos);
  else if (d == "2") draw2(pos);
  else if (d == "3") draw3(pos);
  else if (d == "4") draw4(pos);
  else if (d == "5") draw5(pos);
  else if (d == "6") draw6(pos);
  else if (d == "7") draw7(pos);
  else if (d == "8") draw8(pos);
  else if (d == "9") draw9(pos);
}

void draw1(int p) { lc.setColumn(0, 0+p, B00001000); lc.setColumn(0, 1+p, B00011111); }
void draw2(int p) { lc.setColumn(0, 0+p, B00010111); lc.setColumn(0, 1+p, B00010101); lc.setColumn(0, 2+p, B00011101); }
void draw3(int p) { lc.setColumn(0, 0+p, B00010001); lc.setColumn(0, 1+p, B00010101); lc.setColumn(0, 2+p, B00011111); }
void draw4(int p) { lc.setColumn(0, 0+p, B00011100); lc.setColumn(0, 1+p, B00000100); lc.setColumn(0, 2+p, B00011111); }
void draw5(int p) { lc.setColumn(0, 0+p, B00011101); lc.setColumn(0, 1+p, B00010101); lc.setColumn(0, 2+p, B00010111); }
void draw6(int p) { lc.setColumn(0, 0+p, B00011111); lc.setColumn(0, 1+p, B00010101); lc.setColumn(0, 2+p, B00010111); }
void draw7(int p) { lc.setColumn(0, 0+p, B00010000); lc.setColumn(0, 1+p, B00010011); lc.setColumn(0, 2+p, B00011100); }
void draw8(int p) { lc.setColumn(0, 0+p, B00011111); lc.setColumn(0, 1+p, B00010101); lc.setColumn(0, 2+p, B00011111); }
void draw9(int p) { lc.setColumn(0, 0+p, B00011101); lc.setColumn(0, 1+p, B00010101); lc.setColumn(0, 2+p, B00011111); }
void draw0(int p) { lc.setColumn(0, 0+p, B00011111); lc.setColumn(0, 1+p, B00010001); lc.setColumn(0, 2+p, B00011111); }

Schema

Zie bijgevoegde schakelschema-afbeelding voor de bedrading van MAX7219 shield, drukknoppen (pin 2 & 3 met interne pull-up) en buzzer (pin 9).

Productieproces

  1. Schaken: van oorspronkelijke oorsprong tot moderne productie – een expert overzicht
  2. Pinball: Geschiedenis, Ontwerp en Productie van een Klassiek Arcade Spel
  3. De Evolutie en Vakmanschap van Amerikaans Football: Van Oude Spelen tot Moderne NFL Standaarden
  4. Bouw een Klassiek Pong-spel op Arduino UNO met OLED-display – Stap-voor-stap Tutorial
  5. Bouw Je Eigen 37-LED Roulette-spel met Arduino Nano
  6. Bouw een 24×16 LED Pong-console met Arduino Nano & MAX7219
  7. Bouw een Tetris-spel met Arduino Nano op een Zelfgemaakte 16×8 LED-matrix
  8. Interactieve Joystick Game met Arduino en LED Feedback
  9. Interactieve LED-matrix deurdisplay met PIR-bewegingsensor – Arduino vakantiegroet
  10. Geluidsgeactiveerd 8-LED Lichtdisplay met Arduino
  11. Bouw een Slimme Arduino Vierpotige Robot: Stap-voor-Stap Handleiding