tmlib.js で今流行のフラットデザインを使ったタッチゲームを作ろう – Step01 ピースを定義して並べよう
ピースクラスを定義して画面上に敷き詰めていきます.
いっきに見た目が派手になる楽しい Step です.
Table of contents
チュートリアル目次
前半
後半
サンプル
今回作るサンプルです.
画面にピースが敷き詰められているのがわかるかと思います.
ソースコード
main.js
スクリプト部分のコードです. 追加した箇所のコードはハイライトされています.
Piece というクラスを定義し, シーン内で Piece を生成, 追加しています. これで画面上にピースが敷き詰められて表示されます.
詳しい解説は下へ.
/* * 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(); // ピースグループ 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; } } }, }); /* * ピースクラス */ 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"); }, });
解説
ピース用の定数を設定する
これも Step00 で定義した定数同様, ピースに必要な数値も定数化しておくことで コード中にマジックナンバーが含まれないようにするのと後々の調整が楽になります.
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; // ピースの高さ
ピースクラスを定義しよう
tm.define
を使って Piece
というクラスを定義しています.
これは今回作るゲームの肝となるクラスになります.
細かく見て行きましょう.
/* * ピースクラス */ 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"); }, });
superClass
に tm.app.Shape
を指定することでこのクラスを継承しています.
init
内は色々とやっているので細かくみていきましょう.
まず親の初期化を superInit
で呼びます.
this.superInit(PIECE_WIDTH, PIECE_HEIGHT);
次にタッチ判定が有効になるように setInteractive
に true
を渡して実行しています.
this.setInteractive(true);
これでマウスやタッチに応じて pointingstart
や pointingmove
, pointingend
といったイベントが発行されるようになります.
また, setBoundingType
でバウンディングタイプを指定することができます.
今回は “rect” を指定しているため四角形のバウンディングになります. 他に “circle” を指定して円形バウンディングにすることもできます.
this.setBoundingType("rect");
次に tm.util.Random.randint
というメソッドで 0 ~ 360 の間の乱数を生成しています.
この値を hsl に指定して自分の canvas を塗りつぶします.
hsl を使うことで簡単に彩度, 輝度を統一したカラフルな色を表現することができます. hsl について詳しく知りたいという方はこちらへ.
また, hsl 文字列を作る際に String.format
というメソッドを使っていますが, これも tmlib.js の機能です.
format
にオブジェクトを渡すことで {key} に対応した値に置換することができます.
python を踏襲した機能だったりします.
var angle = tm.util.Random.randint(0, 360); this.canvas.clearColor("hsl({0}, 80%, 70%)".format(angle));
最後に Label
を生成しています.
これを自分に追加することでテキストを表示することができます.
今回は引数として渡された数値を表示しています.
ちなみに addChildTo
は jQuery でいう apeend
と appendTo
の関係と同じようなもので
addChild
の逆方向版みたいなものです.
addChild
の場合複数行にまたがって書かなければいけないことになり
たまに実行し忘れたりするので addChildTo
を使うことをオススメします.
var label = tm.app.Label(); this.addChild(label);
↓同じ結果だけどこっちのほうがオススメ
var label = tm.app.Label().addChildTo(this);
tm.app.Label
には様々なプロパテイがありその値によって
表示するテキストが変化します.
主なプロパティ
fontSize
… フォントサイズfontFamily
… フォントファミリーalign
… アラインbaseline
… ベースライン
今回は align
に “center”, baseline
に “middle” を指定することで
ピースの真ん中に文字が表示されるようにしています.
this.label .setFontSize(70) .setFontFamily(FONT_FAMILY_FLAT) .setAlign("center") .setBaseline("middle");
ランダムな数値配列を作ろう
tmlib.js を読み込むことで Array
に range
, shuffle
というメソッドが追加されます.
range
は第一引数以上, 第二引数未満の数値配列を生成するメソッドです.
例えば [].range(1, 5)
と書くと [1, 2, 3, 4]
という内容の配列が生成されます.
これは Ruby を踏襲しています.
var nums = [].range(1, PIECE_NUM+1); // 1~25
shuffle
はその名の通り配列の中身をシャッフルしてくれるメソッドです.
// 数字配列 nums.shuffle(); // シャッフル
ピースを生成してシーンに追加しよう
ピースを定義しただけでは意味がありません.
Scene
で Piece
クラスを生成して追加しましょう.
// ピースを作成 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; } }
縦 x 横の数だけループを回してピースを生成しています. 今回は 5×5 なので 25 個のピースが生成されます.
生成されたピースを addChildTo
で pieceGroup
に追加します.
あとは i, j の値に応じてx,y 座標を少しずつずらして設定します.
これで画面上にピースが表示されます.
いっきに見た目が派手になりましたね.
ここまでで疑問に思ったことやエラーで動かないなどありましたら, 気軽に @phi_jpまでご連絡ください.
次回は, タッチ判定, クリア判定を実装します.
[…] Step01 ピースを定義して並べよう(今日中公開予定) (サンプル) […]
[…] Step01 ピースを定義して並べよう (サンプル) […]
[…] Step01 ピースを定義して並べよう (サンプル) […]
[…] Step01 ピースを定義して並べよう (サンプル) […]
[…] Step01 ピースを定義して並べよう (サンプル) […]
こんにちは。
サイトのサンプルで遊ばせてもらっています。
main.jsの前回との差分に、21行目が含まれていないようです。
遊んで頂いて嬉しいです:)
ご指摘ありがとうございます!!
早速修正しました.
今後ともよろしくお願いします.
おお、早速の対応おつかれさまです。
コメントにリアクションを貰えると嬉しいものですね。
しばらくtmlibで遊ばせてもらおうと思います:)
> var FONT_FAMILY_FLAT= “‘Helvetica-Light’ ‘Meiryo’ sans-serif”;
sans-serifがシングルクォートで囲まれてない様ですが、誤記でしょうか?(firefoxでデバッガ表示した時に警告が出てました)
お!?
必要ないという認識だったんですけどね.
firefox でも確認しておきますね.