ハートをタッチしたら消えるようにしよう
サンプル
コードの解説
ハートをタッチ(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に行くよう変更しています。