view A-5-4-055722/A-5-4-055722.tex @ 7:47d6428a0af6

change tex file.
author e055722
date Wed, 25 Feb 2009 18:17:01 +0900
parents 8454b822d557
children 9d563ce738ab
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種類に及ぶオブジェクトが存在し、今後も同様な不具合を修正していくとすると、学生実験の進行に大きな支障をきたす事となる。\\
本研究ではCeriumの中でもSceneGraphに着目し、SceneGraph単位でのテストを行うことで、、オブジェクトごとの振る舞いや描画をチェックする。これにより、ゲームのデバッグを容易にし、今後の学生実験におけるゲームの移植や改良、作成を円滑にすることができる。

\section{SceneGraphによるゲームフレームワーク}
	\subsection{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}

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

	\subsection{SceneGraphを用いたゲームプログラム}
	ゲーム内で使用するオブジェクトはBlenderというオープンソースの3次元コンピュータグラフィックスソフトウェアで作成する。作成したオブジェクトモデルはpythonスクリプトによりxmlファイルに変換され、それを元にSceneGraphが生成される。
	生成したSceneGraphはset\_move\_collisionという関数によってmoveやcollisionが実装される。

	\subsubsection{move}
	オブジェクトの動作や状態遷移を記述する。各オブジェクトは複数のmove関数を持っており、set\_move\_collision関数によって状態遷移する。簡単なプログラム例を以下に示す。

{\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}
}

オブジェクトはboss1\_move\_leftによって左に移動する。しかし、そのままだといずれ画面外に消えてしまう。そこでboss1\_move\_left関数中で条件分岐を立て、画面外ぎりぎりの座標になったらset\_move\_collisionでmove\_rightに切り替え、右移動に切り替える。しかし、このままでもいずれ画面外に消えてしまう為、再びset\_move\_collisionに切り替える。これを繰り返す事により、オブジェクトが常に画面内に描画されている状態を保つ事が出来る。

	\subsubsection{collision}
	オブジェクトの衝突判定を記述する。オブジェクト同士が触れた時に行う動作を決定する。例えばシューティングゲームなら弾丸が敵や自機に当たった時にダメージを受ける、ゲームオーバーになる、などの判定を行う。こちらも条件分岐により、set\_move\_collisionで状態遷移する。

\section{CppUnitを用いたSceneGraphのテスト}
	\subsection{CppUnitとは}
	CppUnitはxUnitの一つであり、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として左右のパーツがその子供になっている。\\
	ここで、各オブジェクトのSceneGraphはその親や子、兄弟に対するアドレスを保持している。従って、パーツオブジェクトのテストを行いたい場合は、そのオブジェクトのRootである本体から辿れば、パーツオブジェクトの各パラメータを参照する事が出来る。\\
	そこで、Rootのアドレスを取得するgetSGP()という関数を作成した。getSGP()関数によって取得してきたRootのアドレスを使って、各オブジェクトの座標を取得し、その初期化が正しいか、状態遷移において正しい値を保持いるかテストした。
\newpage
{\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}
}

テストの結果、全てのオブジェクトが正常に初期化されているのが確認出来た。しかし、move,collision中の各オブジェクトの座標は確認出来なかった。これはテストを走らせた時点で全てのテストケースを同時にテストしている為、全てのテストケースにおいて初期化がなされた時点での座標の情報しか参照できない為である。

\section{評価}
CppUnitによるテストはオブジェクトの座標などの初期値はテスト出来るが、move,collisionによって変化した値をテストするのには不向きである。よってCppUnitは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}