Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Классическая игра Asteroids на Arduino Mega и матрице MAX72XX (LED 8×8)

Необходимые компоненты

О проекте

Простая аркадная игра «Астероиды» на одной матрице 8×8. Игрок — космический корабль (один светодиод в нижнем ряду), управляется двумя кнопками. Астероиды (два светодиода вертикально) падают сверху в случайных колонках. Со временем игра ускоряется. При столкновении — взрыв (анимация) и показ счёта (сколько тактов выжили). Нажатие любой кнопки после Game Over — рестарт.

Схема подключения

Алгоритм и код (ключевые моменты)

Полный скетч

/*********************************************************
 * Asteroids на MAX72XX LED Matrix
 * (c) 2018 Joshua Weßner
 *********************************************************/
#include "LedControl.h" // библиотека Eberhard Fahle

// Пины MAX7219
LedControl lc = LedControl(12, 11, 10, 1);

// Глобальные переменные
unsigned long delaytime = 1000;
int score = 0, tick = 300, tickCounter = 1;
unsigned long now = 0, buttonPressed = 0;
const int buttonDelay = 150;
volatile bool gameOver = false;
int ship = 3; // начальная колонка
int columns[8] = {0}; // состояние астероидов
int randomInt;

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

  lc.shutdown(0,false);
  lc.setIntensity(0,1); // яркость 0..15
  lc.clearDisplay(0);

  pinMode(2, INPUT_PULLUP); // Left
  pinMode(3, INPUT_PULLUP); // Right
  attachInterrupt(digitalPinToInterrupt(2), left, FALLING);
  attachInterrupt(digitalPinToInterrupt(3), right, FALLING);
}

// Прерывания кнопок
void left() {
  if (millis() - buttonPressed > buttonDelay) {
    ship = (ship == 0) ? 7 : ship - 1;
    lc.clearDisplay(0);
    buttonPressed = millis();
  }
  if (gameOver) { gameOver = false; setup(); }
}
void right() {
  if (millis() - buttonPressed > buttonDelay) {
    ship = (ship == 7) ? 0 : ship + 1;
    lc.clearDisplay(0);
    buttonPressed = millis();
  }
  if (gameOver) { gameOver = false; setup(); }
}

void loop() {
  if (millis() - now > tick) {
    now = millis();
    score++;

    if (tickCounter == 1) { // каждые 4 такта
      tick = tick / 1.02; // ускорение
      randomInt = random(0,8);
      if (columns[randomInt] == 0) columns[randomInt] = 1; // новый астероид
    }
    tickCounter = (tickCounter == 4) ? 1 : tickCounter + 1;

    // Падение астероидов
    for (int i=0;i<8;i++) {
      if (columns[i] == 10) columns[i] = 0;
      if (columns[i] != 0) columns[i]++;
    }
    lc.clearDisplay(0);
  }

  // Отрисовка
  lc.setLed(0, 7, ship, true); // корабль
  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);
    }
  }

  // Проверка столкновения
  if (columns[ship] == 9 || columns[ship] == 10) {
    lc.clearDisplay(0);
    // Анимация взрыва
    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);
      // Звук
      unsigned long t = millis();
      int rndSnd = 1000;
      while (millis() - t <= 250) {
        rndSnd--;
        tone(9, random(rndSnd, 1000));
      }
      lc.clearDisplay(0);
      noTone(9);
    }
    delay(500);

    // Показ счёта
    String s = String(score);
    char d0 = s.length()>=3 ? s[0] : '0';
    char d1 = s.length()>=2 ? s[s.length()-2] : (s.length()==1 ? '0' : s[0]);
    char d2 = s.length()>=1 ? s[s.length()-1] : '0';
    // Для простоты: выводим последние две цифры
    int pos = 1;
    auto drawDigit = [&](char c, int p) {
      switch(c) {
        case '0': draw0(p); break;
        case '1': draw1(p); break;
        case '2': draw2(p); break;
        case '3': draw3(p); break;
        case '4': draw4(p); break;
        case '5': draw5(p); break;
        case '6': draw6(p); break;
        case '7': draw7(p); break;
        case '8': draw8(p); break;
        case '9': draw9(p); break;
      }
    };
    if (score < 100) {
      drawDigit(d1, 1); drawDigit(d2, 5);
    } else {
      drawDigit(d1, 1); drawDigit(d2, 5);
      // Сотни — точки вверху
      int hundreds = d0 - '0';
      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) { /* ждём нажатия кнопки в прерывании */ }
  }
}

// Функции рисования цифр (3 колонки каждая)
void draw1(int p) { lc.setColumn(0,p,B00001000); lc.setColumn(0,p+1,B00011111); }
void draw2(int p) { lc.setColumn(0,p,B00010111); lc.setColumn(0,p+1,B00010101); lc.setColumn(0,p+2,B00011101); }
void draw3(int p) { lc.setColumn(0,p,B00010001); lc.setColumn(0,p+1,B00010101); lc.setColumn(0,p+2,B00011111); }
void draw4(int p) { lc.setColumn(0,p,B00011100); lc.setColumn(0,p+1,B00000100); lc.setColumn(0,p+2,B00011111); }
void draw5(int p) { lc.setColumn(0,p,B00011101); lc.setColumn(0,p+1,B00010101); lc.setColumn(0,p+2,B00010111); }
void draw6(int p) { lc.setColumn(0,p,B00011111); lc.setColumn(0,p+1,B00010101); lc.setColumn(0,p+2,B00010111); }
void draw7(int p) { lc.setColumn(0,p,B00010000); lc.setColumn(0,p+1,B00010011); lc.setColumn(0,p+2,B00011100); }
void draw8(int p) { lc.setColumn(0,p,B00011111); lc.setColumn(0,p+1,B00010101); lc.setColumn(0,p+2,B00011111); }
void draw9(int p) { lc.setColumn(0,p,B00011101); lc.setColumn(0,p+1,B00010101); lc.setColumn(0,p+2,B00011111); }
void draw0(int p) { lc.setColumn(0,p,B00011111); lc.setColumn(0,p+1,B00010001); lc.setColumn(0,p+2,B00011111); }

Библиотека

Требуется LedControl (Eberhard Fahle): GitHub — установите через Library Manager.

Идеи для развития

Производственный процесс

  1. Шахматы: от древних корней к современному производству — экспертный обзор
  2. Пинбол: история, дизайн и производство классической аркадной игры
  3. Эволюция и мастерство американского футбольного мяча: от древних игр к современным стандартам НФЛ
  4. Создание классической игры Pong на Arduino UNO с OLED-дисплеем: пошаговый урок
  5. Создание рулетки на 37 светодиодов с Arduino Nano
  6. Сборка консоли Pong 24×16 на Arduino Nano и MAX7219
  7. Tetris на Arduino Nano: самостоятельная сборка 16×8 LED-матрицы на 74HC595
  8. Интерактивная игра с джойстиком и LED-обратной связью на Arduino
  9. Интерактивный LED-дисплей в двери с PIR-датчиком — новогоднее приветствие на Arduino
  10. Звукоактивируемый светодиодный дисплей 8 LED на Arduino