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でゲーム開発のページへ移動