宿題06の解説とヒント
1. Javascriptゲーム 08
問題
サンプル08のJavascriptを使ったページを作成し、キャラクターの初期位置、ネズミの速度などのパラメーターを調整して工夫をし、js09.htmlという名前で、hw/hw04/内にアップロードしなさい。
このゲームでは、ねずみのキャラクターをrequestAnimationFrame()関数で一定時間ごとに表示位置を書き換えることで、走り回るように変更した。このアニメーションは、[ネズミを活性化/凍結]ボタンで、再開と一時停止ができる。
本来ならば、ゲームの全ての情報をJavascriptで制御した方が効率が良いが、前回のサンプルを改造したので、ネズミのクリックや、チーズの移動の部分はCSSから得られる情報を使った形のままである。
id要素
この例では、以下ように4つのidが付けられた要素を用いている。
- id="Bkg"
- 背景画像のIMG要素である。背景画像は500px×500pxのサイズで、ファイル名はbackground.pngである。
- id="Nezumi1"
- ねずみのキャラクターのDIV要素で、子要素にファイル名nezumi.pngのIMG要素を含んでいる。nezumi.pngのサイズは64px×64pxである。
CSSで、idセレクタ#Nezumi1のプロパティの定義で、position: absolute;を指定することで、親要素であるDIV要素の左上が(0,0)の原点になるようしている。leftプロパティはid="Nezumi1"の要素の左上の角のx座標、topプロパティはy座標になっている。
クリックするとジャンプするのは、<img src="nezumi.png" alt="ねずみ1" onClick="randomove('Nezumi1', D_nezumi)">のように、onClickのイベントハンドラーとしてrandomove()関数を呼び出して実行しているからである。
- id="Nezumi2"
- id="Nezumi1"と同様である。
- id="Hole"
- 穴を表すDIV要素である。サイズは100px×100pxである。CSSで、idセレクタ#Holeのプロパティの定義で、position: absolute;を指定することで、親要素であるDIV要素の左上が(0,0)の原点になるようしている。leftプロパティは200px、topプロパティは200pxとしている。IMG要素は使用せず、background-color: #000000;で黒く塗りつぶしているだけである。
グローバル変数
以下のグローバル変数を使用している。
- D_nezumi
- ねずみをクリックしたときに、ランダムに移動するが、そのときの最大の移動量を格納する変数である。70px移動するように設定されている。この値を大きくすると、ねずみのジャンプ量が大きくなり、小さくすると少ししか動かなくなる。
- num_nezumi
- 生き残っているネズミの総数を格納する変数。ネズミが池に落ちると、一つ減るようにする。この変数の値が0以下で、ゲーム終了とする。
- V_nezumi
- ネズミを活性化したときの、1フレームあたりの移動距離。
- frame
- アニメーションの1秒間あたりののフレーム数(コマ数)
- ftime
- frameから計算される1フレームの持続時間。単位はミリ秒(= 1/1000 秒)。
- CH
- 登場するキャラクターの情報を格納する連想配列。具体的には、すぐ下で定義されるCH['Nezumi1']、CH['Nezumi2']、CH['Cheese']を、各々キー'Nezumi1'、'Nezumi2'、'Cheese'の値としている。CHの値CH['Nezumi1']自体も連想配列で、キーx, y, vx, vyを持つ。xはx座標、yはy座標、vxはx方向の速さ、vyはy方向の速さである。CH['Cheese']には、vx, vyは定義されていない。
-
- D_cheese
- キーを押したときにチーズが移動する距離
- OVERLAP
- ネズミとチーズの重なり具合を表す変数。touch()関数で二つの要素の重なりがあるかないかを判定するが、第3パラメータとして、そのときの重なり具合を決めるパラメータとして使用するためのグローバル変数である。これは、ねずみとチーズの重なり具合を定め、-40という値にしている。
- OVERLAP_HOLE
- ネズミ(やチーズ)と穴の重なり具合を表す変数。touch()関数で二つの要素の重なりがあるかないかを判定するが、第3パラメータとして、そのときの重なり具合を決めるパラメータとして使用するためのグローバル変数である。これは、ねずみと穴の重なり具合を定め、-60という値にしている。
- msec
- animate()関数で使用。フレームを書き換える間隔を表す。
- requestId
- window.requestAnimationFrame(animate)の戻り値を保持する変数。アニメーションを停止するときに、window.cancelAnimationFrame(requestId)のように引数に指定する。
- lost
- ゲームに負けたときにtrueとする。今回は未使用
- finish
- ゲームが終了したときにtrueとする。今回は未使用
関数(サブルーチン)
以下の関数を定義している。
- initialize()
- document.getElementIdBy()関数を使って、id="Nezumi1"、id="Nezumi2"、id="Hole"、id="Bkg"のx座標、y座標、幅、高さなどのプロパティを設定している。ページを読み込んだときに、このinitialize()関数を実行し(87行目)、CSSで設定した値をこれらのプロパティの値で上書きしている。
- touch( obj1, obj2, overlap )
- 第一引数と第二引数の要素が重なっている場合は1、重なっていない場合は0を返す関数である。第三引数は重なりの条件を調節することができるパラメータで、0とすると調整なしの条件になる。randomove()関数の中で、ねずみと穴の重なりがあるかないかの判定に使用している。
- coordinates(element)
- 要素のleftプロパティとtopプロパティの値は、"px"という単位が付いていいるので、正規表現を使って"px"を除いた数字部分だけを取り出す関数で、返り値はposition = {x: 0, y: 0};と初期化された連想配列である。
- elmSize(element)
- 要素のwidthプロパティとheightプロパティの値は、"px"という単位が付いていいるので、正規表現を使って"px"を除いた数字部分だけを取り出す関数で、返り値はelm_size = {w: 0, h: 0};と初期化された連想配列である。
- KeyDownFunc(e)
- イベントリスナーで、キーが押されたときの処理をする関数である。key_code変数の値でどのキーが押されたのかを判断し、それに合わせてmove_cheese()関数で、押されたカーソルキーの方向にチーズを移動する。
また、id="Nezumi1"とid="Nezumi2"を、move2cheese()関数を使って、チーズの方向に移動している。
- move_cheese(Delta_x, Delta_y)
- チーズを移動する関数。移動後、穴に入ったか否かを判定している。
- move2cheese(element_id, Delta)
- ねずみをチーズの方向に移動する関数。移動後に、ねずみがチーズとぶつかったか、ねずみが穴に落ちたかを判定している。
- randomove(element_id, Delta)
- ねずみをランダムに移動する関数である。
OnClickイベントハンドラーとして使用する。
第一引数にはid名、第二引数は移動量の最大値である。また、移動したのち、穴(id="Hole")と重なった場合は、ねずみのキャラクターのdisplayプロパティを"none"にして、非表示にしている。ねずみがチーズをぶつかったか否かの判定を追加した。
- move(element, dx, dy)
- 第一引数の要素を、第二、第三引数のx、y座標だけ移動して表示する関数である。randomove()、run()、move_cheese()、move2cheese()内で使用されている。このために、pstn = coordinates(element);のようにCSSのプロパティを参照することはやめて、連想配列CH[]の情報を使うように変更した。
- start()
- [ネズミの活性化/凍結]ボタンがクリックされたときに呼び出される。アニメーションの開始と停止を行う。
- animate()
- アニメーションを開始する
- pause_animation()
- アニメーションを停止する
- run(element_id)
- ネズミを走らせる。
ページの構造を理解するためのヒント
DIV要素に枠線を付けると、ページの構造が把握しやすくなる。
例えば、DIV要素に赤い枠線を表示するよにするには、STYLE要素の内容に以下のCSSの記述を追加すれば良い。
div {
border: solid thin red;
}
戻る