Mercurial > hg > Papers > 2011 > koba-master
changeset 17:d39c452010ea
add poster base.
author | koba <koba@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 15 Feb 2011 18:21:02 +0900 |
parents | 4524ba5be532 |
children | a5fb2dea1c60 |
files | poster/master-lt.html poster/ui/CVS/Entries poster/ui/CVS/Repository poster/ui/CVS/Root poster/ui/default/CVS/Entries poster/ui/default/CVS/Repository poster/ui/default/CVS/Root poster/ui/default/blank.gif poster/ui/default/bodybg.gif poster/ui/default/framing.css poster/ui/default/iepngfix.htc poster/ui/default/opera.css poster/ui/default/outline.css poster/ui/default/pretty.css poster/ui/default/print.css poster/ui/default/s5-core.css poster/ui/default/slides.css poster/ui/default/slides.js |
diffstat | 18 files changed, 1629 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/poster/master-lt.html Tue Feb 15 18:21:02 2011 +0900 @@ -0,0 +1,873 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + +<head> +<title>master_presentation</title> +<!-- metadata --> +<meta name="generator" content="S5" /> +<meta name="version" content="S5 1.1" /> +<meta name="presdate" content="20050728" /> +<meta name="author" content="Eric A. Meyer" /> +<meta name="company" content="Complex Spiral Consulting" /> +<!-- configuration parameters --> +<meta name="defaultView" content="slideshow" /> +<meta name="controlVis" content="hidden" /> +<!-- style sheet links --> +<link rel="stylesheet" href="ui/default/slides.css" type="text/css" media="projection" id="slideProj" /> +<link rel="stylesheet" href="ui/default/outline.css" type="text/css" media="screen" id="outlineStyle" /> +<link rel="stylesheet" href="ui/default/print.css" type="text/css" media="print" id="slidePrint" /> +<link rel="stylesheet" href="ui/default/opera.css" type="text/css" media="projection" id="operaFix" /> +<!-- S5 JS --> +<script src="ui/default/slides.js" type="text/javascript"></script> +</head> +<body> + +<div class="layout"> +<div id="controls"><!-- DO NOT EDIT --></div> +<div id="currentSlide"><!-- DO NOT EDIT --></div> +<div id="header"></div> +<div id="footer"> +<h1>[date:11/02/09]</h1> +<h2>Game Framework Cerium を用いたゲームプログラミングにおけるテスト手法の提案</h2> +</div> + +</div> + + +<div class="presentation"> + +<div class="slide"> +<h1>Game Framework Cerium を用いた<br> + ゲームプログラミングにおける<br> + テスト手法の提案</h1> +<h3>発表者:小林 佑亮</h3> +<h4>所属:琉球大学 理工学研究科 情報工学専攻 並列信頼研究室</h4> +<h4>指導教員:河野 真治</h4> +</div> + +<div class="slide"> +<h1>発表内容</h1> +<ol> +<li>序論</li> +<li>CppUnit を用いたゲームプログラムテスト</li> +<li>ゲームプログラミングにおけるテスト</li> +<li>Cell BE と Cerium</li> +<li>テスト対象のシューティングゲーム Super Dandy</li> +<li>構築したテスト環境</li> +<li>テスト環境によるデバッグと検証</li> +<li>まとめ</li> +</ol> +</div> + +<div class="slide"> +<h1>研究背景</h1> +<font size="4"><ul> +<li>我々は PlayStation3(以下 PS3) 上においてゲーム開発が行えるフレームワーク + Cerium を開発した。</li> +<li>Cerium ではプログラムを Task という単位に分けて管理し、これを PS3 の +アーキテクチャである Cell B.E に渡して並列処理を行う。</li> +<li>シーケンシャルなプログラムを Task に分割して並列実行させても、 +逐次実行させた時と同じ動作をするとは限らない。</li> +<li>オブジェクト同士のデータの同期や、処理の実行順序など、シーケンシャルな +プログラムに比べて、バグを発生させる要因は多い。</li> +<li>また、ゲームプログラムの特徴はプレイヤーの入力やプログラム内にある乱数 +などの非決定的な要素が多いことが挙げられる。</li> +<li>これによってバグの再現性が低下するため、ゲームプログラムのテストは + 一般的なソフトウェアのテストに比べて難しい</li> +</ul></font> +</div> + +<div class="slide"> +<h1>研究目的</h1> +<font size="4"><ul> +<li>本研究では Task に分割されたゲームプログラムがシーケンシャルなバージョン +と同じ動作である事を確認できるテスト環境の構築を目的とする。</li> +<li>プレイヤーの入力や乱数などの非決定的な要素を固定化し、バグの再現性を +低下させずにテストを行えるようにする。</li> +<li>動作の同一性を確かめるために必要なパラメータの書き出しを行う</li> +<li>高速なテストを行う為、テストに影響しない範囲で実行時間が大きい処理を +排除する。</li> +</ul></font> +</div> + +<div class="slide"> +<h1>CppUnit</h1> +<ul class="simple"> + <li>xUnit と呼ばれる単体テストのためのフレームワークの内の 1 つ</li> + <li>単体テストとは関数やメソッドなどの比較的小さな単位で行うテストで、 + モジュールへの入力と出力を調べることでそのモジュールが要求された仕様を + 満たしているかをテストする手法</li> + <li>CppUnit は 1 つの事象に対して様々なテストケースを同時にテストできる</li> + <li>羅列したテストケースは一括で実行と結果表示が出来る</li> + <li>しかしこうした単体テストではゲームプログラムのバグを見つけるのは難しい</li> +</ul> +</div> + +<div class="slide"> +<h1>ゲームオブジェクトに対するテスト</h1> +<table> + <tr> + <td><ul class="simple"> + <li>3 つの SceneGraph ノードを持つ</li> + <li>本体を tree の root として左右のパーツがその子供になっている。</li> + <li>オブジェクトの動き(Move)として左右の平行移動をする</li> + <li>簡単なゲームの例題</li> + </ul></td> + <td><img src="images/boss1_SG.png" width=300 height=250></td> + </tr> + </table> +</div> + +<div class="slide"> +<h1>ゲームオブジェクトに対するテスト</h1> +<h2>テスト方法</h2> +<ul class="simple"> + <li>SceneGraph tree の root のアドレスを取得</li> + <li>そこから tree を辿って各オブジェクトの座標を取得</li> + <li>初期値を入力してオブジェクトの初期化が正しいか調べる</li> +</ul> +<h2>テスト結果</h2> +<ul class="simple"> + <li>全てのオブジェクトの初期値が正しい事がわかった</li> + <li>初期化の段階でバグが発生していないことが保証された</li> +</ul> +</div> + +<div class="slide"> +<h1>ゲームに対する単体テストの欠点</h1> +<ul> +<li>単体テストは瞬間的な値の正しさは調べられる</li> +<li>常にオブジェクトのパラメータが変化するゲームには有効的ではない</li> +<li>ゲームのバグは他のオブジェクトのパラメータとの関係により発生するものが +多い</li> +<li>一般的な単体テストではゲームのバグの発見は難しい</li> +</ul> +</div> + +<div class="slide"> +<h1>ゲームプログラムの特徴</h1> +<table> + <tr> + <td><ul class="simple"> + <li>多数のオブジェクトが存在する</li> + <li>オブジェクト同士が相互に干渉する</li> + <li>プレイヤーの入力やゲームの進行によって新たなオブジェクトが生成される</li> + <li>オブジェクトは他のオブジェクトのパラメータを見て、衝突判定や挙動の変化をする</li> + </ul></td> + <td> + <img src="images/game.png" width=300 height=250/> + </td> + </tr> +</table> +</div> + +<div class="slide"> +<h1>ゲームプログラムの特徴</h1> +<ul class="simple"> + <li>プレイヤーの入力がゲームに影響する</li> + <li>遷移する状態が膨大</li> + <li>遷移する状態が仕様の範囲内に収まるかをチェックするテストは向かない</li> + <li>実際にプレイヤーがゲームをプレイするのが重要なテスト</li> +</ul> +</div> + +<div class="slide"> +<h1>プレイヤーの入力の不定性</h1> +<ul class="simple"> + <li>プレイヤーの入力は常に非決定的(毎回結果が異なる)</li> + <li>同じ人間が同じゲームの同じ場面をプレイしても全く同じ入力をする可能性 + は極めて低い</li> + <li>プレイヤーは制御不能なランダム要素</li> + <li>テストにおけるバグの再現性を低下させている</li> +</ul> +</div> + +<div class="slide"> +<h1>ゲームにおける乱数の役割</h1> +<ul class="simple"> + <li>オブジェクトの振る舞いに多様性を持たせる</li> + <li>ランダムな位置配置に使われる</li> + <li>乱数のランダム性はデバッグをする上でバグの再現を困難にする</li> + <li>対処法としては、乱数生成器を無効にするか、定数でシードする</li> +</ul> +</div> + +<div class="slide"> +<h1>Cell Broadband Engine</h1> +<ul class="simple"> + <li>SCE と 東芝、IBM によって開発されたCPU</li> + <li>2 thread の PPE(PowerPC Processor Element) と 8 個の + SPE(Synergistic Processor Element)を持つ</li> + <li>各 CPU 間は高速リングバスであるEIB(Element Interface Bus)で + 繋がっている</li> +</ul> +<center> +<img src="images/cell.png" width=350 height=150/> +</center> +</div> + +<div class="slide"> +<h1>Game Framework Cerium</h1> +<dl> + <b><dt>SceneGraph</dt></b> + <dd>オブジェクトのパラメータやポリゴン情報を tree 構造のノードで管理</dd> + <b><dt>Rendering Engine</dt></b> + <dd>3 種類の Task によって並列に描画処理を行う</dd> + <b><dt>TaskManager</dt></b> + <dd>Task を動的に SPE へ割り振るカーネルとして振舞う</dd> +</dl> +</div> + +<div class="slide"> +<h1>Task Manager</h1> +<ul class="simple"> + <li>Task と呼ばれる分割されたプログラムを管理する</li> + <li>Task の単位はサブルーチンまたは関数とする。</li> + <li>生成された Task を依存関係を考慮しながら SPE に転送したり、実行する</li> +</ul> +</div> + +<div class="slide"> +<h1>Task 生成時に使用できる API</h1> +<center> +<table border="1" cellspacing="0"> + <tr><th>create_task</th><td>Task を生成する</td> + <tr><th>set_inData</th><td>Task への入力データのアドレスを追加</td> + <tr><th>set_outData</th><td>Task からの出力先アドレスを追加</td> + <tr><th>set_param</th><td>Task に 32 bit の情報を追加</td> + <tr><th>set_post</th><td>Task が終了した後に PPE 側で実行される関数を登録</td> +</table> +</center> +</div> + +<div class="slide"> +<h1>シューティングゲーム SuperDandy</h1> +<table> + <tr> + <td><ul class="simple"> + <li>我々が PlayStation 上でのゲーム開発を行っていた 1998 年に開発</li> + <li>タイトルからゲーム本編中の敵機の登場、ステージクリア、エンディングと + ゲーム的な要素が多い</li> + <li>PlayStation, PlayStation2 Linux, OpenGL と伝統的に移植されてきた</li> + </ul></td> + <td> + <img src="images/dandy.png" width=300 height=250/> + </td> + </tr> +</table> +</div> + +<div class="slide"> +<h1>Super Dandy 移植の利点</h1> +<ul class="simple"> + <li>全 5 ステージという、ある程度のボリュームのあるゲーム</li> + <li>衝突判定やオブジェクト判定、ステージクリアによるシーン切り替えと、基本的なゲームの要素が入っている</li> + <li>動作結果を過去の環境と比較することによる新たな環境のチューニングができる</li> +</ul> +</div> + +<div class="slide"> +<h1>Super Dandy Cerium version</h1> +<ul class="simple"> + <li>最初に Cerium に対応したバージョン</li> + <li>描画処理に Cerium の Rendering Engine を用いており、その箇所のみ + Task で処理される</li> + <li>基本的なゲームの処理は変わらない</li> +</ul> +</div> + +<div class="slide"> +<h1>Task Dandy(Super Dandy Task version)</h1> +<table> + <tr> + <td><ul class="simple"> + <li>オブジェクトの Move や Collision を Task 化</li> + <li>オブジェクトの描画は SceneGraph tree の形成、Rendering Task の + 生成といった Cerium の描画処理を使用</li> + <li>できるだけ Super Dandy のコードやデータ構造を流用</li> + </ul></td> + <td> + <img src="images/taskdandy.png" width=300 height=300/> + </td> + </tr> +</table> +</div> + +<div class="slide"> +<h1>Task Dandy のデータ構造</h1> +<dl> + <b><dt>player</dt></b> + <dd>プレイヤーの操作する機体。xy 座標、残機数、無敵時間、 + コンテニュー回数などを持つ。</dd> + <b><dt>CHARACTER</dt></b> + <dd>敵機や敵の弾。xy 座標とその方向の速さ、体力、倒したときのスコア、 + オブジェクトの種類を表すキャラナンバーを持つ。</dd> + <b><dt>tama_lv1〜lv3、laser_lv1〜lv3</dt></b> + <dd>プレイヤーが撃った弾。xy 座標をもつ。プレイヤーが射撃ボタンを押すと + 弾が配列に格納され、敵に当たるか画面外にいくと消滅する。</dd> +</dl> +</div> + +<div class="slide"> +<h1>データ転送に用いる Property</h1> +<table> + <tr> + <td><ul class="simple"> + <li>必要なパラメータをまとめて Property にコピーして set_inData</li> + <li>複数のデータをまとめることによって Task の inData を簡略化</li> + </ul></td> + <td> + <img src="images/property.png" width=400 height=300/> + </td> + </tr> +</table> +</div> + +<div class="slide"> +<h1>ステートパターン</h1> +<table> + <tr> + <td><font size="4"><ul class="simple"> + <li>オブジェクトの Move と Collision を行う</li> + <li>オブジェクトが関数ポインタを持ち、そのポインタが示す関数が + Move や Collision の処理を行う</li> + <li>関数ポインタのアドレスを他の関数ポインタのアドレスに書き換え、 + オブジェクトの状態遷移をする</li> + <li>しかし、メモリが独立している SPE 上で状態遷移をする場合、 + ステートパターンで使用した関数ポインタのアドレスは使えない</li> + </ul></font></td> + <td> + <img src="images/state_pattern.png" width=300 height=200/> + </td> + </tr> +</table> +</div> + +<div class="slide"> +<h1>SPE における状態遷移</h1> +<table> + <tr> + <td><ul class="simple"> + <li>SPE 上では Task の ID を変更</li> + <li>PPE 上で変更された ID を見て次に生成する Task の種類を変更</li> + <li>オブジェクトの状態遷移が成立</li> + </ul></td> + <td> + <img src="images/task_change.png" width=400 height=300/> + </td> + </tr> +</table> +</div> + +<div class="slide"> +<h1>目標とするテスト環境</h1> +<ul class="simple"> + <li>プレイヤーの入力や乱数などの非決定的な要素の固定化</li> + <li>現在動作中の OpenGL バージョンと Cerium バージョン、そして Task Dandy + の動作が同一かどうか確認できるテストログの出力</li> + <li>高速なテスト環境</li> +</ul> +</div> + +<div class="slide"> +<h1>Capture モードと Trace モード</h1> +<ul class="simple"> + <li>プレイヤーからの入力を 1 フレーム毎に記録する</li> + <li>記録した入力をバイナリデータとして書き出す</li> + <li>書き出したファイルを読み込むことで過去のプレイヤー入力を再現できる</li> + <li>実行ファイルにオプションとファイル名を付けて起動する</li> + <li>3 つの Super Dandy 全てで使える</li> + <li>旧バージョンの入力を記録し、新バージョンで読み出すことができる</li> + <li>入力が同じでも動作が違えばそこにバグが潜んでいると考えられる</li> +</ul> +</div> + +<div class="slide"> +<h1>入力を記録するバッファのデータ構造</h1> +<ul class="simple"> + <li>単方向リスト型のバッファ</li> + <li>Capture モードではバッファが足りなくなると新たなバッファを確保する</li> + <li>Trace モードでは必要なバッファサイズを計算し、あらかじめバッファを確保しておく</li> +</ul> +<center> + <img src="images/pad_buff.png" width=400 height=150> +</center> +</div> + +<div class="slide"> +<h1>SPE における乱数生成</h1> +<font size="4"><ul class="simple"> + <li>シーケンシャルプログラムでは 1 つの乱数列から順番に乱数を取得</li> + <li>Cell における並列プログラムでは各 SPE 内で 独自の乱数列を生成</li> + <li>SPE に送られた Task は SPE 固有の乱数列を使用</li> + <li>SPE 内では依存関係を持たない Task は実行順序が不定</li> + <li>シーケンシャルと並列で異なる結果が出る</li> +</ul></font> +<center> + <img src="images/spe_random.png" width=400 height=150> + </center> +</div> + +<div class="slide"> +<h1>SPE 内での予測可能な乱数の使用</h1> +<table> + <tr> + <td><ul class="simple"> + <li>あらかじめ PPE 内で乱数列を生成しておく</li> + <li>inData として Task に渡す</li> + <li>Move Task や Collision Task の生成タイミングは Super Dandy の + Move や Collision のタイミングと同じ</li> + <li>Super Dandy と同じ乱数が使用できる</li> + </ul></td> + <td> + <img src="images/ppe_random.png" width=400 height=300/> + </td> + </tr> +</table> +</div> + +<div class="slide"> +<h1>並列処理をすることによって発生するバグ</h1> +<table> + <tr> + <td><ul> + <li>Task 間のデータの同期による衝突判定のバグ</li> + <li>Task の実行順序の違いによる衝突判定のバグ</li> + <li>Task の実装の違い</li> + <li>主にオブジェクトの衝突判定でバグが発生</li> + <li>衝突時のログを見ることでバグを発見する</li> + </ul></td> + <td> + <img src="images/test_log.png" width=350 height=300/> + </td> + </tr> +</table> +</div> + +<div class="slide"> +<h1>出力されるテストログ</h1> +<font size="4"><pre> +F64: CREATE [NAME]enemy_greenclab_0 [COORD]x= 120.000000 y= -128.000000 + vx= 0.000000 vy= 4.000000 +F85: DELETE [NAME]enemy_greenclab_0 [COORD]x= 120.000000 y= -44.000000 + vx= 0.000000 vy= 4.000000 + [BULLET]tlv1 = 2, tlv2 = 0 llv1 = 0 +</pre></font> +<dl class="simple"> + <b><dt>F64, F85</dt></b> + <dd>生成、被弾した時の経過フレーム</dd> + <b><dt>CREATE, DELETE</dt></b> + <dd>CREATE はオブジェクトの生成、DELETE はオブジェクトの被弾</dd> + <b><dt>NAME</dt></b> + <dd>オブジェクトの種類と ID</dd> +<dl> +</div> + +<div class="slide"> +<h1>出力されるテストログ</h1> +<font size="4"><pre> +F64: CREATE [NAME]enemy_greenclab_0 [COORD]x= 120.000000 y= -128.000000 + vx= 0.000000 vy= 4.000000 +F85: DELETE [NAME]enemy_greenclab_0 [COORD]x= 120.000000 y= -44.000000 + vx= 0.000000 vy= 4.000000 + [BULLET]tlv1 = 2, tlv2 = 0 llv1 = 0 +</pre></font> +<dl> + <b><dt>COORD</dt></b> + <dd>オブジェクトの xy 座標と速度</dd> + <b><dt>BULLET</dt></b> + <dd>その瞬間に画面内に存在した弾丸の数。</dd> +</dl> +</div> + +<div class="slide"> +<h1>Cerium における画面の描画処理</h1> +<table> + <tr> + <td><ul class="simple"> + <li>ビデオモードの選択(SDL, OpenGL)</li> + <li>描画処理を行う画面バッファの領域の確保</li> + <li>ゲーム処理の実行</li> + <li>レンダリング Task による画面バッファへの描画</li> + </ul></td> + <td> + <img src="images/video.png" width=300 height=300/> + </td> + </tr> +</table> +</div> + +<div class="slide"> +<h1>本研究のテスト環境における描画処理</h1> +<table> + <tr> + <td><ul class="simple"> + <li>プレイヤーの入力の自動化により、プログラムを実行するだけでテストが可能</li> + <li>描画処理が不要となる</li> + <li>描画用 Task の生成を行わない事により、テストの高速化ができる</li> + <li>また、画面バッファの確保も不要</li> + </ul></td> + <td> + <img src="images/video2.png" width=300 height=300/> + </td> + </tr> +</table> +</div> + +<div class="slide"> +<h1>描画処理を行わないモード</h1> +<ul class="simple"> + <li>ビデオモードの選択時に選ぶ</li> + <li>Task を生成する処理をスルーしてゲーム処理を実行</li> +</ul> +<center> + <img src="images/video_none.png" width=200 height=150/> +</center> +</div> + +<div class="slide"> +<h1>本研究のテスト環境におけるバグの検出方法</h1> +<ul class="simple"> + <li>OpenGL バージョンを Capture モードでプレイし、入力を記録</li> + <li>Cerium バージョン、Task Dandy を Trace モードで実行</li> + <li>各バージョンで得られたテストログを比較、考察</li> + <li>テストログの違いにより、バグの発生している箇所を特定</li> +</ul> +</div> + +<div class="slide"> +<h1>OpenGL と Cerium のテストログの比較</h1> +<center> +<table border="1" cellspacing="0"> + <tr><td></td><th>大きさ</th><th>行数</th><th>単語数</th></tr> + <tr><th>OpenGL</th><td>349486 byte</td><td>3411</td><td>37194</td></tr> + <tr><th>Cerium</th><td>349471 byte</td><td>3411</td><td>37195</td></tr> +</table> +</center> +<ul class="simple"> + <li>Cerium バージョンは描画を行わないモードで実行</li> + <li>エンディングまでプレイした入力データを仕様</li> + <li>テストログのデータに unix コマンドの wc(word count) コマンドを実行して検証</li> + <li>各バージョンで得られたテストログを比較、考察</li> +</ul> +</div> + +<div class="slide"> +<h1>OpenGL と Cerium のテストログの比較</h1> +<center> +<table border="1" cellspacing="0"> + <tr><td></td><th>大きさ</th><th>行数</th><th>単語数</th></tr> + <tr><th>OpenGL</th><td>349486 byte</td><td>3411</td><td>37194</td></tr> + <tr><th>Cerium</th><td>349471 byte</td><td>3411</td><td>37195</td></tr> +</table> +</center> +<ul class="simple"> + <li>2 つのログに大きな差は無い</li> + <li>Super Dandy をエンディングまでプレイしたときに得られるテストログの大きさ + は約 350 KB</li> + <li>単語数と大きさに僅かな差</li> +</ul> +</div> + +<div class="slide"> +<h1>diff によるテストログの比較</h1> +<font size="4"><pre> +% diff log/demo_log log/dandy_log +1a2 +> Use Joystick +3410,3411c3411,3412 +< 83.308451 FPS +< move: average:49usec, peak:1091usec +--- +> 0.000000 FPS +> game end +</pre></font> +<ul class="simple"> + <li>表示されているメッセージは OpenGL や Cerium 依存のメッセージ</li> + <li>0.000000 FPS は Cerium 側のメッセージで描画を行わないビデオモードにより + 正しく FPS の計算ができなかったため</li> + <li>wc の単語数はスペース区切りで判別するため、Cerium=6,OpenGL=5</li> + <li>よって両バージョンの動作は同じである</li> +</ul> +</div> + +<div class="slide"> +<h1>OpenGL バージョンと Task Dandy の比較</h1> +<font size="4"><pre> +super dandy(OpenGL) >> +F64: CREATE [NAME]enemy_greenclab_0 [COORD]x= 120.000000 y= -128.000000 ... +F85: DELETE [NAME]enemy_greenclab_0 [COORD]x= 120.000000 y= -44.000000 ... + [BULLET]tlv1 = 2, tlv2 = 0 llv1 = 0 +F96: CREATE [NAME]enemy_greenclab_1 [COORD]x= 56.000000 y= -128.000000 ... +F96: CREATE [NAME]enemy_greenclab_2 [COORD]x= 184.000000 y= -128.000000 ... +F109: DELETE [NAME]enemy_greenclab_1 [COORD]x= 56.000000 y= -24.000000 ... + [BULLET]tlv1 = 2, tlv2 = 0 llv1 = 0 +F117: DELETE [NAME]enemy_greenclab_2 [COORD]x= 184.000000 y= 40.000000 ... + [BULLET]tlv1 = 2, tlv2 = 0 llv1 = 0 + +<< task dandy +F64: CREATE [NAME]enemy_greenclab_0 [COORD]x= 120.000000 y= -128.000000 ... +F85: DELETE [NAME]enemy_greenclab_0 [COORD]x= 120.000000 y= -44.000000 ... + [BULLET]tlv1 = 2, tlv2 = 0 llv1 = 0 +F96: CREATE [NAME]enemy_greenclab_1 [COORD]x= 56.000000 y= -128.000000 ... +F96: CREATE [NAME]enemy_greenclab_2 [COORD]x= 184.000000 y= -128.000000 ... +F109: DELETE [NAME]enemy_greenclab_1 [COORD]x= 56.000000 y= -24.000000 ... + [BULLET]tlv1 = 2, tlv2 = 0 llv1 = 0 +F109: DELETE [NAME]enemy_greenclab_2 [COORD]x= 184.000000 y= -24.000000 ... + [BULLET]tlv1 = 2, tlv2 = 0 llv1 = 0 +</pre></font> +</div> + +<div class="slide"> +<h1>ログからのバグの洗い出し</h1> +<font size="4"><pre> +super dandy(OpenGL) >> +F109: DELETE [NAME]enemy_greenclab_1 [COORD]x= 56.000000 y= -24.000000 ... + [BULLET]tlv1 = 2, tlv2 = 0 llv1 = 0 +F117: DELETE [NAME]enemy_greenclab_2 [COORD]x= 184.000000 y= 40.000000 ... + [BULLET]tlv1 = 2, tlv2 = 0 llv1 = 0 + +<< task dandy +F109: DELETE [NAME]enemy_greenclab_1 [COORD]x= 56.000000 y= -24.000000 ... + [BULLET]tlv1 = 2, tlv2 = 0 llv1 = 0 +F109: DELETE [NAME]enemy_greenclab_2 [COORD]x= 184.000000 y= -24.000000 ... + [BULLET]tlv1 = 2, tlv2 = 0 llv1 = 0 +</pre></font> +<ul class="simple"> + <li>OpenGL では別フレームで死んだ 2 つの敵オブジェクトが Task Dandy では + 同フレームで死亡</li> + <li>この時の弾丸の数が一致</li> + <li>片方が死んだ後、弾丸のオブジェクトの除去がされてない</li> + <li>弾丸データが取れていない、という仮説を立てた</li> +</ul> +</div> + +<div class="slide"> +<h1>Collision Task 間でのデータの同期</h1> +<table> + <tr> + <td><ul class="simple"> + <li>Collision Task を同じ CPU に送る</li> + <li>予め衝突判定に必要なパラメータの領域を確保する</li> + <li>その領域のパラメータで衝突判定を行う</li> + <li>SPE 内で変更されたパラメータをメインメモリ側に反映させる</li> + </ul></td> + <td> + <img src="images/collision_reflect.png" width=300 height=300/> + </td> + </tr> +</table> +</div> + +<div class="slide"> +<h1>Collision Task の改良後の比較</h1> +<font size="4"><pre> +super dandy>> +F64: CREATE [NAME]enemy_greenclab_0 [COORD]x= 120.000000 y= -128.000000 ... +F85: DELETE [NAME]enemy_greenclab_0 [COORD]x= 120.000000 y= -44.000000 ... + [BULLET]tlv1 = 2, tlv2 = 0 llv1 = 0 +F96: CREATE [NAME]enemy_greenclab_1 [COORD]x= 56.000000 y= -128.000000 ... +F96: CREATE [NAME]enemy_greenclab_2 [COORD]x= 184.000000 y= -128.000000 ... +F109: DELETE [NAME]enemy_greenclab_1 [COORD]x= 56.000000 y= -24.000000 ... + [BULLET]tlv1 = 2, tlv2 = 0 llv1 = 0 +F117: DELETE [NAME]enemy_greenclab_2 [COORD]x= 184.000000 y= 40.000000 ... + [BULLET]tlv1 = 2, tlv2 = 0 llv1 = 0 + +<< task dandy +F64: CREATE [NAME]enemy_greenclab_0 [COORD]x= 120.000000 y= -128.000000 ... +F85: DELETE [NAME]enemy_greenclab_0 [COORD]x= 120.000000 y= -44.000000 ... + [BULLET]tlv1 = 2, tlv2 = 0 llv1 = 0 +F96: CREATE [NAME]enemy_greenclab_1 [COORD]x= 56.000000 y= -128.000000 ... +F96: CREATE [NAME]enemy_greenclab_2 [COORD]x= 184.000000 y= -128.000000 ... +F109: DELETE [NAME]enemy_greenclab_1 [COORD]x= 56.000000 y= -24.000000 ... + [BULLET]tlv1 = 2, tlv2 = 0 llv1 = 0 +F117: DELETE [NAME]enemy_greenclab_2 [COORD]x= 184.000000 y= 40.000000 ... + [BULLET]tlv1 = 2, tlv2 = 0 llv1 = 0 +</pre></font> +</div> + +<div class="slide"> +<h1>Collision Task の改良後の比較</h1> +<font size="4"><pre> +super dandy(OpenGL) >> +F109: DELETE [NAME]enemy_greenclab_1 [COORD]x= 56.000000 y= -24.000000 ... + [BULLET]tlv1 = 2, tlv2 = 0 llv1 = 0 +F117: DELETE [NAME]enemy_greenclab_2 [COORD]x= 184.000000 y= 40.000000 ... + [BULLET]tlv1 = 2, tlv2 = 0 llv1 = 0 + +<< task dandy +F109: DELETE [NAME]enemy_greenclab_1 [COORD]x= 56.000000 y= -24.000000 ... + [BULLET]tlv1 = 2, tlv2 = 0 llv1 = 0 +F117: DELETE [NAME]enemy_greenclab_2 [COORD]x= 184.000000 y= 40.000000 ... + [BULLET]tlv1 = 2, tlv2 = 0 llv1 = 0 +</pre></font> +<ul class="simple"> + <li>2 つのバージョンのログがフレーム単位で同じ</li> + <li>Collision Task のデータ同期が有効に働いている</li> +</ul> +</div> + +<div class="slide"> +<h1>Task への乱数受け渡しの検証</h1> +<ul class="simple"> + <li>多数の隕石オブジェクトが生成されるステージで全ての隕石オブジェクトが + 生成されるのを観察</li> + <li>隕石オブジェクトの初期配置は乱数によるランダム配置</li> + <li>隕石オブジェクト生成後の座標と速度を出力</li> +</ul> +</div> + +<div class="slide"> +<h1>隕石オブジェクトの実装</h1> +<font size="4"><pre> + int sf; + + sf = random() % 4; + if((sf == 0) || (sf == 1)) + { + p->x = -35; + p->y = random() % (120 - 35); + p->vx = (random() % 4 + 1); + p->vy = random() % 3 + 1; + p->state = chara_state23; + } + if((sf == 2)) + { + p->x = random() % 290; + p->y = -30; + p->vx = random() % 3 - 1; + p->vy = (random() % 4 + 1); + p->state = chara_state23; + } + if(sf == 3) + { + ..... +</pre></font> +</div> + +<div class="slide"> +<h1>Task Dandy 側の実装</h1> +<font size="4"><pre> + int rand1 = (int)smanager->get_param(0); + int rand2 = (int)smanager->get_param(1); + int rand3 = (int)smanager->get_param(2); + int rand4 = (int)smanager->get_param(3); + + CHARACTER *p = (CHARACTER*)smanager->get_input(rbuf, 0); + + int sf = rand1 % 4; + if((sf == 0) || (sf == 1)) + { + p->x = -35; + p->y = rand2 % (120 - 35); + p->vx = (rand3 % 4 + 1); + p->vy = rand4 % 3 + 1; + } + if((sf == 2)) + { + p->x = rand2 % 290; + p->y = -30; + p->vx = rand3 % 3 - 1; + p->vy = (rand4 % 4 + 1); + ..... +</pre></font> +</div> + +<div class="slide"> +<h1>実行結果</h1> +<font size="4"><pre> +demolog >> +[COORD]x= 320.000000 y= 66.000000 vx= -2.000000 vy= 0.000000 +[COORD]x= -35.000000 y= 20.000000 vx= 3.000000 vy= 1.000000 +[COORD]x= -35.000000 y= 36.000000 vx= 3.000000 vy= 2.000000 +[COORD]x= 89.000000 y= -30.000000 vx= 1.000000 vy= 3.000000 +[COORD]x= -35.000000 y= 81.000000 vx= 1.000000 vy= 2.000000 +[COORD]x= 320.000000 y= 8.000000 vx= -4.000000 vy= -1.000000 +[COORD]x= 220.000000 y= -30.000000 vx= 1.000000 vy= 4.000000 +.... + +<< tdandylog +[COORD]x= 320.000000 y= 66.000000 vx= -2.000000 vy= 0.000000 +[COORD]x= -35.000000 y= 20.000000 vx= 3.000000 vy= 1.000000 +[COORD]x= -35.000000 y= 36.000000 vx= 3.000000 vy= 2.000000 +[COORD]x= 89.000000 y= -30.000000 vx= 1.000000 vy= 3.000000 +[COORD]x= -35.000000 y= 81.000000 vx= 1.000000 vy= 2.000000 +[COORD]x= 320.000000 y= 8.000000 vx= -4.000000 vy= -1.000000 +[COORD]x= 220.000000 y= -30.000000 vx= 1.000000 vy= 4.000000 +.... + +% diff demolog tdandylog +% +</pre></font> +</div> + +<div class="slide"> +<h1>乱数受け渡しによる実行結果の検証</h1> +<ul class="simple"> + <li>生成された隕石オブジェクトのパラメータが両バージョンで一致している</li> + <li>Task への乱数受け渡しによるバグの再現性の低下防止は有効である</li> +</ul> +</div> + +<div class="slide"> +<h1>ビデオモードによる実行時間の比較</h1> +<ul class="simple"> + <li>実行時間の計測には unix の time コマンドを使用</li> + <li>3 バージョンの描画無しモードを使用(OpenGL は 1x1)</li> + <li>描画ありバージョンは 1200x800 で統一して計測</li> +</ul> +</div> + +<div class="slide"> +<h1>実行結果</h1> +<table border="1" cellspacing="0"> + <tr><td></td><th>OpenGL(w=1,h=1)</th><th>Cerium(no video)</th><th>Task(no video)</th><th>OpenGL</th><th>Cerium</th><th>Task</th></tr> + <tr><th>実行時間</th><td>335.06 sec</td><td>334.21 sec</td><td>385.17 sec</td><td>336.09 sec</td><td>5066.11 sec</td><td>6643.16 sec</td></tr> +</table> +<ul class="simple"> + <li>OpenGL バージョンと Cerium バージョンではほとんど差がない</li> + <li>描画処理を除けば 2 つのバージョンには殆ど差がない為と考えられる</li> + <li>TaskDandy では Cerium における Task の処理が発生したため、実行時間が大きく増加したと考えられる</li> +</ul> +</div> + +<div class="slide"> +<h1>実行結果</h1> +<table border="1" cellspacing="0"> + <tr><td></td><th>OpenGL(w=1,h=1)</th><th>Cerium(no video)</th><th>Task(no video)</th><th>OpenGL</th><th>Cerium</th><th>Task</th></tr> + <tr><th>実行時間</th><td>335.06 sec</td><td>334.21 sec</td><td>385.17 sec</td><td>336.09 sec</td><td>5066.11 sec</td><td>6643.16 sec</td></tr> +</table> +<ul class="simple"> + <li>OpenGL では描画無しバージョンとの差がほとんど無い</li> + <li>Cerium バージョンや Task バージョンは劇的に処理時間が増加</li> + <li>描画処理の Task の処理時間が非常に大きいと考えられる</li> + <li>描画処理の Task に比べればゲームの Task は処理が小さい</li> +</ul> +</div> + +<div class="slide"> +<h1>結論</h1> +<h2>本研究では並列環境におけるゲームプログラムのテスト手法を提案した</h2> +<ul class="simple"> + <li>衝突判定時のテストログ出力によるデバッグは OpenGL バージョンと Task + Dandy の実行結果が同じであることから、効果的であった</li> + <li>Task への乱数受け渡しによるバグの再現性は 同様にして有効であることが + わかった</li> + <li>描画をしないビデオモードによるテスト時間の高速化は、描画をする場合に + 比べて 非常に効果があった</li> +</ul> +</div> + +<div class="slide"> +<h1>今後の課題</h1> +<ul class="simple"> + <li>描画処理におけるバグの修正</li> + <li>Cerium におけるメモリアロケータの実装</li> +</ul> +</div> + +</div> +</body> +</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/poster/ui/CVS/Entries Tue Feb 15 18:21:02 2011 +0900 @@ -0,0 +1,1 @@ +D/default////
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/poster/ui/CVS/Repository Tue Feb 15 18:21:02 2011 +0900 @@ -0,0 +1,1 @@ +member/koba/document/presentation/ui
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/poster/ui/CVS/Root Tue Feb 15 18:21:02 2011 +0900 @@ -0,0 +1,1 @@ +koba@firefly.cr.ie.u-ryukyu.ac.jp:/home/one/CVS_DB
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/poster/ui/default/CVS/Entries Tue Feb 15 18:21:02 2011 +0900 @@ -0,0 +1,12 @@ +/blank.gif/1.1/Fri Nov 21 07:36:57 2008// +/bodybg.gif/1.1/Fri Nov 21 07:36:57 2008// +/framing.css/1.1/Fri Nov 21 07:36:57 2008// +/iepngfix.htc/1.1/Fri Nov 21 07:36:57 2008// +/opera.css/1.1/Fri Nov 21 07:36:57 2008// +/outline.css/1.1/Fri Nov 21 07:36:57 2008// +/pretty.css/1.1/Fri Nov 21 07:36:57 2008// +/print.css/1.1/Fri Nov 21 07:36:57 2008// +/s5-core.css/1.1/Fri Nov 21 07:36:57 2008// +/slides.css/1.1/Fri Nov 21 07:36:57 2008// +/slides.js/1.1/Fri Nov 21 07:36:57 2008// +D
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/poster/ui/default/CVS/Repository Tue Feb 15 18:21:02 2011 +0900 @@ -0,0 +1,1 @@ +member/koba/document/presentation/ui/default
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/poster/ui/default/CVS/Root Tue Feb 15 18:21:02 2011 +0900 @@ -0,0 +1,1 @@ +koba@firefly.cr.ie.u-ryukyu.ac.jp:/home/one/CVS_DB
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/poster/ui/default/framing.css Tue Feb 15 18:21:02 2011 +0900 @@ -0,0 +1,23 @@ +/* The following styles size, place, and layer the slide components. + Edit these if you want to change the overall slide layout. + The commented lines can be uncommented (and modified, if necessary) + to help you with the rearrangement process. */ + +/* target = 1024x768 */ + +div#header, div#footer, .slide {width: 100%; top: 0; left: 0;} +div#header {top: 0; height: 3em; z-index: 1;} +div#footer {top: auto; bottom: 0; height: 2.5em; z-index: 5;} +.slide {top: 0; width: 92%; padding: 3.5em 4% 4%; z-index: 2; list-style: none;} +div#controls {left: 50%; bottom: 0; width: 50%; z-index: 100;} +div#controls form {position: absolute; bottom: 0; right: 0; width: 100%; + margin: 0;} +#currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1em; z-index: 10;} +html>body #currentSlide {position: fixed;} + +/* +div#header {background: #FCC;} +div#footer {background: #CCF;} +div#controls {background: #BBD;} +div#currentSlide {background: #FFC;} +*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/poster/ui/default/iepngfix.htc Tue Feb 15 18:21:02 2011 +0900 @@ -0,0 +1,42 @@ +<public:component> +<public:attach event="onpropertychange" onevent="doFix()" /> + +<script> + +// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com +// Free usage permitted as long as this notice remains intact. + +// This must be a path to a blank image. That's all the configuration you need here. +var blankImg = 'ui/default/blank.gif'; + +var f = 'DXImageTransform.Microsoft.AlphaImageLoader'; + +function filt(s, m) { + if (filters[f]) { + filters[f].enabled = s ? true : false; + if (s) with (filters[f]) { src = s; sizingMethod = m } + } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")'; +} + +function doFix() { + if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) || + (event && !/(background|src)/.test(event.propertyName))) return; + + if (tagName == 'IMG') { + if ((/\.png$/i).test(src)) { + filt(src, 'image'); // was 'scale' + src = blankImg; + } else if (src.indexOf(blankImg) < 0) filt(); + } else if (style.backgroundImage) { + if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) { + var s = RegExp.$1; + style.backgroundImage = ''; + filt(s, 'crop'); + } else filt(); + } +} + +doFix(); + +</script> +</public:component> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/poster/ui/default/opera.css Tue Feb 15 18:21:02 2011 +0900 @@ -0,0 +1,7 @@ +/* DO NOT CHANGE THESE unless you really want to break Opera Show */ +.slide { + visibility: visible !important; + position: static !important; + page-break-before: always; +} +#slide0 {page-break-before: avoid;}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/poster/ui/default/outline.css Tue Feb 15 18:21:02 2011 +0900 @@ -0,0 +1,15 @@ +/* don't change this unless you want the layout stuff to show up in the outline view! */ + +.layout div, #footer *, #controlForm * {display: none;} +#footer, #controls, #controlForm, #navLinks, #toggle { + display: block; visibility: visible; margin: 0; padding: 0;} +#toggle {float: right; padding: 0.5em;} +html>body #toggle {position: fixed; top: 0; right: 0;} + +/* making the outline look pretty-ish */ + +#slide0 h1, #slide0 h2, #slide0 h3, #slide0 h4 {border: none; margin: 0;} +#slide0 h1 {padding-top: 1.5em;} +.slide h1 {margin: 1.5em 0 0; padding-top: 0.25em; + border-top: 1px solid #888; border-bottom: 1px solid #AAA;} +#toggle {border: 1px solid; border-width: 0 0 1px 1px; background: #FFF;}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/poster/ui/default/pretty.css Tue Feb 15 18:21:02 2011 +0900 @@ -0,0 +1,86 @@ +/* Following are the presentation styles -- edit away! */ + +body {background: #FFF url(bodybg.gif) -16px 0 no-repeat; color: #000; font-size: 2em;} +:link, :visited {text-decoration: none; color: #00C;} +#controls :active {color: #88A !important;} +#controls :focus {outline: 1px dotted #227;} +h1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;} +ul, pre {margin: 0; line-height: 1em;} +html, body {margin: 0; padding: 0;} + +blockquote, q {font-style: italic;} +blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em; text-align: center; font-size: 1em;} +blockquote p {margin: 0;} +blockquote i {font-style: normal;} +blockquote b {display: block; margin-top: 0.5em; font-weight: normal; font-size: smaller; font-style: normal;} +blockquote b i {font-style: italic;} + +kbd {font-weight: bold; font-size: 1em;} +sup {font-size: smaller; line-height: 1px;} + +.slide code {padding: 2px 0.25em; font-weight: bold; color: #533;} +.slide code.bad, code del {color: red;} +.slide code.old {color: silver;} +.slide pre {padding: 0; margin: 0.25em 0 0.5em 0.5em; color: #533; font-size: 90%;} +.slide pre code {display: block;} +.slide ul {margin-left: 5%; margin-right: 7%; list-style: disc;} +.slide li {margin-top: 0.75em; margin-right: 0;} +.slide ul ul {line-height: 1;} +.slide ul ul li {margin: .2em; font-size: 85%; list-style: square;} +.slide img.leader {display: block; margin: 0 auto;} + +div#header, div#footer {background: #005; color: #AAB; + font-family: Verdana, Helvetica, sans-serif;} +div#header {background: #005 url(bodybg.gif) -16px 0 no-repeat; + line-height: 1px;} +div#footer {font-size: 0.5em; font-weight: bold; padding: 1em 0;} +#footer h1, #footer h2 {display: block; padding: 0 1em;} +#footer h2 {font-style: italic;} + +div.long {font-size: 0.75em;} +.slide h1 {position: absolute; top: 0.7em; left: 87px; z-index: 1; + margin: 0; padding: 0.3em 0 0 50px; white-space: nowrap; + font: bold 150%/1em Helvetica, sans-serif; text-transform: capitalize; + color: #DDE; background: #005;} +.slide h3 {font-size: 130%;} +h1 abbr {font-variant: small-caps;} + +div#controls {position: absolute; left: 50%; bottom: 0; + width: 50%; + text-align: right; font: bold 0.9em Verdana, Helvetica, sans-serif;} +html>body div#controls {position: fixed; padding: 0 0 1em 0; + top: auto;} +div#controls form {position: absolute; bottom: 0; right: 0; width: 100%; + margin: 0; padding: 0;} +#controls #navLinks a {padding: 0; margin: 0 0.5em; + background: #005; border: none; color: #779; + cursor: pointer;} +#controls #navList {height: 1em;} +#controls #navList #jumplist {position: absolute; bottom: 0; right: 0; background: #DDD; color: #227;} + +#currentSlide {text-align: center; font-size: 0.5em; color: #449;} + +#slide0 {padding-top: 3.5em; font-size: 90%;} +#slide0 h1 {position: static; margin: 1em 0 0; padding: 0; + font: bold 2em Helvetica, sans-serif; white-space: normal; + color: #000; background: transparent;} +#slide0 h2 {font: bold italic 1em Helvetica, sans-serif; margin: 0.25em;} +#slide0 h3 {margin-top: 1.5em; font-size: 1.5em;} +#slide0 h4 {margin-top: 0; font-size: 1em;} + +ul.urls {list-style: none; display: inline; margin: 0;} +.urls li {display: inline; margin: 0;} +.note {display: none;} +.external {border-bottom: 1px dotted gray;} +html>body .external {border-bottom: none;} +.external:after {content: " \274F"; font-size: smaller; color: #77B;} + +.incremental, .incremental *, .incremental *:after {color: #DDE; visibility: visible;} +img.incremental {visibility: hidden;} +.slide .current {color: #B02;} + + +/* diagnostics + +li:after {content: " [" attr(class) "]"; color: #F88;} + */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/poster/ui/default/print.css Tue Feb 15 18:21:02 2011 +0900 @@ -0,0 +1,1 @@ +/* The following rule is necessary to have all slides appear in print! DO NOT REMOVE IT! */ .slide, ul {page-break-inside: avoid; visibility: visible !important;} h1 {page-break-after: avoid;} body {font-size: 12pt; background: white;} * {color: black;} #slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;} #slide0 h3 {margin: 0; padding: 0;} #slide0 h4 {margin: 0 0 0.5em; padding: 0;} #slide0 {margin-bottom: 3em;} h1 {border-top: 2pt solid gray; border-bottom: 1px dotted silver;} .extra {background: transparent !important;} div.extra, pre.extra, .example {font-size: 10pt; color: #333;} ul.extra a {font-weight: bold;} p.example {display: none;} #header {display: none;} #footer h1 {margin: 0; border-bottom: 1px solid; color: gray; font-style: italic;} #footer h2, #controls {display: none;} /* The following rule keeps the layout stuff out of print. Remove at your own risk! */ .layout, .layout * {display: none !important;} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/poster/ui/default/s5-core.css Tue Feb 15 18:21:02 2011 +0900 @@ -0,0 +1,9 @@ +/* Do not edit or override these styles! The system will likely break if you do. */ + +div#header, div#footer, div#controls, .slide {position: absolute;} +html>body div#header, html>body div#footer, + html>body div#controls, html>body .slide {position: fixed;} +.handout {display: none;} +.layout {display: block;} +.slide, .hideme, .incremental {visibility: hidden;} +#slide0 {visibility: visible;}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/poster/ui/default/slides.css Tue Feb 15 18:21:02 2011 +0900 @@ -0,0 +1,3 @@ +@import url(s5-core.css); /* required to make the slide show run at all */ +@import url(framing.css); /* sets basic placement and size of slide components */ +@import url(pretty.css); /* stuff that makes the slides look better than blah */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/poster/ui/default/slides.js Tue Feb 15 18:21:02 2011 +0900 @@ -0,0 +1,553 @@ +// S5 v1.1 slides.js -- released into the Public Domain +// +// Please see http://www.meyerweb.com/eric/tools/s5/credits.html for information +// about all the wonderful and talented contributors to this code! + +var undef; +var slideCSS = ''; +var snum = 0; +var smax = 1; +var incpos = 0; +var number = undef; +var s5mode = true; +var defaultView = 'slideshow'; +var controlVis = 'visible'; + +var isIE = navigator.appName == 'Microsoft Internet Explorer' && navigator.userAgent.indexOf('Opera') < 1 ? 1 : 0; +var isOp = navigator.userAgent.indexOf('Opera') > -1 ? 1 : 0; +var isGe = navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('Safari') < 1 ? 1 : 0; + +function hasClass(object, className) { + if (!object.className) return false; + return (object.className.search('(^|\\s)' + className + '(\\s|$)') != -1); +} + +function hasValue(object, value) { + if (!object) return false; + return (object.search('(^|\\s)' + value + '(\\s|$)') != -1); +} + +function removeClass(object,className) { + if (!object) return; + object.className = object.className.replace(new RegExp('(^|\\s)'+className+'(\\s|$)'), RegExp.$1+RegExp.$2); +} + +function addClass(object,className) { + if (!object || hasClass(object, className)) return; + if (object.className) { + object.className += ' '+className; + } else { + object.className = className; + } +} + +function GetElementsWithClassName(elementName,className) { + var allElements = document.getElementsByTagName(elementName); + var elemColl = new Array(); + for (var i = 0; i< allElements.length; i++) { + if (hasClass(allElements[i], className)) { + elemColl[elemColl.length] = allElements[i]; + } + } + return elemColl; +} + +function isParentOrSelf(element, id) { + if (element == null || element.nodeName=='BODY') return false; + else if (element.id == id) return true; + else return isParentOrSelf(element.parentNode, id); +} + +function nodeValue(node) { + var result = ""; + if (node.nodeType == 1) { + var children = node.childNodes; + for (var i = 0; i < children.length; ++i) { + result += nodeValue(children[i]); + } + } + else if (node.nodeType == 3) { + result = node.nodeValue; + } + return(result); +} + +function slideLabel() { + var slideColl = GetElementsWithClassName('*','slide'); + var list = document.getElementById('jumplist'); + smax = slideColl.length; + for (var n = 0; n < smax; n++) { + var obj = slideColl[n]; + + var did = 'slide' + n.toString(); + obj.setAttribute('id',did); + if (isOp) continue; + + var otext = ''; + var menu = obj.firstChild; + if (!menu) continue; // to cope with empty slides + while (menu && menu.nodeType == 3) { + menu = menu.nextSibling; + } + if (!menu) continue; // to cope with slides with only text nodes + + var menunodes = menu.childNodes; + for (var o = 0; o < menunodes.length; o++) { + otext += nodeValue(menunodes[o]); + } + list.options[list.length] = new Option(n + ' : ' + otext, n); + } +} + +function currentSlide() { + var cs; + if (document.getElementById) { + cs = document.getElementById('currentSlide'); + } else { + cs = document.currentSlide; + } + cs.innerHTML = '<span id="csHere">' + snum + '<\/span> ' + + '<span id="csSep">\/<\/span> ' + + '<span id="csTotal">' + (smax-1) + '<\/span>'; + if (snum == 0) { + cs.style.visibility = 'hidden'; + } else { + cs.style.visibility = 'visible'; + } +} + +function go(step) { + if (document.getElementById('slideProj').disabled || step == 0) return; + var jl = document.getElementById('jumplist'); + var cid = 'slide' + snum; + var ce = document.getElementById(cid); + if (incrementals[snum].length > 0) { + for (var i = 0; i < incrementals[snum].length; i++) { + removeClass(incrementals[snum][i], 'current'); + removeClass(incrementals[snum][i], 'incremental'); + } + } + if (step != 'j') { + snum += step; + lmax = smax - 1; + if (snum > lmax) snum = lmax; + if (snum < 0) snum = 0; + } else + snum = parseInt(jl.value); + var nid = 'slide' + snum; + var ne = document.getElementById(nid); + if (!ne) { + ne = document.getElementById('slide0'); + snum = 0; + } + if (step < 0) {incpos = incrementals[snum].length} else {incpos = 0;} + if (incrementals[snum].length > 0 && incpos == 0) { + for (var i = 0; i < incrementals[snum].length; i++) { + if (hasClass(incrementals[snum][i], 'current')) + incpos = i + 1; + else + addClass(incrementals[snum][i], 'incremental'); + } + } + if (incrementals[snum].length > 0 && incpos > 0) + addClass(incrementals[snum][incpos - 1], 'current'); + ce.style.visibility = 'hidden'; + ne.style.visibility = 'visible'; + jl.selectedIndex = snum; + currentSlide(); + number = 0; +} + +function goTo(target) { + if (target >= smax || target == snum) return; + go(target - snum); +} + +function subgo(step) { + if (step > 0) { + removeClass(incrementals[snum][incpos - 1],'current'); + removeClass(incrementals[snum][incpos], 'incremental'); + addClass(incrementals[snum][incpos],'current'); + incpos++; + } else { + incpos--; + removeClass(incrementals[snum][incpos],'current'); + addClass(incrementals[snum][incpos], 'incremental'); + addClass(incrementals[snum][incpos - 1],'current'); + } +} + +function toggle() { + var slideColl = GetElementsWithClassName('*','slide'); + var slides = document.getElementById('slideProj'); + var outline = document.getElementById('outlineStyle'); + if (!slides.disabled) { + slides.disabled = true; + outline.disabled = false; + s5mode = false; + fontSize('1em'); + for (var n = 0; n < smax; n++) { + var slide = slideColl[n]; + slide.style.visibility = 'visible'; + } + } else { + slides.disabled = false; + outline.disabled = true; + s5mode = true; + fontScale(); + for (var n = 0; n < smax; n++) { + var slide = slideColl[n]; + slide.style.visibility = 'hidden'; + } + slideColl[snum].style.visibility = 'visible'; + } +} + +function showHide(action) { + var obj = GetElementsWithClassName('*','hideme')[0]; + switch (action) { + case 's': obj.style.visibility = 'visible'; break; + case 'h': obj.style.visibility = 'hidden'; break; + case 'k': + if (obj.style.visibility != 'visible') { + obj.style.visibility = 'visible'; + } else { + obj.style.visibility = 'hidden'; + } + break; + } +} + +// 'keys' code adapted from MozPoint (http://mozpoint.mozdev.org/) +function keys(key) { + if (!key) { + key = event; + key.which = key.keyCode; + } + if (key.which == 84) { + toggle(); + return; + } + if (s5mode) { + switch (key.which) { + case 10: // return + case 13: // enter + if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return; + if (key.target && isParentOrSelf(key.target, 'controls')) return; + if(number != undef) { + goTo(number); + break; + } + case 32: // spacebar + case 34: // page down + case 39: // rightkey + case 40: // downkey + if(number != undef) { + go(number); + } else if (!incrementals[snum] || incpos >= incrementals[snum].length) { + go(1); + } else { + subgo(1); + } + break; + case 33: // page up + case 37: // leftkey + case 38: // upkey + if(number != undef) { + go(-1 * number); + } else if (!incrementals[snum] || incpos <= 0) { + go(-1); + } else { + subgo(-1); + } + break; + case 36: // home + goTo(0); + break; + case 35: // end + goTo(smax-1); + break; + case 67: // c + showHide('k'); + break; + } + if (key.which < 48 || key.which > 57) { + number = undef; + } else { + if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return; + if (key.target && isParentOrSelf(key.target, 'controls')) return; + number = (((number != undef) ? number : 0) * 10) + (key.which - 48); + } + } + return false; +} + +function clicker(e) { + number = undef; + var target; + if (window.event) { + target = window.event.srcElement; + e = window.event; + } else target = e.target; + if (target.getAttribute('href') != null || hasValue(target.rel, 'external') || isParentOrSelf(target, 'controls') || isParentOrSelf(target,'embed') || isParentOrSelf(target,'object')) return true; + if (!e.which || e.which == 1) { + if (!incrementals[snum] || incpos >= incrementals[snum].length) { + go(1); + } else { + subgo(1); + } + } +} + +function findSlide(hash) { + var target = null; + var slides = GetElementsWithClassName('*','slide'); + for (var i = 0; i < slides.length; i++) { + var targetSlide = slides[i]; + if ( (targetSlide.name && targetSlide.name == hash) + || (targetSlide.id && targetSlide.id == hash) ) { + target = targetSlide; + break; + } + } + while(target != null && target.nodeName != 'BODY') { + if (hasClass(target, 'slide')) { + return parseInt(target.id.slice(5)); + } + target = target.parentNode; + } + return null; +} + +function slideJump() { + if (window.location.hash == null) return; + var sregex = /^#slide(\d+)$/; + var matches = sregex.exec(window.location.hash); + var dest = null; + if (matches != null) { + dest = parseInt(matches[1]); + } else { + dest = findSlide(window.location.hash.slice(1)); + } + if (dest != null) + go(dest - snum); +} + +function fixLinks() { + var thisUri = window.location.href; + thisUri = thisUri.slice(0, thisUri.length - window.location.hash.length); + var aelements = document.getElementsByTagName('A'); + for (var i = 0; i < aelements.length; i++) { + var a = aelements[i].href; + var slideID = a.match('\#slide[0-9]{1,2}'); + if ((slideID) && (slideID[0].slice(0,1) == '#')) { + var dest = findSlide(slideID[0].slice(1)); + if (dest != null) { + if (aelements[i].addEventListener) { + aelements[i].addEventListener("click", new Function("e", + "if (document.getElementById('slideProj').disabled) return;" + + "go("+dest+" - snum); " + + "if (e.preventDefault) e.preventDefault();"), true); + } else if (aelements[i].attachEvent) { + aelements[i].attachEvent("onclick", new Function("", + "if (document.getElementById('slideProj').disabled) return;" + + "go("+dest+" - snum); " + + "event.returnValue = false;")); + } + } + } + } +} + +function externalLinks() { + if (!document.getElementsByTagName) return; + var anchors = document.getElementsByTagName('a'); + for (var i=0; i<anchors.length; i++) { + var anchor = anchors[i]; + if (anchor.getAttribute('href') && hasValue(anchor.rel, 'external')) { + anchor.target = '_blank'; + addClass(anchor,'external'); + } + } +} + +function createControls() { + var controlsDiv = document.getElementById("controls"); + if (!controlsDiv) return; + var hider = ' onmouseover="showHide(\'s\');" onmouseout="showHide(\'h\');"'; + var hideDiv, hideList = ''; + if (controlVis == 'hidden') { + hideDiv = hider; + } else { + hideList = hider; + } + controlsDiv.innerHTML = '<form action="#" id="controlForm"' + hideDiv + '>' + + '<div id="navLinks">' + + '<a accesskey="t" id="toggle" href="javascript:toggle();">Ø<\/a>' + + '<a accesskey="z" id="prev" href="javascript:go(-1);">«<\/a>' + + '<a accesskey="x" id="next" href="javascript:go(1);">»<\/a>' + + '<div id="navList"' + hideList + '><select id="jumplist" onchange="go(\'j\');"><\/select><\/div>' + + '<\/div><\/form>'; + if (controlVis == 'hidden') { + var hidden = document.getElementById('navLinks'); + } else { + var hidden = document.getElementById('jumplist'); + } + addClass(hidden,'hideme'); +} + +function fontScale() { // causes layout problems in FireFox that get fixed if browser's Reload is used; same may be true of other Gecko-based browsers + if (!s5mode) return false; + var vScale = 22; // both yield 32 (after rounding) at 1024x768 + var hScale = 32; // perhaps should auto-calculate based on theme's declared value? + if (window.innerHeight) { + var vSize = window.innerHeight; + var hSize = window.innerWidth; + } else if (document.documentElement.clientHeight) { + var vSize = document.documentElement.clientHeight; + var hSize = document.documentElement.clientWidth; + } else if (document.body.clientHeight) { + var vSize = document.body.clientHeight; + var hSize = document.body.clientWidth; + } else { + var vSize = 700; // assuming 1024x768, minus chrome and such + var hSize = 1024; // these do not account for kiosk mode or Opera Show + } + var newSize = Math.min(Math.round(vSize/vScale),Math.round(hSize/hScale)); + fontSize(newSize + 'px'); + if (isGe) { // hack to counter incremental reflow bugs + var obj = document.getElementsByTagName('body')[0]; + obj.style.display = 'none'; + obj.style.display = 'block'; + } +} + +function fontSize(value) { + if (!(s5ss = document.getElementById('s5ss'))) { + if (!isIE) { + document.getElementsByTagName('head')[0].appendChild(s5ss = document.createElement('style')); + s5ss.setAttribute('media','screen, projection'); + s5ss.setAttribute('id','s5ss'); + } else { + document.createStyleSheet(); + document.s5ss = document.styleSheets[document.styleSheets.length - 1]; + } + } + if (!isIE) { + while (s5ss.lastChild) s5ss.removeChild(s5ss.lastChild); + s5ss.appendChild(document.createTextNode('body {font-size: ' + value + ' !important;}')); + } else { + document.s5ss.addRule('body','font-size: ' + value + ' !important;'); + } +} + +function notOperaFix() { + slideCSS = document.getElementById('slideProj').href; + var slides = document.getElementById('slideProj'); + var outline = document.getElementById('outlineStyle'); + slides.setAttribute('media','screen'); + outline.disabled = true; + if (isGe) { + slides.setAttribute('href','null'); // Gecko fix + slides.setAttribute('href',slideCSS); // Gecko fix + } + if (isIE && document.styleSheets && document.styleSheets[0]) { + document.styleSheets[0].addRule('img', 'behavior: url(ui/default/iepngfix.htc)'); + document.styleSheets[0].addRule('div', 'behavior: url(ui/default/iepngfix.htc)'); + document.styleSheets[0].addRule('.slide', 'behavior: url(ui/default/iepngfix.htc)'); + } +} + +function getIncrementals(obj) { + var incrementals = new Array(); + if (!obj) + return incrementals; + var children = obj.childNodes; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (hasClass(child, 'incremental')) { + if (child.nodeName == 'OL' || child.nodeName == 'UL') { + removeClass(child, 'incremental'); + for (var j = 0; j < child.childNodes.length; j++) { + if (child.childNodes[j].nodeType == 1) { + addClass(child.childNodes[j], 'incremental'); + } + } + } else { + incrementals[incrementals.length] = child; + removeClass(child,'incremental'); + } + } + if (hasClass(child, 'show-first')) { + if (child.nodeName == 'OL' || child.nodeName == 'UL') { + removeClass(child, 'show-first'); + if (child.childNodes[isGe].nodeType == 1) { + removeClass(child.childNodes[isGe], 'incremental'); + } + } else { + incrementals[incrementals.length] = child; + } + } + incrementals = incrementals.concat(getIncrementals(child)); + } + return incrementals; +} + +function createIncrementals() { + var incrementals = new Array(); + for (var i = 0; i < smax; i++) { + incrementals[i] = getIncrementals(document.getElementById('slide'+i)); + } + return incrementals; +} + +function defaultCheck() { + var allMetas = document.getElementsByTagName('meta'); + for (var i = 0; i< allMetas.length; i++) { + if (allMetas[i].name == 'defaultView') { + defaultView = allMetas[i].content; + } + if (allMetas[i].name == 'controlVis') { + controlVis = allMetas[i].content; + } + } +} + +// Key trap fix, new function body for trap() +function trap(e) { + if (!e) { + e = event; + e.which = e.keyCode; + } + try { + modifierKey = e.ctrlKey || e.altKey || e.metaKey; + } + catch(e) { + modifierKey = false; + } + return modifierKey || e.which == 0; +} + +function startup() { + defaultCheck(); + if (!isOp) + createControls(); + slideLabel(); + fixLinks(); + externalLinks(); + fontScale(); + if (!isOp) { + notOperaFix(); + incrementals = createIncrementals(); + slideJump(); + if (defaultView == 'outline') { + toggle(); + } + document.onkeyup = keys; + document.onkeypress = trap; + document.onclick = clicker; + } +} + +window.onload = startup; +window.onresize = function(){setTimeout('fontScale()', 50);} \ No newline at end of file