Arduboy ゲームプログラム 「シューティングゲーム」

Arduboyでゲーム開発へ戻る

●操作方法とルール
・方向キーで自機を移動、左ボタンで弾を撃つ(要連打)、右ボタンは押しっぱなしで発射可
・一周5ステージ。6ステージで1ステージと同じ敵の出現パタンに戻る
・敵の出現頻度は先のステージほど上がる
・プログラムの行数 308行

●ゲームサンプルコード02「シューティングゲーム」
#include <Arduboy2.h>

Arduboy2 arduboy;
BeepPin1 beep;

//for A_Button B_Button
byte nowA=0, nowB=0;
byte oldA=0, oldB=0;

//for String
char txt[10];

//for PROCESS
byte proc = 0;
byte tmr = 0;

//Bitmap unsigned char = byte
const byte PROGMEM pplane[] = {//プレイヤーの戦闘機
  0x0c, 0x14, 0x5c, 0x7f, 0x5c, 0x14, 0x0c, 0x00
};

const byte PROGMEM eplane[] = {//敵の戦闘機
  0x18, 0x38, 0x19, 0x7f, 0x19, 0x38, 0x18, 0x00
};

//移動量
const char XP[10] = {0,-2, 0, 2,-3, 0, 3,-2, 0, 2};
const char YP[10] = {0, 2, 3, 2, 0, 0, 0,-2,-3,-2};

//ステージデータ
const byte SMAX = 5;
const byte SSEC = 60;//何秒ごとにステージが進むか
const byte STAGE[SMAX][3] = {//敵機の最大速度、弾を撃つ、幅寄せする
  {1, 0, 0}, //1
  {2, 0, 1}, //2
  {2, 1, 1}, //3
  {3, 1, 1}, //4
  {3, 2, 2}  //5
};

//Display 128x64

int hi_sc = 100;
int score = 0;
byte stage = 0;
int nexts = 0;
byte energy = 30;

//Player (X, Y)
int px = 44;
int py = 48;

//自機の弾
const byte MMAX = 5;
byte msl_f[MMAX] = { 0 };
int msl_x[MMAX] = { 0 };
int msl_y[MMAX] = { 0 };

//敵
const byte EMAX = 10;
byte emy_f[EMAX] = { 0 };
byte emy_t[EMAX] = { 0 }; // 0は弾、1は機体
byte emy_b[EMAX] = { 0 }; // 弾を撃ったか、弾の左右移動にも使う
int emy_x[EMAX] = { 0 };
int emy_y[EMAX] = { 0 };

//ヒットチェック
int get_dis(int x0, int y0, int x1, int y1) {
  return((x0-x1)*(x0-x1)+(y0-y1)*(y0-y1));
}

void move_player() {//自機を動かす
  byte d = 0;
  if(arduboy.pressed(UP_BUTTON)) {//↑
    d = 8;
    if(arduboy.pressed(LEFT_BUTTON)) d = 7;
    if(arduboy.pressed(RIGHT_BUTTON)) d = 9;
  }
  else if(arduboy.pressed(DOWN_BUTTON)) {//↓
    d = 2;
    if(arduboy.pressed(LEFT_BUTTON)) d = 1;
    if(arduboy.pressed(RIGHT_BUTTON)) d = 3;
  }
  else if(arduboy.pressed(LEFT_BUTTON)) {//←
    d = 4;
  }
  else if(arduboy.pressed(RIGHT_BUTTON)) {//→
    d = 6;
  }
  px = px + XP[d];
  py = py + YP[d];
  if(px <  4) px =  4;
  if(px > 84) px = 84;
  if(py < 12) py = 12;
  if(py > 59) py = 59;

  if((nowA==1&&oldA==0)||(nowB==1&&tmr%5==0)) {
    set_missile(px, py);
    beep.tone(659, 1);//ミの音
  }

  //敵とのヒットチェック
  for(byte j=0; j<EMAX; j++) {
    if(emy_f[j]==1 && get_dis(emy_x[j], emy_y[j], px, py)<7*7) {
      emy_f[j] = 2;
      beep.tone(4186, 3);//低いドの音
      energy -= 10;
      if(energy <= 0) {
        energy = 0;
        proc = 2;
        tmr = 0;
      }
      break;
    }
  }
  arduboy.drawBitmap(px-3, py-3, pplane, 8, 8, WHITE);
}

void set_missile(int x, int y) {//自機が撃つミサイル
  for(byte i=0; i<MMAX; i++) {
    if(msl_f[i]==0) {
      msl_f[i] = 1;
      msl_x[i] = x;
      msl_y[i] = y;
      break;
    }
  }
}

void move_missile() {//自機のミサイルを動かす
  for(byte i=0; i<MMAX; i++) {
    if(msl_f[i]==1) {
      msl_y[i] -= 6;
      arduboy.drawLine(msl_x[i]-1, msl_y[i]-3, msl_x[i]-1, msl_y[i]+3, WHITE);
      arduboy.drawLine(msl_x[i]+1, msl_y[i]-3, msl_x[i]+1, msl_y[i]+3, WHITE);
      for(byte j=0; j<EMAX; j++) {
        if(emy_f[j]==1 && emy_t[j]>0 && get_dis(emy_x[j], emy_y[j], msl_x[i], msl_y[i])<6*6) {
          score++;
          if(score > hi_sc) hi_sc = score;
          emy_f[j] = 2;
          msl_y[i] = -99;
          beep.tone(2217, 1);
        }
      }
      if(msl_y[i]<0) msl_f[i] = 0;
    }
  }
}

