Buat Game Asteroids Klasik dengan Arduino Mega dan LED Matrix MAX72XX
Komponen dan Perlengkapan
Arduino Mega 2560 — 1 unit
Maxim Integrated MAXREFDES99# MAX7219 Display Driver Shield — 1 unit
SparkFun Pushbutton switch 12mm — 2 unit
Buzzer aktif — 1 unit
Breadboard (generic) — 1 unit
Tentang Proyek
Ini adalah game sederhana menggunakan MAX72XX LED-Matrix sebagai tampilan, dua tombol mikro sebagai tombol dan buzzer aktif untuk efek suara.
Anda adalah kapal angkasa dan Anda harus menghindari kontak dengan asteroid yang jatuh ke bawah. Game semakin cepat seiring waktu. Di akhir, skor ditampilkan yang menunjukkan berapa lama Anda bertahan.
Code
kode game asteroidArduino
/********************************************************
* Ini adalah game sederhana menggunakan MAX72XX LED-Matrix.
* Anda adalah kapal angkasa dan Anda harus menghindari kontak dengan
* asteroid yang jatuh ke bawah.
*
* (c) 2018 by Joshua Weßner
*
*******************************************************/
// LedControl by Eberhard Fahle
// lihat: https://wayoda.github.io/LedControl/
#include "LedControl.h"
/* Sekarang kita memerlukan LedControl untuk bekerja.
***** Nomor pin ini mungkin tidak akan bekerja dengan hardware Anda *****
* pin 12 terhubung ke pin DataIn
* pin 11 terhubung ke pin CLK
* pin 10 terhubung ke pin LOAD
* Kami hanya memiliki satu MAX72XX. */
LedControl lc = LedControl(12, 11, 10, 1);
/***************************************************************
* Variabel Global */
/* jeda antara pembaruan tampilan */
unsigned long delaytime = 1000;
/* untuk menampilkan skor */
String scoreString;
int score;
int hundreds;
String scoreStr;
String scoreArr[] = {"" ,"" ,"" };
/* tombol mikro untuk kontrol */
int pinLeft = 2;
int pinRight = 3;
volatile unsigned long buttonPressed;
int buttonDelay = 150; //handle contact bounce
volatile bool gameOver = false;
/* "ritme" game, dalam milidetik */
int tick;
int tickCounter = 1;
/* timestamp */
unsigned long now;
/* tampilan */
int ship;
/* Posisi awal kapal */
int columns[] = {0,0,0,0,0,0,0,0}; // 8 kolom, setiap int adalah baris 1-8.
int randomInt;
/***************************************************************
* setup */
void setup() {
/* Inisialisasi */
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)); // angka acak yang lebih baik
for(int i = 0; i<8; i++) columns[i] = 0;
/* Debugging
* Serial.begin(9600);
* Serial.print(columns[0]); */
/* MAX72XX berada dalam mode hemat daya saat startup, kita harus melakukan panggilan bangun */
lc.shutdown(0, false);
/* Setel kecerahan ke nilai medium */
lc.setIntensity(0, 1);
/* dan hapus tampilan */
lc.clearDisplay(0);
pinMode(pinLeft, INPUT_PULLUP);
pinMode(pinRight, INPUT_PULLUP);
/* lampirkan tekanan tombol ke interrupt */
attachInterrupt(digitalPinToInterrupt(pinLeft), left, FALLING);
attachInterrupt(digitalPinToInterrupt(pinRight), right, FALLING);
}
/***************************************************************
* tangani tekanan tombol kiri */
void left() {
if(millis() - buttonPressed > buttonDelay) // handle switch contact bounce {
if(ship != 0) ship--;
else ship = 7;
lc.clearDisplay(0);
buttonPressed = millis();
}
// setelah game over, tekanan tombol akan memulai ulang game
if(gameOver == true){
gameOver = false;
setup();
}
}
/***************************************************************
* tangani tekanan tombol kanan */
void right() {
if(millis() - buttonPressed > buttonDelay) // handle switch contact bounce {
if(ship != 7) ship++;
else ship = 0;
lc.clearDisplay(0);
buttonPressed = millis();
}
// setelah game over, tekanan tombol akan memulai ulang game
if(gameOver == true){
gameOver = false;
setup();
}
}
/***************************************************************
* loop */
void loop() {
if(millis() - now > tick){ //do every tick
// score is: how many ticks you survived
score++;
now = millis();
if(tickCounter == 1){ //every 4th tick
// make game faster over time
tick = tick/1.02;
// randomly choose column
randomInt = random(0, 8);
// if no asteroid exists in column, create one in row 1.
if(columns[randomInt] == 0){
columns[randomInt] = 1;
}
}
if(tickCounter != 4) tickCounter++;
else tickCounter = 1;
// do for every column
for(int i = 0; i<8; i++){
if(columns[i] == 10) // delete asteroids when out of display
columns[i] = 0;
if(columns[i] != 0) // make asteroids fall down
columns[i]++;
}
lc.clearDisplay(0);
}
/* write to display */
// ship
lc.setLed(0, 7, ship, true);
// asteroids
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);
}
// detect collision of ship with asteroid
if(columns[ship] == 10 or columns[ship] == 9){
lc.clearDisplay(0);
// animate explosion
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);
// explosion sound
unsigned long time = millis();
int randomSound=1000;
while(millis() - time <= 250) {
randomSound--;
tone(9, random(randomSound, 1000));
}
lc.clearDisplay(0);
noTone(9);
}
delay(500);
/* display score */
scoreStr = String(score);
// get single digits from score
int scoreArr[0] = scoreStr.charAt(0);
scoreArr[1] = scoreStr.charAt(1);
scoreArr[2] = scoreStr.charAt(2);
// matrix can only display up to 2 digits (up to 99)
if(score < 100){
for(int i = 0; i<2; i++){
if(scoreArr[i] == "0") draw0(1+i*4);
if(scoreArr[i] == "1") draw1(1+i*4);
if(scoreArr[i] == "2") draw2(1+i*4);
if(scoreArr[i] == "3") draw3(1+i*4);
if(scoreArr[i] == "4") draw4(1+i*4);
if(scoreArr[i] == "5") draw5(1+i*4);
if(scoreArr[i] == "6") draw6(1+i*4);
if(scoreArr[i] == "7") draw7(1+i*4);
if(scoreArr[i] == "8") draw8(1+i*4);
if(scoreArr[i] == "9") draw9(1+i*4);
}
}
// if score is > 100, display only last two digits of score
else{
for(int i = 1; i<3; i++){
if(scoreArr[i] == "0") draw0(1+(i-1)*4);
if(scoreArr[i] == "1") draw1(1+(i-1)*4);
if(scoreArr[i] == "2") draw2(1+(i-1)*4);
if(scoreArr[i] == "3") draw3(1+(i-1)*4);
if(scoreArr[i] == "4") draw4(1+(i-1)*4);
if(scoreArr[i] == "5") draw5(1+(i-1)*4);
if(scoreArr[i] == "6") draw6(1+(i-1)*4);
if(scoreArr[i] == "7") draw7(1+(i-1)*4);
if(scoreArr[i] == "8") draw8(1+(i-1)*4);
if(scoreArr[i] == "9") draw9(1+(i-1)*4);
}
// first digit of score ("hundreds") is displayed as dots: One dot for every hundred.
for(int i = 1; i<10; 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 == true){
// do nothing but wait for button press
}
}
}
///////////////////////////// Draw score digits /////////////////////////////////////////
void draw1(int position){
lc.setColumn(0,0+position,B00001000);
lc.setColumn(0,1+position,B00011111);
}
void draw2(int position){
lc.setColumn(0,0+position,B00010111);
lc.setColumn(0,1+position,B00010101);
lc.setColumn(0,2+position,B00011101);
}
void draw3(int position){
lc.setColumn(0,0+position,B00010001);
lc.setColumn(0,1+position,B00010101);
lc.setColumn(0,2+position,B00011111);
}
void draw4(int position){
lc.setColumn(0,0+position,B00011100);
lc.setColumn(0,1+position,B00000100);
lc.setColumn(0,2+position,B00011111);
}
void draw5(int position){
lc.setColumn(0,0+position,B00011101);
lc.setColumn(0,1+position,B00010101);
lc.setColumn(0,2+position,B00010111);
}
void draw6(int position){
lc.setColumn(0,0+position,B00011111);
lc.setColumn(0,1+position,B00010101);
lc.setColumn(0,2+position,B00010111);
}
void draw7(int position){
lc.setColumn(0,0+position,B00010000);
lc.setColumn(0,1+position,B00010011);
lc.setColumn(0,2+position,B00011100);
}
void draw8(int position){
lc.setColumn(0,0+position,B00011111);
lc.setColumn(0,1+position,B00010101);
lc.setColumn(0,2+position,B00011111);
}
void draw9(int position){
lc.setColumn(0,0+position,B00011101);
lc.setColumn(0,1+position,B00010101);
lc.setColumn(0,2+position,B00011111);
}
void draw0(int position){
lc.setColumn(0,0+position,B00011111);
lc.setColumn(0,1+position,B00010001);
lc.setColumn(0,2+position,B00011111);
}