ハートをタッチしたら消えるようにしよう
サンプル
コードの解説
ハートをタッチ(or クリック)した時の処理を追加してみましょう。処理を作るヒントは、「シーンをタッチした時の処理」です。
/** * MainScene */ (function(ns) { // ラベルのリスト var UI_DATA = { LABELS: { children: [{ type: "Label", name: "label", x: 40, y: 80, width: ns.SCREEN_WIDTH, fillStyle: "red", text: "ここはMainSceneです。", fontSize: 30, align: "left" }] } }; var HEART_SIZE = 64; var HEART_NUM = 10; var HEART_PARAM = { fillStyle: "pink", }; ns.MainScene = tm.createClass({ superClass : tm.app.Scene, init : function() { this.superInit(); // ラベル表示 this.fromJSON(UI_DATA.LABELS); // 画面(シーンの描画箇所)をタッチした時の動作 // this.addEventListener("pointingend", function(e) { // // シーンの遷移 // e.app.replaceScene(ns.EndScene()); // }); // たくさんハートを作る for (var i = 0; i < HEART_NUM; ++i) { // 色をつくる HEART_PARAM.fillStyle = tm.graphics.Color.createStyleHSLA(Math.rand(0, 360), 95, 75, 0.8); // ハートを作る var heart = tm.app.HeartShape( HEART_SIZE, HEART_SIZE, HEART_PARAM); // 表示位置 heart.position.set( Math.rand(HEART_SIZE/2, ns.SCREEN_WIDTH - HEART_SIZE/2), Math.rand(HEART_SIZE/2, ns.SCREEN_HEIGHT - HEART_SIZE/2)); // ハートをタッチした時の処理を作る heart.interaction.enabled = true; // ヒット判定フラグをON heart.interaction.boundingType = "circle"; // 円形のヒット判定を行う heart.addEventListener("pointingend", function() { // 消す this.remove(); }); // 表示する this.addChild(heart); } }, }); })(game);
シーンをタッチした時の処理と同じく、addEventListener()関数を使います。違うのは、addEventListenerの左側に書いてある変数が、thisではなく、heartであることです。
heart.addEventListener("pointingend", function() { // 消す this.remove(); });
こうすることで、heartをタッチした時の処理を書くことができます。ハートを消すときは、remove()関数を使います。タッチしたときにremove()関数を読んであげると、タッチしたときにハートが消えるようになります。
制限時間を作ろう
サンプル
コードの解説
今回は追加する処理が多いですが、めげないでくださいね!
/** * MainScene */ (function(ns) { // ラベルのリスト var UI_DATA = { LABELS: { children: [{ type: "Label", name: "label", x: 40, y: 80, width: ns.SCREEN_WIDTH, fillStyle: "red", text: "ここはMainSceneです。", fontSize: 30, align: "left" },{ type: "Label", name: "limitTimeLabel", x: 200, y: 120, width: ns.SCREEN_WIDTH, fillStyle: "white", text: " ", fontSize: 40, align: "left" }] } }; var HEART_SIZE = 64; var HEART_NUM = 10; var HEART_PARAM = { fillStyle: "pink", }; var LIMIT_TIME = 300; // 10秒 x 30フレーム = 300 ns.MainScene = tm.createClass({ superClass : tm.app.Scene, init : function() { this.superInit(); // ラベル表示 this.fromJSON(UI_DATA.LABELS); // たくさんハートを作る for (var i = 0; i < HEART_NUM; ++i) { // 色をつくる HEART_PARAM.fillStyle = tm.graphics.Color.createStyleHSLA(Math.rand(0, 360), 95, 75, 0.8); // ハートを作る var heart = tm.app.HeartShape( HEART_SIZE, HEART_SIZE, HEART_PARAM); // 表示位置 heart.position.set( Math.rand(HEART_SIZE/2, ns.SCREEN_WIDTH - HEART_SIZE/2), Math.rand(HEART_SIZE/2, ns.SCREEN_HEIGHT - HEART_SIZE/2)); // ハートをタッチした時の処理を作る heart.interaction.enabled = true; // ヒット判定フラグをON heart.interaction.boundingType = "circle"; // 円形のヒット判定を行う heart.addEventListener("pointingend", function() { // 消す this.remove(); }); // 表示する this.addChild(heart); } // 制限時間 this.limitTime = LIMIT_TIME; }, update: function (app) { // カウントダウンを行う --this.limitTime; // 制限時間を表示する this.limitTimeLabel.text = "残り時間 : " + ((this.limitTime / 30) |0); // 制限時間がなくなったらEndSceneに遷移する if (this.limitTime <= 0) { app.replaceScene(ns.EndScene()); } }, }); })(game);
複数の処理を追加したので、一つ一つ見ていきます。まず最初に、制限時間を表示するためのラベルを追加しました。以下のコードです。
// ラベルのリスト var UI_DATA = { LABELS: { children: [{ type: "Label", name: "label", x: 40, y: 80, width: ns.SCREEN_WIDTH, fillStyle: "red", text: "ここはMainSceneです。", fontSize: 30, align: "left" },{ type: "Label", name: "limitTimeLabel", x: 200, y: 120, width: ns.SCREEN_WIDTH, fillStyle: "white", text: " ", fontSize: 40, align: "left" }] } };
次に、制限時間を設定するための変数が増えました。
var LIMIT_TIME = 300; // 10秒 x 30フレーム = 300
ゲームの処理は一秒間に30回行われるので、それを見越して10秒を制限時間に設定したい場合は300となります。この300という値をゲームの実行毎にマイナス1していくことで、10秒経ったのかどうかが分かるようにします。
次に、update()という関数が増えました。update()関数は、ゲームの処理毎に呼ばれる関数です。そのため、一秒間に30回呼ばれることになります。
update: function (app) { // カウントダウンを行う --this.limitTime; // 制限時間を表示する this.limitTimeLabel.text = "残り時間 : " + ((this.limitTime / 30) |0); // 制限時間がなくなったらEndSceneに遷移する if (this.limitTime <= 0) { app.replaceScene(ns.EndScene()); } },
カウントダウンを行なって、0になれば勝手にEndSceneに遷移するように処理を作ります。画面に表示する制限時間の計算方法も見ておきます。
// 制限時間を表示する this.limitTimeLabel.text = "残り時間 : " + ((this.limitTime / 30) |0);
this.limitTime変数は秒ではありません。ややこしいですが、一秒間に30回処理が行われる上で成り立っている300という数値です。30で割ることで現在の残り時間を取得することができます。”|0″というのはJavaScriptのテクニックの一つで、値を整数にします。割り算してるので小数点以下の数が出てしまいますが、”|0″のテクニックを使うことで整数になります。
全てハートを消したらゲームが終わるようにしよう
サンプル
コードの解説
ハートの数が今いくつなのか分かるように、「グループ」を作って管理するように変更しました。
/** * MainScene */ (function(ns) { // ラベルのリスト var UI_DATA = { LABELS: { children: [{ type: "Label", name: "label", x: 40, y: 80, width: ns.SCREEN_WIDTH, fillStyle: "red", text: "ここはMainSceneです。", fontSize: 30, align: "left" },{ type: "Label", name: "limitTimeLabel", x: 200, y: 120, width: ns.SCREEN_WIDTH, fillStyle: "white", text: " ", fontSize: 40, align: "left" }] } }; var HEART_SIZE = 64; var HEART_NUM = 10; var HEART_PARAM = { fillStyle: "pink", }; var LIMIT_TIME = 300; // 10秒 x 30フレーム = 300 ns.MainScene = tm.createClass({ superClass : tm.app.Scene, init : function() { this.superInit(); // ラベル表示 this.fromJSON(UI_DATA.LABELS); // たくさんハートを作る this.heartGroup = tm.app.CanvasElement(); for (var i = 0; i < HEART_NUM; ++i) { // 色をつくる HEART_PARAM.fillStyle = tm.graphics.Color.createStyleHSLA(Math.rand(0, 360), 95, 75, 0.8); // ハートを作る var heart = tm.app.HeartShape( HEART_SIZE, HEART_SIZE, HEART_PARAM); // 表示位置 heart.position.set( Math.rand(HEART_SIZE/2, ns.SCREEN_WIDTH - HEART_SIZE/2), Math.rand(HEART_SIZE/2, ns.SCREEN_HEIGHT - HEART_SIZE/2)); // ハートをタッチした時の処理を作る heart.interaction.enabled = true; // ヒット判定フラグをON heart.interaction.boundingType = "circle"; // 円形のヒット判定を行う heart.addEventListener("pointingend", function() { // 消す this.remove(); }); // 表示する this.heartGroup.addChild(heart); } this.addChild(this.heartGroup); // 制限時間 this.limitTime = LIMIT_TIME; }, update: function (app) { // カウントダウンを行う --this.limitTime; // 制限時間を表示する this.limitTimeLabel.text = "残り時間 : " + ((this.limitTime / 30) |0); // 制限時間がなくなったらEndSceneに遷移する if (this.limitTime <= 0) { app.replaceScene(ns.EndScene()); } // ハートが全部なくなったらEndSceneに遷移する if (this.heartGroup.children.length <= 0) { app.replaceScene(ns.EndScene()); } }, }); })(game);
ハイライトの部分をみてみると、this.addChild()としてシーンに追加するのはグループのみになってますね。そのグループに対してheartをaddChild()するので、シーンから見るとheartは子でなく孫になります。一つグループをかませることにより、heartの数を簡単に取得することができます。
// ハートが全部なくなったらEndSceneに遷移する if (this.heartGroup.children.length <= 0) { app.replaceScene(ns.EndScene()); }
これで、EndSceneに遷移する条件は「ハートが全部無くなる」か、「制限時間が無くなる」場合の2つとなりました。
スコアを表示しよう
サンプル
コードの解説
/** * MainScene */ (function(ns) { // ラベルのリスト var UI_DATA = { LABELS: { children: [{ type: "Label", name: "label", x: 40, y: 80, width: ns.SCREEN_WIDTH, fillStyle: "red", text: "ここはMainSceneです。", fontSize: 30, align: "left" },{ type: "Label", name: "limitTimeLabel", x: 200, y: 120, width: ns.SCREEN_WIDTH, fillStyle: "white", text: " ", fontSize: 40, align: "left" }] } }; var HEART_SIZE = 64; var HEART_NUM = 10; var HEART_PARAM = { fillStyle: "pink", }; var LIMIT_TIME = 300; // 10秒 x 30フレーム = 300 ns.MainScene = tm.createClass({ superClass : tm.app.Scene, init : function() { this.superInit(); // ラベル表示 this.fromJSON(UI_DATA.LABELS); // たくさんハートを作る this.heartGroup = tm.app.CanvasElement(); for (var i = 0; i < HEART_NUM; ++i) { // 色をつくる HEART_PARAM.fillStyle = tm.graphics.Color.createStyleHSLA(Math.rand(0, 360), 95, 75, 0.8); // ハートを作る var heart = tm.app.HeartShape( HEART_SIZE, HEART_SIZE, HEART_PARAM); // 表示位置 heart.position.set( Math.rand(HEART_SIZE/2, ns.SCREEN_WIDTH - HEART_SIZE/2), Math.rand(HEART_SIZE/2, ns.SCREEN_HEIGHT - HEART_SIZE/2)); // ハートをタッチした時の処理を作る heart.interaction.enabled = true; // ヒット判定フラグをON heart.interaction.boundingType = "circle"; // 円形のヒット判定を行う heart.addEventListener("pointingend", function() { // 消す this.remove(); }); // 表示する this.heartGroup.addChild(heart); } this.addChild(this.heartGroup); // 制限時間 this.limitTime = LIMIT_TIME; }, update: function (app) { // カウントダウンを行う --this.limitTime; // 制限時間を表示する this.limitTimeLabel.text = "残り時間 : " + ((this.limitTime / 30) |0); // 制限時間がなくなったらEndSceneに遷移する if (this.limitTime <= 0) { app.replaceScene(ns.EndScene(0)); } // ハートが全部なくなったらEndSceneに遷移する if (this.heartGroup.children.length <= 0) { app.replaceScene(ns.EndScene(this.limitTime)); } }, }); })(game);
EndSceneに現在残っているリミット時間を渡すようにしています。そして、EndSceneに渡したデータをどうするのかと言うと……。
/** * EndScene */ (function(ns) { // ラベルのリスト var UI_DATA = { LABELS: { children: [{ type: "Label", name: "label", x: 40, y: 80, width: ns.SCREEN_WIDTH, fillStyle: "red", text: "ここはEndSceneです。", fontSize: 30, align: "left" }] } }; var RESULT_PARAM = { score: 256, msg: "【タッチゲーム制作チュートリアル】", hashtags: ["omatoro", "tmlibチュートリアル"], url: "http://testcording.com", width: ns.SCREEN_WIDTH, height: ns.SCREEN_HEIGHT, related: "tmlib.js Tutorial testcording", }; ns.EndScene = tm.createClass({ superClass : tm.app.ResultScene, init : function(leftTime) { // スコア計算 RESULT_PARAM.score = (leftTime * 100) |0; // スコア this.superInit(RESULT_PARAM); // ラベル表示 this.fromJSON(UI_DATA.LABELS); // // 画面(シーンの描画箇所)をタッチした時の動作 // this.addEventListener("pointingend", function(e) { // // シーンの遷移 // e.app.replaceScene(ns.TitleScene()); // }); }, // Backボタンを押したらTitleSceneに戻る onnextscene: function (e) { e.target.app.replaceScene(ns.TitleScene()); }, }); })(game);
init関数に引数を記述しています。こうすると、クラスを呼び出した時にinit関数がデータを受け取ることができます。で、受け取ったデータはそのままスコアの計算に使っています。
// スコア計算 RESULT_PARAM.score = (leftTime * 100) |0;
これでスコアを作ることができました。ゲームの処理はこれで出来上がりです!お疲れ様でした!!次はゲームを彩ってくれる”音”を入れてみたいと思います。
もうちょっと詳しく解説
よく見ると……
// Backボタンを押したらTitleSceneに戻る onnextscene: function (e) { e.target.app.replaceScene(ns.TitleScene()); },
この処理も新たに追加していますね。これはコメントの通り、Backボタンを押した時の動作を書くための処理です。今まで画面をタッチしたらTitleSceneに戻っていましたが、Backボタンを押した時のみTitleSceneに行くよう変更しています。