2013/5/29 - 17:18 - Category / JavaScript, tmlib.js, Tutorial
ハートをタッチしたら消えるようにしよう
サンプル
コードの解説
ハートをタッチ(or クリック)した時の処理を追加してみましょう。処理を作るヒントは、「シーンをタッチした時の処理」です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
/** * 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であることです。
1 2 3 4 |
heart.addEventListener("pointingend", function() { // 消す this.remove(); }); |
こうすることで、heartをタッチした時の処理を書くことができます。ハートを消すときは、remove()関数を使います。タッチしたときにremove()関数を読んであげると、タッチしたときにハートが消えるようになります。
制限時間を作ろう
サンプル
コードの解説
今回は追加する処理が多いですが、めげないでくださいね!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
/** * 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); |
複数の処理を追加したので、一つ一つ見ていきます。まず最初に、制限時間を表示するためのラベルを追加しました。以下のコードです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// ラベルのリスト 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" }] } }; |
次に、制限時間を設定するための変数が増えました。
1 |
var LIMIT_TIME = 300; // 10秒 x 30フレーム = 300 |
ゲームの処理は一秒間に30回行われるので、それを見越して10秒を制限時間に設定したい場合は300となります。この300という値をゲームの実行毎にマイナス1していくことで、10秒経ったのかどうかが分かるようにします。
次に、update()という関数が増えました。update()関数は、ゲームの処理毎に呼ばれる関数です。そのため、一秒間に30回呼ばれることになります。
1 2 3 4 5 6 7 8 9 10 11 12 |
update: function (app) { // カウントダウンを行う --this.limitTime; // 制限時間を表示する this.limitTimeLabel.text = "残り時間 : " + ((this.limitTime / 30) |0); // 制限時間がなくなったらEndSceneに遷移する if (this.limitTime <= 0) { app.replaceScene(ns.EndScene()); } }, |
カウントダウンを行なって、0になれば勝手にEndSceneに遷移するように処理を作ります。画面に表示する制限時間の計算方法も見ておきます。
1 2 |
// 制限時間を表示する this.limitTimeLabel.text = "残り時間 : " + ((this.limitTime / 30) |0); |
this.limitTime変数は秒ではありません。ややこしいですが、一秒間に30回処理が行われる上で成り立っている300という数値です。30で割ることで現在の残り時間を取得することができます。”|0″というのはJavaScriptのテクニックの一つで、値を整数にします。割り算してるので小数点以下の数が出てしまいますが、”|0″のテクニックを使うことで整数になります。
全てハートを消したらゲームが終わるようにしよう
サンプル
コードの解説
ハートの数が今いくつなのか分かるように、「グループ」を作って管理するように変更しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
/** * 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の数を簡単に取得することができます。
1 2 3 4 |
// ハートが全部なくなったらEndSceneに遷移する if (this.heartGroup.children.length <= 0) { app.replaceScene(ns.EndScene()); } |
これで、EndSceneに遷移する条件は「ハートが全部無くなる」か、「制限時間が無くなる」場合の2つとなりました。
スコアを表示しよう
サンプル
コードの解説
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
/** * 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に渡したデータをどうするのかと言うと……。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
/** * 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関数がデータを受け取ることができます。で、受け取ったデータはそのままスコアの計算に使っています。
1 2 |
// スコア計算 RESULT_PARAM.score = (leftTime * 100) |0; |
これでスコアを作ることができました。ゲームの処理はこれで出来上がりです!お疲れ様でした!!次はゲームを彩ってくれる”音”を入れてみたいと思います。
もうちょっと詳しく解説
よく見ると……
1 2 3 4 |
// Backボタンを押したらTitleSceneに戻る onnextscene: function (e) { e.target.app.replaceScene(ns.TitleScene()); }, |
この処理も新たに追加していますね。これはコメントの通り、Backボタンを押した時の動作を書くための処理です。今まで画面をタッチしたらTitleSceneに戻っていましたが、Backボタンを押した時のみTitleSceneに行くよう変更しています。