シューティングゲームの4回目です.今回は前回までの演習を構造体を使い実装しています.
まず,12行目から20行目で構造体myObjectを定義しています.メンバとしては,位置pos[3],回転行列R[12],質量m,半径r,サイズside[3],色*colorなどの変数です.
Step3との大きな違いは113行目のinitObject関数でゲームに使う物体を初期化しています.114行目のwelcomeMessage()で,ゲームのウェルカム表示と遊び方を表示します.具体的な遊び方は書いていないので,自分のオリジナルゲームを制作するときは、ユーザーが遊べるように遊び方を書きましょう.
また,Collision関数の引数がStep3では要素数3個の配列からmyObjecgt構造体に変更されています.
それ以外は,Step3とあまり違いはありません.Step3の演習は難しかったので,今回もほとんど同じにしています.構造体の復習を兼ねて,ソースコードを読んで演習をしましょう.
該当するソースコードは次のとおりです.
/* step4 */ /* A simple shooting game */ /* step4 2015-07-09 */ #include "dm4.h" #include <time.h> #include <math.h> #include <stdlib.h> #define TARGET_NUM 10 // 敵の数 #define BULLET_NUM 100 // 弾数 typedef struct myObject { double pos[3]; // 位置 x, y, z [m] double R[12]; // 回転行列 要素数4x3 double m; // 質量 [kg] double r,l; // 半径 [m], 長さ [m] double side[3]; // サイズ x,y,z float *color; // 色 r,g,b int hit; // 弾が当たった数 }; myObject target[TARGET_NUM]; myObject bullet[BULLET_NUM]; myObject robot; int bullet_no = 0; double start_x =0.0, start_y = 0.5, start_z = 0.5; // 初期位置 double R[12] = {1,0,0,0, 0,1,0,0, 0,0,1,0}; // 回転行列が格納される配列, 位置(x,y,z)[m] double sides[3] = {1.0, 0.5, 1.0}; // 直方体のサイズ(x, y, z)[m] static float blue[3] = {0.0, 0.0, 1.0}, red[3] = {1.0, 0, 0}, yellow[3] = {1.0, 1.0, 0}; // 青、赤、黄色 void setBullet(int no, double pos[3]) { bullet[no].pos[0] = pos[0]; bullet[no].pos[1] = pos[1]; bullet[no].pos[2] = pos[2]; } void command(int cmd) { switch (cmd) { case 'a': robot.pos[0] -= 1.0; break; case 'd': robot.pos[0] += 1.0; break; case 'x': robot.pos[1] -= 1.0; break; case 'w': robot.pos[1] += 1.0; break; case 32: setBullet(bullet_no,robot.pos); bullet_no++; printf("bullet=%d\n",bullet_no); break; default: printf("Input %c (%d)\n",(char)cmd, cmd); } } void drawTarget() { int i; for (i = 0; i < TARGET_NUM; i++) { if (target[i].hit) continue; dsSetColor(target[i].color[0],target[i].color[1],target[i].color[2]); // 色の設定 dsDrawBox(target[i].pos,target[i].R,target[i].side); // 直方体の表示 } } void drawBullet() { int i; for (i=0; i< BULLET_NUM; i++) { dsSetColor(bullet[i].color[0], bullet[i].color[1], bullet[i].color[2]); // 色の設定 dsDrawSphere(bullet[i].pos,bullet[i].R, bullet[i].r); // 球の表示 } } void drawRobot() { // ロボットの表示 dsSetColor(robot.color[0], robot.color[1], robot.color[2]); // 黄色 dsDrawSphere(robot.pos, robot.R, robot.r); } // ブロックが他のブロックと衝突したら1を返す,それ以外は0を返す int collision(myObject a, myObject b) { // ブロック間の距離が1未満なら1を返すコードを // ここに書きなさい double dist = sqrt((a.pos[0]- b.pos[0]) * (a.pos[0]-b.pos[0]) + (a.pos[1]-b.pos[1]) * (a.pos[1]-b.pos[1])); if (dist < 0.5) return 1; else return 0; } void simLoop(int pause) { /*** シミュレーションループ ***/ int i,j; for (i=0; i < bullet_no; i++) { bullet[i].pos[1] += 0.01; for (j = 0; j < TARGET_NUM; j++) { if (collision(bullet[i],target[j])) { target[j].hit = 1; } } } drawBullet(); drawTarget(); // 敵の描画 drawRobot(); // ロボットの描画 } // 物体の初期化 void initObject() { int i, j, k, c; // 敵 for (i =0; i < TARGET_NUM; i++) { target[i].pos[0] = 2 * i + start_x - TARGET_NUM + 1; // 位置のx成分 target[i].pos[1] = start_y + 10; // 位置のx成分 target[i].pos[2] = 0.5; target[i].color = blue; target[i].hit = 0; for (k = 0; k < 12; k++) target[i].R[k] = R[k]; for (j = 0; j < 3; j++) target[i].side[j] = sides[j]; } // ロボット robot.pos[0] = start_x; robot.pos[1] = start_y - 10; robot.pos[2] = start_z; robot.color = yellow; for (k = 0; k < 12; k++) robot.R[k] = R[k]; robot.r = 0.5; // 弾 for (i =0; i < BULLET_NUM; i++) { for (j=0; j < 3; j++) bullet[i].pos[j] = robot.pos[j]; bullet[i].color = red; for (k = 0; k < 12; k++) bullet[i].R[k] = R[k]; bullet[i].r = 0.1; } } void welcomeMessage() { printf("****************************************\n"); printf("* Welcom to the Simple Shooting Game ! *\n"); printf("****************************************\n\n"); printf(" Please write here. how to play.\n"); } int main() { /*** main関数 ***/ welcomeMessage(); initObject(); // 物体の初期化 dmLoop(800, 600); // シミュレーションループ ウインドウの幅,高 return 0; }
演習
- step4-150709.zipをダウンロードし,実行してください.
- 遊び方を表示するwelcomeMessage()を自分の好きなように変えよう!
- サンプルでは弾が1発当たると敵は破壊されましたが,1発命中すると敵の色が赤くように改良しよう!
- サンプルでは弾が1発当たると敵は破壊されましたが,1発命中すると敵の色が赤くなり,2発目で破壊するように改良しよう!
- 敵がインベーダーゲームのように移動するように改良しよう!
- 敵も弾を発射するように改良しよう!
- 敵の弾が自分のロボットに命中したら,ゲームオーバーにするよう改良しよう!また,敵を1台破壊したら10点入るようにし,Scoreを表示しよう.
- ロボットの初期位置に弾が残って表示されるバグがあります。バグを取ろう!
コメント