物理エンジンODEで学ぶC言語2015[STEP3:関数]

step3

ODEで学ぶC言語の3回目です.ODEの物理計算の部分は使わず,drawstuffを使った表示だけにします.今回は今まで演習で作ったコードを整理して関数化しています.

まず,76行目のsimLoop関数から説明します.ここはシミュレーションで毎回呼び出される関数です.67行目のcollision関数で弾が敵に衝突しているかどうかの判定を行っています。衝突したら1を返し,それ以外は0を返します.衝突したら,敵が被弾した情報を格納する配列target_hit[j]に1を代入しています.被弾したら1を代入します.
89行目は弾を描画し,91行目で敵を表示しています.

24行目からのキー入力処理をするcommand関数では,スペースキー(32)が押されると,弾を設定し,弾数を1増加させています.

48行目のdrawTarget関数では敵を描画しています.51行目で,敵が被弾していたら,continueを使い,被弾した敵の描画を飛ばします.

 

説明はこのぐらいにして,ソースコードを読んで演習をしましょう.約100行です.

#include "dm3.h"
#include 
#include 
#include 

#define TARGET_NUM 10   // 敵の数
#define BULLET_NUM 100  // 弾数

int bullet_no = 0;
int target_hit[TARGET_NUM] = {0}; // 弾が当たったら1に設定
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 target_pos[TARGET_NUM][3] = {0.0, 0.0, 0.5};   // 位置(x,y,z)[m]
double robot_pos[3]  = {start_x, start_y, start_z}; // ロボットの位置
double bullet_pos[BULLET_NUM][3]; // 弾の位置;
double sides[3] = {1.0, 0.5, 1.0}; // 直方体のサイズ(x, y, z)[m]

void setBullet(int no, double pos[3]) {
    bullet_pos[no][0] = pos[0];
    bullet_pos[no][1] = pos[1];
    bullet_pos[no][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_hit[i]) continue;
        dsSetColor(1.0, 0.0, 0.0); // 色の設定
        target_pos[i][0] = 2 * i  + start_x - TARGET_NUM + 1;  // 位置のx成分
        target_pos[i][1] = start_y + 10;       // 位置のx成分
        target_pos[i][2] = 0.5;                 // 位置のz成分
        dsDrawBox(target_pos[i],R,sides); // 直方体の表示
    }
}

void drawBullet(double pos[3]) {
    int i;
    dsSetColor(0.0, 0.0, 1.0); // 色の設定
    dsDrawSphere(pos,R,0.1); // 球の表示
}

// ブロックが他のブロックと衝突したら1を返す,それ以外は0を返す
int collision(double pos1[3], double pos2[3]) {
    // ブロック間の距離が1未満なら1を返すコードを
    //  ここに書きなさい
    double dist = sqrt((pos1[0]-pos2[0]) * (pos1[0]-pos2[0])
                       + (pos1[1]-pos2[1]) * (pos1[1]-pos2[1]));
    if (dist < 0.5) return 1;
    else            return 0;
}

void simLoop(int pause) {      /***  シミュレーションループ ***/
    int i,j;
    // ロボットの表示
    dsSetColor(1.0, 1.0, 0.0);   // 黄色
    dsDrawSphere(robot_pos, R, 0.5);

    for (i=0; i < bullet_no; i++) {
        bullet_pos[i][1] += 0.01;
        for (j = 0; j < TARGET_NUM; j++) {
            if (collision(bullet_pos[i],target_pos[j])) {
                target_hit[j] = 1;
            }
        }
        drawBullet(bullet_pos[i]);  // 弾の描画
    }
    drawTarget();  // 敵の描画
}

int main() {       /*** main関数 ***/
    robot_pos[1] = start_y - 10;
    dmLoop(800, 600); // シミュレーションループ ウインドウの幅,高
    return 0;
}

では,演習をしながらシューティングゲームを作っていきましょう.

演習

  1. step3-150701.zipをダウンロードし,実行してください.
  2. ンプルでは弾が1発当たると敵は破壊されましたが,1発命中すると敵の色が赤くように改良しよう!
  3. サンプルでは弾が1発当たると敵は破壊されましたが,1発命中すると敵の色が赤くなり,2発目で破壊するように改良しよう!
  4. 敵がインベーダーゲームのように移動するように改良しよう!
  5. 敵も弾を発射するように改良しよう!
  6. 敵の弾が自分のロボットに命中したら,ゲームオーバーにするよう改良しよう!また,敵を1台破壊したら10点入るようにし,Scoreを表示しよう.

コメントを残す

メールアドレスが公開されることはありません。