2-1 ゲーム制作の基礎知識1 インデックスとタイマー

第二章ではゲームを開発するために必要な知識を解説します。 そして本講座で学んで下さっている方が、ご自身でゲームを完成させられるところまで到達したいと思います。

人気のあるスマートフォンのソーシャルゲームや家庭用ゲームソフトは、ゲームの中で様々な世界を冒険でき、色々なキャラクターが登場します。 ゲームのシステムやルールも、キャラクターを育てたり、たくさんの収集物を手に入れたり、 中には世界そのものを作っていくことができるなど、やりごたえのある内容になっています。 昨今のコンピューターゲームの中身はこのようにとても凝ったものになっています。 ですので、プログラミングを学び始めて日が浅い方は市販ゲームの内容に圧倒され、 本当にゲームが作れるようになるのだろうかと心配されるかもしれませんが、その心配は無用です。 様々な要素が詰まっているゲームでも、処理の基本は実はそれほど複雑ではないのです。 コンピューターが行う処理の全体像を知るとそのことが理解できます。 処理の流れを理解することはゲーム開発に必要な知識ですので、まずはゲームの処理の基本的な流れを解説します。


(1)処理の流れを管理する

ゲームには色々なジャンルがありますが、どのようなジャンルのゲームでも最も中心となる処理はシンプルにできています。 具体的には次のようになります。


この基本的な流れに、それぞれのゲームに必要な処理が加わります。 例えばキャラクター選択やステージ選択があるゲームは、タイトルからゲーム画面に移行する間にそれらの処理が入ります。 ゲーム中にメニュー画面を開ける場合は、ゲーム画面でメニューボタンを押した時にその処理に入るわけです。 主人公の残り人数やハートが無くなるまでゲームを続けられるルールであれば、ゲームオーバーに移行する前にやられた演出画面があり、人数やハートが残っていれば再びゲーム画面に戻ります。 全ての条件を達成した時にエンディングを迎えられるゲームであれば、ゲームクリアの後にその処理に入ります。

ゲーム内の目標や条件が達成された時のゲームクリアやステージクリアの“クリア”という言葉は日本独特の表現だそうです。 我々日本人にとってはこの言葉が一番判りやすいと思いますので、 本講座では成功した時をゲームクリア、失敗してゲーム終了となる時をゲームオーバーと表現します。


このような処理の流れはインデックスとタイマーで実現します。 まずはこの図の流れを行うサンプルを見てみましょう。
example211.html ← 動作の確認
ソースコードは次のようになります。
01<!DOCTYPE html>
02<html lang="ja">
03<head>
04<meta charset="utf-8">
05<title>JavaScriptのテストプログラム</title>
06</head>
07<body style="text-align:center;">
08<canvas style="background-color:#cef;" id="bg" width="800" height="600"></canvas>
09<script>
10var canvas = document.getElementById("bg");
11var cnt = canvas.getContext("2d");
12cnt.font = "36px monospace";
13cnt.textAlign = "center";
14cnt.textBaseline = "middle";
15
16//マウスとタップの判定
17var tapX = 0, tapY = 0, tapC = 0;
18
19if( 'ontouchend' in document ) {
20 canvas.addEventListener( "touchstart", touchStart );
21 canvas.addEventListener( "touchend", touchEnd );
22 function touchStart(event) {
23  event.preventDefault();
24  var rect = event.target.getBoundingClientRect();
25  tapX = Math.floor( event.touches[0].clientX-rect.left );
26  tapY = Math.floor( event.touches[0].clientY-rect.top );
27  tapC = 1;
28 }
29 function touchEnd(event) {
30  event.preventDefault();
31  tapC = 0;
32 }
33}
34else {
35 canvas.addEventListener( "mousedown", mouseDown );
36 canvas.addEventListener( "mouseup", mouseUp );
37 function mouseDown(event) {
38  var rect = event.target.getBoundingClientRect();
39  tapX = event.clientX-rect.left;
40  tapY = event.clientY-rect.top;
41  tapC = 1;
42 }
43 function mouseUp(event) {
44  tapC = 0;
45 }
46}
47
48//描画用の関数
49function fText( str, x, y, col ) {//文字表示
50 cnt.fillStyle = col;
51 cnt.fillText( str, x, y );
52}
53
54function fRect( x, y, w, h, col ) {//矩形
55 cnt.fillStyle = col;
56 cnt.fillRect( x, y, w, h );
57}
58
59//以下がメイン処理
60var idx = 0;
61var tmr = 0;
62
63window.onload = indexProc();
64function indexProc() {
65 tmr ++;
66 fRect( 0, 0, 800, 600, "#000" );
67 fText( "インデックス:"+idx, 200, 25, "#ff0" );
68 fText( "タイマー:"+tmr, 600, 25, "#0ff" );
69 fText( "tapX="+tapX+" tapY="+tapY+" tapC="+tapC, 400, 575, "#fff" );
70
71 switch( idx ) {
72  case 0:
73  fRect( 100, 100, 600, 200, "#cf8" );
74  fText( "タイトル画面", 400, 200, "#000" );
75  fText( "画面をタップしてスタート", 400, 400, "#fff" );
76  if( tapC == 1 ) { idx = 1; tmr = 0; tapC = 0; }
77  break;
78
79  case 1:
80  fText( "ゲーム画面", 400, 100, "#8f8" );
81  fRect( 100, 200, 200, 300, "#0ff" );
82  fText( "目標達成", 200, 350, "#000" );
83  fRect( 500, 200, 200, 300, "#ff0" );
84  fText( "失敗", 600, 350, "#000" );
85  if( tapC == 1 ) {
86  if( 100 <= tapX && tapX < 300 && 200 <= tapY && tapY < 500 ) { idx = 2; tmr = 0; }
87  if( 500 <= tapX && tapX < 700 && 200 <= tapY && tapY < 500 ) { idx = 3; tmr = 0; }
88  }
89  break;
90
91  case 2:
92  fRect( 400-tmr*3, 300-tmr, tmr*6, tmr*2, "#48f" );
93  fText( "ゲームクリア", 400, 300, "#000" );
94  if( tmr == 100 ) idx = 0;
95  break;
96
97  case 3:
98  fRect( 100+tmr*3, 200+tmr, 600-tmr*6, 200-tmr*2, "#f0c" );
99  fText( "ゲームオーバー", 400, 300, "#000" );
100  if( tmr == 100 ) idx = 0;
101  break;
102 }
103
104 setTimeout( indexProc, 100 );
105}
106</script>
107</body>
108</html>

