view A-5-4-055722/A-5-4-055722.tex @ 11:ed5a8511ad3c

finish.
author e055722
date Wed, 25 Feb 2009 20:12:48 +0900
parents b8cfcefb7e56
children
line wrap: on
line source

\documentclass[twocolumn,twoside,9.5pt]{jarticle}
\usepackage[dvips]{graphicx}

\usepackage{fancyhdr}
\usepackage{picins}
\pagestyle{fancy}
\lhead{\parpic{\includegraphics[height=1zw,clip,keepaspectratio]{pic/emblem-bitmap.eps}}琉球大学主催 工学部情報工学科 卒業研究発表会}
\rhead{}
\cfoot{}

\setlength{\topmargin}{-1in \addtolength{\topmargin}{15mm}}
\setlength{\headheight}{0mm}
\setlength{\headsep}{5mm}
\setlength{\oddsidemargin}{-1in \addtolength{\oddsidemargin}{11mm}}
\setlength{\evensidemargin}{-1in \addtolength{\evensidemargin}{21mm}}
\setlength{\textwidth}{181mm}
\setlength{\textheight}{261mm}
\setlength{\footskip}{0mm}
\pagestyle{empty}

\begin{document}
\title{ SceneGraphを用いたゲームプログラムの為のテスト作成手法}
\author{055722G 小林 佑亮 {}{} 指導教員 : 河野真治}
\date{}
\maketitle
\thispagestyle{fancy}

\section{研究背景・目的}

当研究室では学生実験において、PlayStation3を用いた並列的な
ゲームプログラムの作成を行っている。そこで使用されるのが当
研究室で開発したCeriumレンダリングエンジンである。Ceriumを
用いたゲームプログラムの例題としてPlayStation2で動作してい
た超弾帝(スーパーダンディ)というゲームの移植を行った。

その際、オブジェクトの描画、衝突判定などで不具合が発生した。
超弾帝には約100種類に及ぶオブジェクトが存在し、今後も同様な
不具合を修正していく必要があると考えられる。

本研究ではゲームプログラムをSceneGraph単位でテストすることで
オブジェクトごとの振る舞いや描画をチェックする。これにより、
ゲームのデバッグを容易にし、今後の学生実験におけるゲームの移植や
改良、作成を円滑にすることができる。

\section{SceneGraphによるゲームフレームワーク}

ゲームの中の一つの場面(Scene)を構成するオブジェクトやその振
る舞い、ゲームのルールの集合をSceneGraphとする。SceneGraph
のノードは親子関係を持つTreeで構成される。(図\ref{fig:sglist})

\begin{figure}[htbp]
\includegraphics[width=8.5cm]{pic/SceneGraph.eps}
\caption{SceneGraph}
\label{fig:sglist}
\end{figure}

親子関係とは、親オブジェクトの回転や並行移動等の行列計算に
よる頂点座標の変更が子オブジェクトにも反映する関係の事であ
る。これは子に対してスタックに積まれた親の変更行列を掛ける
事で実現できる。


ゲーム内で使用するオブジェクトはBlenderというオープンソース
の3次元コンピュータグラフィックスソフトウェアで作成する。作
成したオブジェクトモデルはpythonスクリプトによりxmlファイル
に変換され、それを元にSceneGraphが生成される。

生成したSceneGraphの各ノードには、オブジェクトの動きを決める
\verb+move+ という関数と、オブジェクトの相互作用を決める
\verb+collision+という関数を入れる変数がある。この変数は、
\verb+set_move_collision+という関数によって変更される。

\subsection{move}
以下の例では、\verb+boss1_move_right+は、ボス1を右に
\verb+node->stack_xyz[0]+だけ移動させる。スクリーン
適当な位置にくると、\verb+move+をボス1を左に移動される関数
\verb+boss1_move_left+に設定する。

{\scriptsize
\begin{verbatim}
static void
boss1_move_right(SceneGraphPtr node, int screen_w, int screen_h) {
  node->xyz[0] += node->stack_xyz[0];
  if(node->xyz[0] > screen_w-280) {
    node->set_move_collision(boss1_move_left, boss1_collision);
  }
}

static void
boss1_move_left(SceneGraphPtr node, int screen_w, int screen_h) {
  node->xyz[0] -= node->stack_xyz[0];
  if(node->xyz[0] < 280) {
     node->set_move_collision(boss1_move_right, boss1_collision);
  }
}
\end{verbatim}
}

