tmlib.js で今流行のフラットデザインを使ったタッチゲームを作ろう – Step02 ピースのタッチ処理とゲームクリア処理を実装しよう
今回は, ピースをタッチした際にひっくり返るようにして, 更にすべてタッチし終わったらスコアを表示するようにします.
この Step でなんとなくゲームとして遊べるようになります.
Table of contents
チュートリアル目次
前半
後半
サンプル
今回作るサンプルです.
タッチするとひっくり返ってグレイになるのがわかると思います. また, 全てタッチし終わると掛かった時間が alert されます.
ソースコード
main.js
スクリプト部分のコードです. 追加した箇所のコードはハイライトされています.
Piece
に disable
というメソッドを追加しています.
更に MainScene
で Piece
を生成した際に,
onpointingstart
というプロパティに関数を登録しています.
これでタッチ時にこのメソッドが呼ばれるようになります.
詳しい解説は下へ.
/* * main.js */ /* * contant */ var SCREEN_WIDTH = 680; // スクリーン幅 var SCREEN_HEIGHT = 960; // スクリーン高さ var SCREEN_CENTER_X = SCREEN_WIDTH/2; // スクリーン幅の半分 var SCREEN_CENTER_Y = SCREEN_HEIGHT/2; // スクリーン高さの半分 var PIECE_NUM_X = 5; // ピースの列数 var PIECE_NUM_Y = 5; // ピースの行数 var PIECE_NUM = PIECE_NUM_X*PIECE_NUM_Y; // ピース数 var PIECE_OFFSET_X = 90; // ピースオフセットX var PIECE_OFFSET_Y = 240; // ピースオフセットY var PIECE_WIDTH = 120; // ピースの幅 var PIECE_HEIGHT = 120; // ピースの高さ var FONT_FAMILY_FLAT= "'Helvetica-Light' 'Meiryo' sans-serif"; // フラットデザイン用フォント /* * main */ tm.main(function() { // アプリケーションセットアップ var app = tm.app.CanvasApp("#world"); // 生成 app.resize(SCREEN_WIDTH, SCREEN_HEIGHT); // サイズ(解像度)設定 app.fitWindow(); // 自動フィッティング有効 app.background = "rgba(250, 250, 250, 1.0)";// 背景色 app.replaceScene( GameScene() ); // シーン切り替え // 実行 app.run(); }); /* * ゲームシーン */ tm.define("GameScene", { superClass: "tm.app.Scene", init: function() { this.superInit(); var self = this; // カレント数 self.currentNumber = 1; // ピースグループ this.pieceGroup = tm.app.CanvasElement(); this.addChild(this.pieceGroup); // 数字配列 var nums = [].range(1, PIECE_NUM+1); // 1~25 nums.shuffle(); // シャッフル // ピースを作成 for (var i=0; i<PIECE_NUM_Y; ++i) { for (var j=0; j<PIECE_NUM_X; ++j) { // 数値 var number = nums[ i*PIECE_NUM_X+j ]; // ピースを生成してピースグループに追加 var piece = Piece(number).addChildTo(this.pieceGroup); // 座標を設定 piece.x = j * 125 + PIECE_OFFSET_X; piece.y = i * 125 + PIECE_OFFSET_Y; // タッチ時のイベントリスナーを登録 piece.onpointingstart = function() { // 正解かどうかの判定 if (this.number === self.currentNumber) { // クリアかどうかの判定 if (self.currentNumber === PIECE_NUM) { // 結果表示 var time = (self.app.frame/self.app.fps)|0; alert("GameClear: {0}".format(time)); } self.currentNumber += 1;// インクリメント this.disable(); // ボタン無効 } }; } } }, }); /* * ピースクラス */ tm.define("Piece", { superClass: "tm.app.Shape", init: function(number) { this.superInit(PIECE_WIDTH, PIECE_HEIGHT); // 数値をセット this.number = number; this.setInteractive(true); this.setBoundingType("rect"); var angle = tm.util.Random.randint(0, 360); this.canvas.clearColor("hsl({0}, 80%, 70%)".format(angle)); this.label = tm.app.Label(number).addChildTo(this); this.label .setFontSize(70) .setFontFamily(FONT_FAMILY_FLAT) .setAlign("center") .setBaseline("middle"); }, disable: function() { this.setInteractive(false); var self = this; this.tweener .clear() .to({scaleX:0}, 100) .call(function() { self.canvas.clearColor("rgb(100, 100, 100)"); }.bind(this)) .to({scaleX:1, alpha:0.5}, 100) } });
解説
タッチ判定を無効にする
setInteractionve()
メソッドに false を渡して実行することで
タッチ判定を無効化することができます.
こうすることで pointingstart
, pointingmove
, pointingend
といった
イベントが発火されなくなります.
disable: function() { this.setInteractive(false);
Tweener を使ってピースをタッチしたときにアニメーションさせよう
tmlib.js には tweener
というクラスがあります.
これを使うことで簡単に複雑なアニメーションをさせることができます.
ActionScript の Tweener
的なものですね.
Sprite
や Shape
, Label
といったインスタンスの
tweener
プロパティとして使うことができます.
今回, tweener
を使った処理について詳しく見て行きましょう.
this.tweener .clear() .to({scaleX:0}, 100) .call(function() { self.canvas.clearColor("rgb(100, 100, 100)"); }.bind(this)) .to({scaleX:1, alpha:0.5}, 100)
繋げて実行しているのでパッと見, 分かりにくいかもしれませんが
単純に tweener
のメソッドを連続で実行しているだけです.
tmlib.js のクラスは基本チェーンメソッドが使えるよう実装してあるので,
clear().to(...).call(...);
といった形で繋げて実行することができます.
次に処理の方ですが, まず clear()
メソッドを呼んで登録されているアニメーションタスクをクリアします.
this.tweener .clear()
その次に to()
メソッドでアニメーションを登録しています.
scaleX
を 100 ms かけて 0 にします.
.to({scaleX:0}, 100)
その次に call
で登録されたメソッドを呼びます.
今回は色を変更しています.
.call(function() { self.canvas.clearColor("rgb(100, 100, 100)"); }.bind(this))
最後にもう一度 scaleX
を 1 にすることで
大きさを元に戻しています.
.to({scaleX:1, alpha:0.5}, 100)
これで一旦小さくなって色が変わって元に戻るという アニメーションが再生されます.
ひっくり返ってるように見えませんかね?w
Tweener
クラスは他にも wait
で処理を待ったり,
move
で座標を動かしたり, fadeOut
でフェードアウトさせたりと便利な機能がたくさんあります.
色々いじって遊んでみてください.
ピースをタッチ時のイベントを登録しよう
setInteractive(true)
を実行したインスタンスは,
タッチ時に pointingstart
というイベントが発行されます.
onpointingstart
プロパティに代入した関数もしくは,
addEventListener(function() {...})
と登録した関数が実行されます.
// タッチ時のイベントリスナーを登録 piece.onpointingstart = function() { .... };
終了判定を実装しよう
最後に終了判定です.
onpointingstart
で実行している処理について見て行きましょう.
// 正解かどうかの判定 if (this.number === self.currentNumber) { // クリアかどうかの判定 if (self.currentNumber === PIECE_NUM) { // 結果表示 var time = (self.app.frame/self.app.fps)|0; alert("GameClear: {0}".format(time)); } self.currentNumber += 1;// インクリメント this.disable(); // ボタン無効 }
まず, 押されたピースの number
プロパティが scene の currentNumber
プロパティと
一致するかを判定します.
一致していれば currentNumber
を次の数字にして,
押されたピースを disable()
メソッドで無効化します.
self.currentNumber += 1;// インクリメント this.disable(); // ボタン無効
更に, currentNumber
が PIECE_NUM
, つまり最後のピースの数と一致すると
全て押し終わったということになるので終了として
掛かった時間を alert します.
// クリアかどうかの判定 if (self.currentNumber === PIECE_NUM) { // 結果表示 var time = (self.app.frame/self.app.fps)|0; alert("GameClear: {0}".format(time)); }
経過時間は app.frame
で取得できます.
それを app.fps
で割れば経過秒数を取得することができます.
これを (...)|0
で整数化して time
を求めています.
var time = (self.app.frame/self.app.fps)|0;
更に前回の Step で学んだ format
を使って alert
メッセージを作成しています.
alert("GameClear: {0}".format(time));
まとめ
おさえておいて欲しいポイント
- tmlib.js のクラスは基本チェーンメソッドが使える
Tweener
というクラスで簡単にアニメーションできるsetInteractive()
メソッドでタッチ判定の有効/無効を切り替えられる- 経過時間は
app.frame
で取得でるのでそれをapp.fps
で割ることで経過秒数を取得できる
これで前半の Step は終わりとなります. とても簡単ですよね♪
ここまでで詰まったりうまく動かないなどありましたら 気軽に @phi_jpまでご連絡ください.
次回は後半, ゲームに色々な演出を加えてより ゲームっぽくしていきます.
[…] Step02 ピースのタッチ処理とゲームクリア処理を実装しよう (サンプル) […]
[…] Step02 ピースのタッチ処理とゲームクリア処理を実装しよう (サンプル) […]
[…] Step02 ピースのタッチ処理とゲームクリア処理を実装しよう (サンプル) […]
[…] Step02 ピースのタッチ処理とゲームクリア処理を実装しよう (サンプル) […]