目次

第5回以降の趣旨

企業や研究でのプログラム開発では、開発の効率化やバグ等を減らすため
同じような処理は関数等にまとめて、ライブラリ化する事が良く行われます。
そこで今回はゲーム開発を題材にライブラリ開発の意義や方法について学びます。

ライブラリを開発するのにも別のライブラリを使用することは良く行われます.
今回の課題では、3次元物理シミュレータとしてOpen Dynamics Engineを使用して、
ライブラリの使用と開発の両方を経験する事によって、使いやすいライブラリや
開発やメンテナンスしやすいライブラリはどのようなものかを実際に作る事で考えてもらいます。

最終目標

楽しいゲームを開発しやすくするゲームライブラリの開発

Open Dynamics Engine (ODE) について

ODEはこのゲームライブラリがベースにしているオープンソースの物理シミュレーションライブラリです。
正確な物理シミュレーションより速度を重視した設計でゲーム用途に向いています。
今回はスクリプトファイルを実行する事で、自動的にインストールされます。

ODEは物理シミュレーションを行う部分と表示を行う部分に分かれています。
表示プログラムは自分でOpenGL等を用いて作成することも可能ですが、
ODEにはあらかじめdrawstuffという簡易的な表示ライブラリが付属しています。
内部でOpenGLを用いていますが、特に意識する必要はありません。

サンプルコードのインストール

以下のファイルをダウンロードしてインストールして下さい。

$ wget www.er.ams.eng.osaka-u.ac.jp/kawai/AP2018/ap2018_gamelib.zip
$ unzip ap2018_gamelib.zip
$ cd ap2018_gamelib
$ ./start.sh

./start.sh スクリプトによりODEの解凍、コンパイル、インストールと
今回の課題のサンプルプログラムのコンパイルとインストールが行われます。

こちらからでもダウンロードできます。

許可がないと怒られるときは

$ chmod 777 ./start.sh

でやってみる。

Open Dynamics Engine とゲームのサンプルプログラム

インストールしたライブラリ等の解説は次のページに詳しく書いてあります。
gamelibの解説

ライブラリの開発方法を次のページにまとめています。
ただし、今回のサンプルプログラムでは、start.shやexec.sh、Makefileを使うことで、
これらを意識せずに簡単にライブラリとアプリケーションをコンパイルできます。
ライブラリ開発方法

ODE付属のデモプログラムを動かしてみよう

以下のディレクトリにはODEが解凍されています

$ cd src/ode-0.13/ode/demo/
$ ./demo_crash

サンプルプログラムを動かしてみよう

$ cd application/shooting_game
$ ./exec.sh ./shooting_game

許可がないと怒られた場合は

$ chmod 777 ./exec.sh

のコマンドを打ってから実行しましょう。

サンプルプログラムでは、敵(enemy_agent)がランダムに動いており、
弾を撃って当てるとhit_pointが減少し、0になると消滅します。
全ての敵が消滅するとGame Clearが表示され、ゲームが終了されます。
自機(self_agent)と敵の本体が接触すると、
自機のhitpointが減少し、0になるとGame Overが表示され、ゲームが終了されます。

  • サンプルプログラムのボタン配置(後の改造で変更可)
    w: 前進
    s: 後進
    d: 右平行移動
    a: 左平行移動
    x: 右旋回
    z: 左旋回
    k: ジャンプ
    l: 弾を撃ち出す
    v: 視点切り替え(一人称視点と三人称視点.ゲームによってはどちらかに固定した方がよいかも)
    u: 敵キャラ 消滅/生成 (最終的なゲームでは無意味なので削除すべきだが、動作確認のため実装)
    q: 強制終了

サンプルプログラムの構造を理解しよう

  • 全てのファイルをエディタで見てみよう。
application/shooting_game

ディレクトリ内にはゲームアプリケーションのソースコードが入っています。
ゲームアプリケーションはライブラリを使用して具体的なゲームを構成します。

src/gamelib

にはライブラリのソースコードが入っています。

アプリケーションとライブラリのディレクトリ内にあるファイルを全てエディタで開いて、
中身を確認してください。

main.c

に、drawstuffによるシミュレーション管理のための構造体や関数が書かれており。

shooting_game.c

に、実際のゲームのロジックが書かれています。

練習3:マップを広げてみよう

基本的な処理を行う関数を作成し、必要に応じて引数や組み合わせを変更して、
様々なアプリケーションを作成する事を可能にするのがライブラリ開発の醍醐味です。
マップの変更はその1つなので、まず始めに挑戦してみてください。

現在のマップは下図のようになっています。
3×3のブロックに、マップ要素が配置されています。

map.png

マップの拡張

map.h

map.hの

#define MAP_X_SIZE 3
#define MAP_Y_SIZE 3

はマップの大きさを定義しています。
今、3×3のサイズになっていますので、これを4×4に変更してみましょう。

shooting_game.c

shootint_game.c には

void start()

という関数があり、ゲーム環境の初期化を行っています。
そこにマップを構成するための関数が書かれているので、関数を修正してマップを変更してみましょう。

int make_dead_end_walls(int map_x, int map_y, enum DIRECTION direction)

は,MAP_*_SIZEで定義されたマップの座標(map_x, map_y)に行き止まりの通路(壁)を生成する関数です。
directionは行き止まりの方向を決めます。
同様に,他のmake_*_walls関数も通路(壁)を生成する関数です。
現状だと3×3のサイズになっていますので、4×4のサイズを埋めるように関数を追加して、マップを構成してください。

コンパイル

コンパイルには

$ ./start.sh

をすればよいのですが、改めてODEをインストールする必要はないので、

start.sh

中の

