tmlib.js で今流行のフラットデザインを使ったタッチゲームを作ろう – Step01 ピースを定義して並べよう

phiary に引っ越しました. 毎日プログラミングやWebに関する情報を発信しています! RSS 登録してたまに覗いたり, tweet やハテブして拡散してもらえると幸いです.

step01

Pocket

ピースクラスを定義して画面上に敷き詰めていきます.

いっきに見た目が派手になる楽しい Step です.

Table of contents

チュートリアル目次

前半

後半

up

サンプル

今回作るサンプルです.

画面にピースが敷き詰められているのがわかるかと思います.

up

ソースコード

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");
    },
});

up

解説

ピース用の定数を設定する

これも 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");
    },
});

superClasstm.app.Shape を指定することでこのクラスを継承しています.

init 内は色々とやっているので細かくみていきましょう.

まず親の初期化を superInit で呼びます.

this.superInit(PIECE_WIDTH, PIECE_HEIGHT);

次にタッチ判定が有効になるように setInteractivetrue を渡して実行しています.

this.setInteractive(true);

これでマウスやタッチに応じて pointingstartpointingmove, 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 でいう apeendappendTo の関係と同じようなもので 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 を読み込むことで Arrayrange, shuffle というメソッドが追加されます. range は第一引数以上, 第二引数未満の数値配列を生成するメソッドです.

例えば [].range(1, 5) と書くと [1, 2, 3, 4] という内容の配列が生成されます.

これは Ruby を踏襲しています.

var nums = [].range(1, PIECE_NUM+1);  // 1~25

shuffle はその名の通り配列の中身をシャッフルしてくれるメソッドです.

// 数字配列
nums.shuffle(); // シャッフル

ピースを生成してシーンに追加しよう

ピースを定義しただけでは意味がありません. ScenePiece クラスを生成して追加しましょう.

        // ピースを作成
        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 個のピースが生成されます.

生成されたピースを addChildTopieceGroup に追加します. あとは i, j の値に応じてx,y 座標を少しずつずらして設定します.

これで画面上にピースが表示されます.

up

いっきに見た目が派手になりましたね.

ここまでで疑問に思ったことやエラーで動かないなどありましたら, 気軽に @phi_jpまでご連絡ください.

次回は, タッチ判定, クリア判定を実装します.

TRACK BACK URL

POST COMMENT

メールアドレスが公開されることはありません。

COMMENT