void set_enemy() {//敵機を出現させる
  for(byte i=0; i<EMAX; i++) {
    if(emy_f[i]==0) {
      emy_f[i] = 1;
      emy_t[i] = 1;
      emy_b[i] = 0;
      emy_x[i] = 4+rand()%80;
      emy_y[i] = -8;
      break;
    }
  }
}

void set_ebullet(int x, int y) {//敵機の発射する弾
  for(byte i=EMAX-1; i>=0; i--) {
    if(emy_f[i]==0) {
      emy_f[i] = 1;
      emy_t[i] = 0;
      emy_b[i] = 2;
      if(px < x-8) emy_b[i] = 1;
      if(px > x+8) emy_b[i] = 3;
      emy_x[i] = x;
      emy_y[i] = y;
      break;
    }
  }
}

void move_enemy() {//敵(弾と期待)を動かす
  for(byte i=0; i<EMAX; i++) {
    if(emy_f[i]==1) {
      byte spd = i%STAGE[stage%SMAX][0];
      if(emy_t[i]==0) {//弾
        emy_x[i] = emy_x[i] + emy_b[i] - 2;
        emy_y[i] = emy_y[i] + 1 + spd;
        arduboy.drawCircle(emy_x[i], emy_y[i], 1+nexts%2, WHITE);
      }
      if(emy_t[i]==1) {//機体
        if(i%3<STAGE[stage%SMAX][2]) {
          if(emy_x[i]<px-3) emy_x[i] += 1;
          if(emy_x[i]>px+3) emy_x[i] -= 1;
        }
        emy_y[i] = emy_y[i] + 1 + spd;
        if(emy_b[i]==0 && i%3<STAGE[stage%SMAX][1]) {
          emy_b[i] = 1;
          set_ebullet(emy_x[i], emy_y[i]);
        }
        arduboy.drawBitmap(emy_x[i]-3, emy_y[i]-3, eplane, 8, 8, WHITE);
      }
      if(emy_y[i]>72) emy_f[i] = 0;
    }
    if(emy_f[i]>=2) {
      arduboy.drawCircle(emy_x[i], emy_y[i], emy_f[i], WHITE);
      emy_f[i]++;
      if(emy_f[i]==10) emy_f[i] = 0;      
    }
  }
}

void new_game() {//ゲーム開始
  stage = 0;
  score = 0;
  nexts = 0;
  energy = 30;
  px = 44;
  py = 48;
  for(byte i=0; i<MMAX; i++) msl_f[i] = 0;
  for(byte i=0; i<EMAX; i++) emy_f[i] = 0;
  proc = 1;
}

void setup() {
 arduboy.begin();
 arduboy.setFrameRate(30);
 beep.begin();
}

void loop() {
  if (!(arduboy.nextFrame())) return;
  beep.timer();
  nowA = arduboy.pressed(A_BUTTON);
  nowB = arduboy.pressed(B_BUTTON);
  tmr++;
  arduboy.clear();//clear screen to black

  int sec, per;

  switch(proc) {
    case 0://タイトル画面
    arduboy.setTextColor(WHITE);
    arduboy.setTextSize(2);
    arduboy.setCursor(16, 16);
    arduboy.print("1940");
    arduboy.setTextSize(1);
    arduboy.setCursor(4, 40);
    if(tmr%60<30) arduboy.print("Press Button");
    if((nowA==1&&oldA==0)||(nowB==1&&oldB==0)) new_game();
    break;

    case 1://ゲーム
    move_player();
    move_missile();
    move_enemy();
    nexts++;
    if(nexts%(30*SSEC)==0) {
      stage++;
      energy += 10;
      if(energy>30) energy = 30;
    }
    sec = (nexts/30)%SSEC;
    per = 25-stage/5;//何フレごとに敵機が出るか
    if(per < 10) per = 10;
    if(sec<3) {
      arduboy.setTextColor(WHITE);
      arduboy.setCursor(20, 24);
      sprintf(txt, "STAGE %d", stage+1);
      arduboy.print(txt);
    }
    if(3<sec && sec<SSEC-3 && nexts%per==0) set_enemy();
    break;

    case 2://ゲームオーバー
    move_missile();
    move_enemy();
    if(tmr<30*3) {
      arduboy.fillCircle(px+rand()%11-5, py+rand()%11-5, 3+rand()%3, WHITE);
    }
    else {
      arduboy.setTextColor(WHITE);
      arduboy.setCursor(16, 24);
      arduboy.print("GAME OVER");
    }
    if(tmr>30*8) proc = 0;
    break;
  }
  arduboy.fillRect(88, 0, 40, 64, WHITE);
  arduboy.setTextColor(BLACK);
  arduboy.setCursor(94, 2);
  arduboy.print("STAGE");
  arduboy.setCursor(94, 10);
  sprintf(txt, "%5d", stage+1);
  arduboy.print(txt);
  arduboy.setCursor(94, 21);
  arduboy.print("HI-SC");
  arduboy.setCursor(94, 29);
  sprintf(txt, "%04d0", hi_sc);
  arduboy.print(txt);
  arduboy.setCursor(94, 40);
  arduboy.print("SCORE");
  arduboy.setCursor(94, 48);
  sprintf(txt, "%04d0", score);
  arduboy.print(txt);
  arduboy.fillRect(92, 58, 32, 4, BLACK);
  if(energy>0) arduboy.fillRect(93, 59, energy, 2, WHITE);
  arduboy.display();

  oldA = nowA;
  oldB = nowB;
}

Arduboyでゲーム開発のページへ移動
プログラミング、ゲーム開発の書籍を執筆します
メールはこちらへ: