前回でシーンの行き来を覚えました。
前回は、ただタイトルと、実際は何もないゲーム画面を行ったりきたりしただけでしたが、今回は「Game.js」をゲームブロック崩しに仕上げてみます。
完成ページを見てみましょう。
※PCの場合グーグルクロームかSafari、スマートフォンの場合アンドロイド、iPhoneでごらんください
完成サンプルはこちら
jActionで作られてるので、もちろんそのままスマートフォンで動きます。
前回までと同じで
「index.html」「jAction.js」「Main.js」「Start.js」「Game.js」があります。
「Image」フォルダの中は
Bg.jpg -- ゲーム用の背景画像 titleBg.jpg - タイトル画面用背景画像 touchStart.png - タイトル画面に表示される「タッチスタート」の文字素材 block.jpg - ブロック崩しゲーム用のブロック |
が入ってます。
「Main.js」「Start.js」の中身は前回のチュートリアルと全く同じものです。
今回重要なのは「Game.js」になります。では「Game.js」を見てましょう。
Game = function() { EventDispatcher.initialize(this); var boxObject = new ja.BoxClass(20,20,"#0000ff"); boxObject.x = 150; boxObject.y = 200; var barObj = new ja.BoxClass(100 ,15 ,"#00ffff"); //自分の指で動かすバー barObj.x = 110; barObj.y = 400; var actionFlg = false; var xinc = 5; var yinc = 5; ja.imageUnitObj.addEventListener("onLoad", this); ja.imageUnitObj.load(["Image/Bg.jpg", "Image/block.jpg"]); var block_array = new Array(); //ブロックを格納する配列を作る var textObj = new ja.TextClass(); textObj.color = "#FFFFFF"; textObj.x = 0; textObj.y = 100; var startTextObj = new ja.TextClass(); startTextObj.px = "30px"; startTextObj.color = "#FFFFFF"; startTextObj.x = 50; startTextObj.y = 200; startTextObj.text = "タッチでスタート"; var blockContainer = new ja.Container(); this.onLoad = function() { window.scrollTo(0, 1); //アドレスバーを消す ja.imageUnitObj.removeEventListener("onLoad", this); ja.stage.addChild(ja.imageUnitObj["Bg"]); ja.stage.addChild(blockContainer); ja.stage.addChild(boxObject); ja.stage.addChild(barObj); ja.stage.addChild(startTextObj); ja.stage.addChild(textObj); var x = 10; for(var i = 0 ; i < 5 ; i++) { var y = 0; for(var j = 0 ; j < 3 ; j++) { var block = new ja.ImageClass(ja.imageUnitObj["block"]); block.x = x; block.y = y; blockContainer.addChild(block); y += block.h + 10; } x += block.w + 10; } textObj.text = "残りのブロックは15個"; ja.imageUnitObj["Bg"].addEventListener("touchUp", this); ja.imageUnitObj["Bg"].addEventListener("touchMove", this); }; this.touchMove = function(e) { barObj.x = e.touch_x - 50; }; this.touchUp = function() { ja.imageUnitObj["Bg"].removeEventListener("touchUp", this); startTextObj.visible = false; if(actionFlg) { actionFlg = false; this.dispatchEvent({type:"onGameEnd", target:this}); } else { actionFlg = true; boxObject.addEventListener("onEnterFrame" , this); } }; this.onEnterFrame = function() { boxObject.x += xinc; boxObject.y += yinc; for(var i = 0 ; i < blockContainer.numChildren() ; i++) { var blockObj = blockContainer.getChildAt(i); if(ja.hitObj.intersect(boxObject,blockObj)) { blockContainer.removeChildAt(i); yinc = -yinc; textObj.text = "残り" + blockContainer.numChildren() + "個"; break; } } if(ja.hitObj.intersect(boxObject , barObj)) { yinc = -yinc; boxObject.y = barObj.y - boxObject.h - 1; } if(boxObject.x >= 300) { boxObject.x = 300; xinc = -xinc; } else if(boxObject.x <= 0) { boxObject.x = 0; xinc = -xinc; } if(boxObject.y <= 0) { boxObject.y = 0; yinc = -yinc; } else if(boxObject.y > 480) { startTextObj.x = 20; startTextObj.text = "タッチでタイトル画面へ" startTextObj.visible = true; boxObject.removeEventListener("onEnterFrame" , this); ja.imageUnitObj["Bg"].addEventListener("touchUp", this); } }; this.destroy = function() { for(var i = ja.stage.numChildren() - 1 ; i >= 0 ; i--) { ja.stage.removeChildAt(i); } ja.imageUnitObj.destroy(); EventDispatcher.destroy(this); }; }; |
「Game.js」は「チュートリアル2」の「ブロックの数を表示する(文字を表示する)」が元になっています。
どこが「チュートリアル2」の「ブロックの数を表示する(文字を表示する)」と比べて変わったか見てみましょう。
EventDispatcher.initialize(this); |
前回のチュートリアルの通り、イベントを発生させるオブジェクトは、まずこの宣言をしなければなりません。
「Game.js」が、イベントを発行するのに必要な処理です。
自分の指で動かすバーも必要です。
var barObj = new ja.BoxClass(100 ,15 ,"#00ffff"); //自分の指で動かすバー |
今回はボールと同じで「ja.BoxClass」を使って生成しました。
ja.imageUnitObj["Bg"].addEventListener("touchMove", this); |
画面全体なので、画面全体に貼られているBG画面に、「”touchMove”」リスナーを貼ります。
touchMoveは、指が画面上で動くと反応します。
touchMoveメソッドは以下のように定義しました。
this.touchMove = function(e) { barObj.x = e.touch_x - 50; } |
eという引数が指定されていますが、eは画面上の指の動きのイベントオブジェクトが格納されています。
「e.touch_x」で画面上のX座標です。今回使いませんが「e.touch_y」でY座標も拾えます。
バーは左上が原点で幅100ピクセルのバーです。
指の位置を真ん中にしたいので、半分の長さの50ピクセル分を引いていきます。
this.onEnterFrameメソッドに、ブロックの跳ね返りだけでなく
if(ja.hitObj.intersect(boxObject , barObj)) { yinc = -yinc; boxObject.y = barObj.y - boxObject.h - 1; } |
動かすバーの当たり判定と跳ね返り処理をいれます。
玉とバーが接触してyincの+-が逆転してますが、次の瞬間触れてると戻って誤動作してしまいますので、
念の為に
boxObject.y = barObj.y - boxObject.h - 1; |
として、バーの上に持ってきています。バーのY座標からボールの縦幅分-1ピクセル分上に持ってきてるのです。
ボールがバーの位置を飛び越えて、画面外に出たらゲームオーバーです。
if(boxObject.y > 480) { startTextObj.x = 20; startTextObj.text = "タッチでタイトル画面へ" startTextObj.visible = true; boxObject.removeEventListener("onEnterFrame" , this); ja.imageUnitObj["Bg"].addEventListener("touchUp", this); } |
でゲームオーバーの処理をしています。
ゲームオーバー時は、イベント
this.dispatchEvent({type:"onGameEnd", target:this}); |
を発行して「Main.js」に終了を伝え「Main.js」からメモリなどを綺麗にする為の最終処理「destroy」メソッドを呼ぶようにしています。
this.destroy = function() { for(var i = ja.stage.numChildren() - 1 ; i >= 0 ; i--) { ja.stage.removeChildAt(i); } ja.imageUnitObj.destroy(); EventDispatcher.destroy(this); }; |
ここで注意点がひとつあります。
ja.imageUnitObj.destroy(); |
を実行剃る前に、ja.stageに張り付いている画面オブジェクトをremoveChildしなければなりません。
複数子供の画像オブジェクトがはりついている場合は、一つづつ指定するのは面倒です。
そこで今回は、numChildren()を使って画面からremoveChildしています。
for(var i = ja.stage.numChildren() - 1 ; i >= 0 ; i--) { ja.stage.removeChildAt(i); } |
ここで気を付けないといけないのは、0番目の画像オブジェクトがremoveChildされた瞬間に1番目の画像オブジェクトが
0番目に変化することです。常に0番目からスタートするので、0番目がなくなった瞬間に一つづつ繰り上がるのです。
ここを気をつけてremoveChildしないとエラーを引き起こすことになります。
例では、安全に最後の方からremnoveChildをかけています。
for(var i = 0 ; i < ja.stage.numChildren() ; i++) { ja.stage.removeChildAt(0); } |
というやり方もあります。存在する数だけ0番めの画像オブジェクトをremoveChildするのです。
後は、いままでのチュートリアルの応用です。
今回簡単なブロック崩しゲームを作ってみましたが、バーのどの位置で当たったかを判定して跳ね返る位置を変えたり
時間経過と共にボールのスピードを早めるなどすると、ゲームとしての面白さは、ぐっとあがってきます。
是非、挑戦してみてください。
次回はチュートリアル5「音の再生」に移ります。
実は音に関しては、iOSでは同時再生1音のみ、アンドロイドではOS2.2 などでは音はなりません。
jActionでは、アンドロイドではFlashの音声モジュールを併用して音を再生します。