この\verb+move+では、ボス1が常に画面内に描画されている必要がある。
これはテストすべき条件の一つとなる。

\subsection{collision}

この変数は、オブジェクトの衝突判定する関数を入れる。
例えばシューティングゲームなら自機と敵、または、弾
を引数に持ち、
当たった時のダメージや、ゲームオーバーの判定を行なう。
判定にしたがって、
\verb+set_move_collision+により新しい\verb+move,collsion+
を設定する。これは、State Pattern と呼ばれるパターンである。

\section{CppUnitを用いたSceneGraphのテスト}

CppUnitは、C++の単体テストを自動化するframe
workである。 CppUnitの特徴は、テストケースを増やす事が容易
であり、1つの事象に対して様々なテストケースを同時にテストす
る事が出来る。また、羅列したテストケースは一括で実行、結果
の表示ができる。(図\ref{fig:cpptest}) 

\begin{figure}[htbp]
\includegraphics[width=8.5cm]{pic/test_state.eps}
\caption{CppUnitTest}
\label{fig:cpptest}
\end{figure}
	
\subsection{ゲームプログラムのテスト} 

3つのSceneGraphを持つオブジェクトのテストを行った。このオブ
ジェクトは本体の他に左右にパーツを1つずつ持つ。本体をTreeの
rootとして左右のパーツがその子供になっている。(図\ref{fig:boss1}) 

\begin{figure}[htbp]
\includegraphics{pic/boss1.eps}
\caption{Boss1}
\label{fig:boss1}
\end{figure}

\newpage
ここで、各オブジェクトのSceneGraphはその親や子、兄弟に対す
るアドレスを保持している。従って、パーツオブジェクトのテス
トを行いたい場合は、そのオブジェクトのRootである本体から辿
れば、パーツオブジェクトの各パラメータを参照する事が出来る。

そこで、Rootのアドレスを取得するgetSGP()という関数を作成し
た。getSGP()関数によって取得してきたRootのアドレスを使って、
各オブジェクトの座標を取得し、その初期化が正しいか、状態遷
移において正しい値を保持しているかテストした。

{\scriptsize
\begin{verbatim}
void
sgTest::rootTest() {
  test_init();

  sg_root->print_member();
  CPPUNIT_ASSERT_EQUAL((float)width/2, sg_root->xyz[0]);
  CPPUNIT_ASSERT_EQUAL(0.0f, sg_root->xyz[1]);
  CPPUNIT_ASSERT_EQUAL(-100.0f, sg_root->xyz[2]);
}

void
sgTest::childTest() {
  while (sg_root) {
    if(sg_root->children != NULL) {
      sg_root->children->print_member();
...
      sg_root = sg_root->children;
    } else if(sg_root->brother != NULL) {
      sg_root->brother->print_member();
      CPPUNIT_ASSERT_EQUAL(0.0f, sg_root->brother->xyz[0]);
...
      sg_root = sg_root->brother;
    } else {
	...
\end{verbatim}
}

このテストの結果、全てのオブジェクトの位置の初期値が正しいことは
確認できた。

Ceriumにおいてもこのテストケースは有効であった。

\section{今後の課題}

しかし、\verb+move,collision+中の各オブジェクトの座
標は確認出来なかった。よって\verb+move,collision+を
テストする為に各\verb+move,collision+を別々に抜き出して
テストする手法を今後実装していく。

\thispagestyle{fancy}
\begin{thebibliography}{9}

\bibitem{1}宮國 渡, 河野 真治, 神里 晃, 杉山 千秋: Cell 用の Fine-grain Task Manager の実装, 第108回システムソフトウェアとオペレーティング・システム研究会(2008)

\bibitem{2}高橋 寿一:知識ゼロから学ぶソフトウェアテスト, 翔泳社 (2005)

\bibitem{3}伊藤 喜一:CppUnit入門, (http://www.ogis-ri.co.jp/otc/hiroba/technical/CppUnit/)

\end{thebibliography}
\end{document}