今回のソースではインデックスの変数名をidx、タイマーをtmrとしました。 インデックスで何の処理を行うかを管理し、タイマーは文字通り時間を管理します。
メインの処理がindexProc()という関数で、setTimeout命令でリアルタイム処理を行っています。 プログラムの流れが判りやすいように、idxとtmr、タップの値を画面に表示しました。
今回は idx の値が 0 の時にタイトル画面の処理、1の時にゲーム画面の処理、2の時にゲームクリアの処理、3の時にゲームオーバーの処理を行うようにしており、 switch文で次のように各処理へ分岐させています。

タイトル画面では画面をタップした時に idx=1 としゲーム画面に移行します。 ゲーム画面では左の枠内をタップした時にゲームクリア(idx=2)、右の枠内をタップした時にゲームオーバーの処理(idx=3)に移行します。 ゲームクリアとゲームオーバーの処理はタイマーで管理し、tmrの値が100になった時にタイトル画面に戻しています(idx=0)。 タイマー用の変数tmrは毎フレームカウントアップし、必要な時に0にリセットするようにしています。

以上がインデックスとタイマーによるゲームの進行管理です。 ゲームメーカーが発売する多くのゲームソフトの処理は基本的にこのようになっています。


(2)ゲームの仕様を考えよう

ゲーム会社の開発の現場には、制作するゲームの内容をまとめた仕様書が存在します。 仕様書には、キャラクターにどんなパラメーターが設定されそれがゲームの何に影響するか、 各ステージのクリア条件は何かなど、ゲームを開発する上で必要な情報が事細かに書かれているのが一般的です。 個人レベルのゲーム開発ではそこまで細かい資料を用意する必要はないですが、 ゲームを完成させるために必要と思われる項目を書き出すだけで、プログラミングの速度は確実に上がります。
そこで制作するゲームの完成形をイメージし、まずどのような画面があるか書き出してみましょう。 そしてそれぞれの画面の内容を箇条書きにしてみると、プログラムすべき内容(仕様)がはっきりします。

例えば「タップ入力した位置に猫を誘導しネズミを捕らせるゲーム」を作るなら、その内容を次のように箇条書きにしてみます。
index画面内容
0タイトル
画面をタップしたらゲーム開始
1ゲーム
タップした位置に猫を移動させる
ネズミに触れたら点数を増やし、一定数捕まえたらステージクリア
持ち時間を減らしていき、時間0でゲームオーバー
犬に接触したら持ち時間を多く減らす
2ステージクリア
一定時間文字を表示する
ステージ数が10の場合はエンディングへ
そうでなければステージ数を+1し再びゲーム開始
3エンディング
「おめでとう!」の文字を表示し、タイトルに戻る
4ゲームオーバー
一定時間文字を表示したらタイトルに戻る
2-3 で実際にこのゲームを制作します

処理の流れをフローチャートにすると更に判りやすくなります。
正式なフローチャートは、処理の開始と終了を両側を丸めた長方形、処理を長方形、判断(処理の分岐)をひし形で記述しますが、 個人レベルのゲーム制作では、(1)の図のように四角内に処理を書き矢印で流れを書くだけでも十分プログラムが組みやすくなります。

本格的なフローチャートを書くには表計算ソフトが便利
エクセルや、エクセルと互換性のあるフリーの表計算ソフト(LibreOfficeのCalcなど)には、フローチャートの図形が用意されています。 プログラマーを目指される方は、一度、正式なフローチャートを書いてみてはいかがでしょう。 プログラミング用のフローチャートではそれぞれの処理や判断に簡単な数式や命令を記述しますが、 ゲーム制作用のフローチャートでは言葉で内容を記述してもよいでしょう。

参考)正式なフローチャートで使う図形(部品)

これら以外にも処理に応じていくつかの図形を使い分けます。
本講座ではフローチャートは概要説明に留めますが、詳しく学ばれたい方はネットで検索すればフローチャートの解説を行う様々なページがございます。



前のページへ / 次のページへ

お気軽にお問い合わせ下さい →