Arduinoでシューティングゲームを作ってみた。【Arduino UNO R4】
Arduino UNO R4とOLEDディスプレイを使って、クラシックなシューティングゲームを作ってみました。
その内容を簡単にですがご紹介します。(ソースコードもあるよ)
はじめに
この記事では、Arduino UNOでシューティングゲームを作る方法についてご紹介しています。
下記の注意事項をお読みいただいた上で、ぜひお楽しみください。
必要なもの
1. マイコンボード
本記事では、Arduino UNO R4 Wi-Fiを使います。
2. 電子部品
以下の電子部品を使います。
OLEDディスプレイ(SSD1306, 秋月電子で購入)
ブレッドボード (SAD-101)
ジャンパーワイヤー
タクトスイッチ × 2
回路図
OLEDディスプレイは👆のように繋ぎます。
加えてタクトスイッチをそれぞれ、Arduinoの2、4、6ピンに繋ぎます。
・2ピン が ←ボタン
・4ピン が →ボタン
・6ピン が Aボタン
です。
実際の動作
どのようなゲームなのかは、👆の動画後半で紹介しています。
ソースコード
ソースコードが👇になります。注意事項をよくお読みいただき、ご使用ください。
//当Webサイトに掲載された内容によって生じた損害・損失の一切の責任を負いません。
//当webサイトの免責事項に同意いただける場合に限り、プログラムをご利用いただけます。
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define SW_A 6
#define SW_R 4
#define SW_L 2
#define NUM_SIZE 2
#define WIDTH 6
#define HEIGHT 8
int CENTER_WIDTH = SCREEN_WIDTH / 2 - WIDTH / 2 * NUM_SIZE;
int CENTER_HEIGHT = SCREEN_HEIGHT / 2 - NUM_SIZE * 7 / 2;
int playerPosition = SCREEN_WIDTH/2-SCREEN_WIDTH/16/2;
int playerLifePoint = 3;
int playerMoveSpeed = 2;
int bulletPosition[1][2];
int bulletExistFlag = 0;
int bulletMoveSpeed = 2;
int enemyPosition[1][2];
int enemyExistFlag = 0;
int enemyDefeatCount = 0;
int enemyMoveSpeed = 1;
#define OLED_RESET -1
//画面のサイズ(データシートから)
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
void setup() {
pinMode(SW_A, INPUT_PULLUP);
pinMode(SW_L, INPUT_PULLUP);
pinMode(SW_R, INPUT_PULLUP);
Serial.begin(115200);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
randomSeed(analogRead(0));
initialDisp();
}
void loop() {
display.clearDisplay();
playerPositionDisp(); //自機の表示
bulletPositionDisp(); //弾の表示
enemyPositionDisp();
attackHitJudge();
enemyDefeatCountDisp();
playerLifePointDisp();
display.display();
if(playerLifePoint == 0){
gameOverDisp();
resultDisp();
}
}
//起動時の画面表示
void initialDisp(){
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(CENTER_WIDTH-43, CENTER_HEIGHT+30);
display.println("PRESS A TO START");
display.display();
while(digitalRead(SW_A)==HIGH){}
delay(100);
}
//自機の表示
void playerPositionDisp(void) {
//display.clearDisplay();
if(digitalRead(SW_R)==LOW){
if(playerPosition < SCREEN_WIDTH - SCREEN_WIDTH/16){
playerPosition += playerMoveSpeed;
}
}else if(digitalRead(SW_L)==LOW){
if(playerPosition > 0){
playerPosition -= playerMoveSpeed;
}
}
//Serial.println(playerPosition);
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(playerPosition, SCREEN_HEIGHT - SCREEN_HEIGHT/16);
display.println("A");
//display.display();
//delay(1);
}
//弾の表示
void bulletPositionDisp(void) {
//display.clearDisplay();
if(digitalRead(SW_A) == LOW && bulletExistFlag == 0){
bulletPosition[0][0] = playerPosition+2;
bulletPosition[0][1] = SCREEN_HEIGHT - SCREEN_HEIGHT/16;
bulletExistFlag = 1;
display.fillCircle(bulletPosition[0][0], bulletPosition[0][1], 1, SSD1306_INVERSE);
}else if(bulletExistFlag == 1){
bulletPosition[0][1] -= bulletMoveSpeed;
display.fillCircle(bulletPosition[0][0], bulletPosition[0][1], 1, SSD1306_INVERSE);
}
if(bulletPosition[0][1] < 0){
bulletExistFlag = 0;
}
}
//敵機の表示
void enemyPositionDisp(){
if(enemyExistFlag == 0){
enemyPosition[0][0] = random(SCREEN_WIDTH/16/2,SCREEN_WIDTH+1-SCREEN_WIDTH/16/2);
enemyPosition[0][1] = 0;
display.fillCircle(enemyPosition[0][0], enemyPosition[0][1], 3, SSD1306_INVERSE);
enemyExistFlag =1;
}else if(enemyExistFlag == 1){
enemyPosition[0][1] += enemyMoveSpeed;
display.fillCircle(enemyPosition[0][0], enemyPosition[0][1], 3, SSD1306_INVERSE);
}
if(enemyPosition[0][1] > SCREEN_HEIGHT){
enemyExistFlag = 0;
playerLifePoint--;
}
}
//攻撃が当たったかの判定
void attackHitJudge(){
if(abs(bulletPosition[0][0]-enemyPosition[0][0])<=3 && abs(bulletPosition[0][1] - enemyPosition[0][1]) <= 3 ){
bulletExistFlag = 0;
enemyExistFlag = 0;
enemyDefeatCount++;
//初期化
bulletPosition[0][0] = playerPosition+SCREEN_WIDTH/16/2;
bulletPosition[0][1] = SCREEN_HEIGHT - SCREEN_HEIGHT/16;
enemyPosition[0][1] = 0;
}
}
//敵機の撃破数
void enemyDefeatCountDisp(){
display.setTextColor(WHITE);
display.setTextSize(NUM_SIZE);
if(enemyDefeatCount<10){
display.setCursor(CENTER_WIDTH, CENTER_HEIGHT-10);
}else{
display.setCursor(CENTER_WIDTH-8, CENTER_HEIGHT-10);
}
display.println(enemyDefeatCount);
}
//自機のライフ表示
void playerLifePointDisp(){
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(CENTER_WIDTH-5, CENTER_HEIGHT+10);
display.print("L:");
display.println(playerLifePoint);
}
void difficultyChange(){
if(enemyDefeatCount == 10){
playerMoveSpeed = 4;
bulletMoveSpeed = 4;
enemyMoveSpeed = 2;
}
}
//ゲームオーバー表示
void gameOverDisp(){
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(CENTER_WIDTH-20, CENTER_HEIGHT+4);
display.println("GAME OVER");
display.display();
delay(2000);
}
//リザルト表示
void resultDisp(){
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(CENTER_WIDTH-20, CENTER_HEIGHT+4);
display.print("SCORE: ");
display.println(enemyDefeatCount);
display.println("");
display.println("");
display.println(" RESTART>>");
display.display();
while(digitalRead(SW_A)==HIGH){}
delay(200);
//初期化
playerLifePoint = 3;
enemyDefeatCount = 0;
bulletExistFlag = 0;
enemyExistFlag = 0;
playerMoveSpeed = 2;
enemyMoveSpeed = 1;
bulletMoveSpeed = 2;
}
おわりに
いかがだったでしょうか。
もしこの記事がお役に立てたら、"スキ"や"サポート"をいただけると励みになります!
最後まで読んでいただき、ありがとうございました。
いいなと思ったら応援しよう!
今後ともお役に立てるような記事を発信していきます!よろしければサポートいただけると嬉しいです!