tar zxvf ode-${ODE_VERSION}.tar.gz

から、

cp drawstuff/src/.libs/libdrawstuff.* ../../lib/

までを#でコメントアウトしてください。 それと、その下の

cd ../gamelib/

cd gamelib/

に書き換えてください。

マップライブラリ

マップに関するライブラリのヘッダファイルはinclude/gamelib/map.hです。
マップ関数を追加したいときはこのヘッダファイルにその関数を宣言してください。

マップに関するライブラリのソースコードはsrc/gamelib/map.cです。
追加したいマップ関数の中身をここに書き加えてください。

マップライブラリの関数では、どのような壁の配置にするかを設定した後に、
make_wall関数により実際に壁を生成します。

int make_wall( dReal wall_center_position_x, dReal wall_center_position_y,
              dReal wall_direction_x, dReal wall_direction_y,
              dReal wall_length,
              struct GameObject* wall_object );

引数はそれぞれ、壁の中心座標、壁の方向を示す座標、壁の長さ、物体情報です。
この物体情報は実質的にはWallData?構造体になっており、物体のIDや壁を固定するためのジョイントのIDが格納されています。

物体の生成

ODEでは、動力学計算と衝突検出計算が独立に実装されています。
動力学計算の対象は、ワールド内にボディ(剛体)として生成されます。
衝突検出計算の対象は、スペース内にジオメトリ(形状)として生成されます。
最終的に、ボディとジオメトリの対応付けをすることで、物体を生成することができます。

make_wall関数での物体の生成法を解説します。

ボディの生成と位置の指定

dBodyID dBodyCreate(dWorldID world);

ボディをワールドworld内に生成し、ボディIDを返します。

void dBodySetPosition(dBodyID body, dReal x, dReal y, dReal z);

ボディID bodyを絶対座標系の位置(x, y, z)に設定します。

質量パラメータの設定

void dMassSetBox (dMass *mass, dReal density, dReal lx, dReal ly, dReal lz);

質量パラメータmassを密度densityとサイズ(lx, ly, lz)のボックスとして設定します。

void dMassAdjust (dMass *mass, dReal newmass);

質量パラメータmassの質量がnewmassになるように設定します。

void dBodySetMass (dBodyID body, const dMass *mass);

ボディID bodyに上記の質量パラメータmassに設定します。

ボディの回転

void dQFromAxisAndAngle (dQuaternion q, dReal ax, dReal ay, dReal az, dReal angle);

軸(ax, ay, az)まわりにangleラジアン回転したときのクオータニオンqを求めます。

void dBodySetQuaternion (dBodyID body, const dQuaternion q);

ボディID bodyをクオータニオンqに従って回転させます。

ジョイントの生成

dJointID dJointCreateFixed(dWorldID world, dJointGroupID);

ワールドworld内にジョイントを生成して、そのジョイントIDを返します。

void dJointAttach(dJointID joint, dBodyID body1, dBodyID dBody2);

ボディbody1とbody2にジョイントID jointを取り付けます。

void dJointSetFixed(dJointID joint);

ジョイントID jointを固定します。

ジオメトリの生成とボディとの対応付け

dGeomID dCreateBox (dSpaceID space, dReal lx, dReal ly, dReal lz);

スペース space内にサイズ(lx, ly, lz)のボックスを生成し、そのジオメトリIDを返します。

void dGeomSetBody (dGeomID geom, dBodyID body);

ジオメトリID geomとボディID bodyを対応付けます。

課題3:新たなマップ要素を追加しよう

マップに関するライブラリを書き換え、ゲームシステムを更新し、をれを反映したアプリケーションを作ってください。
自分なりのアイディアを実現して良いですが、思いつかなければ(例)の一つを実現してください。

  • 例)坂道
  • 例)ジャンプでしか移動できない段差
  • 例)移動しずらいデコボコがある
  • 例)入るとHit Pointが減少する毒沼

注意事項

  • サンプルコードにバグがある可能性や、課題が分かりづらい等の問題点がある可能性もあります。
    何か気がついた事があれば担当教員やTAに連絡をお願いします。
  • 適宜コメントを入れたり、関数化したりして、他人にもわかりやすいプログラムになるように心がけてください。
    全くコメントのないものは減点します。
  • 他人のプログラムを写したことが判明した場合は、両者とも0点になります。
  • 課題内容に対応していないプログラムには点をつけられません。

提出方法

  • 第7回(5/30)の講義中に課題プログラムのコンパイルと実行を正しくできるかを提出者の環境で確認します。
  • 下記の提出物を第7回講義日(5/30)24:00までにCLEで提出してください。
  • 提出物一式を入れるフォルダの名前は学生番号(ログインIDではない!)にし、zipファイルに圧縮してください。
  • 提出物
    • ソースコード
    • コンパイルに使用するMakefile
    • その他,コンパイル・実行に必要なファイル
    • プログラムの説明(工夫した点・頑張った点,操作方法)

評価方法

  • 仕様を満たしているか
  • ソースコードの可読性の高さ
    • 機能ごとに関数を分け,分かりやすい関数名をつけているか(機能ごとにソースを分けて分割コンパイルをする)
    • 分かりやすい変数名をつけているか
    • 分かりやすいコメントを記述しているか
  • 機能に対応した分かりやすい関数を設計しているか
  • 無駄な処理を行っていないか
  • 工夫に応じて加点する

参考になる情報

質問がある場合

  • 浅田研 岩城までメールをください.
    なお,件名は「AP2018:課題3」としてください.
    ryo.iwaki_AT_ams.eng.osaka-u.ac.jp (_AT_は@に変えてください)

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-04-12 (木) 18:46:09 (70d)