こんにちは! Nike大好き!ダンサー兼フロントエンドエンジニアのシスコです。
我が足は常にNikeと共にあり!というくらい毎日大切に履かせてもらってます。ダンスシューズもNikeに変えたら前より調子よいのです……。
それはさておき、今回はJavaScriptゲームライブラリであるphina.jsというのを一緒に触っていきましょう!!導入方法や基本的な操作の部分を説明できればと思います!
phina.jsとは?

ゲームやツールなどを作れるJavaScript製のゲームライブラリです。PC, スマホ両方に対応しており、簡単にゲームが作れるみたいです!
また、国産なので日本語のリファレンスがあるというのも、これから初める人には優しくなっているところかもしれませんね。
使うための下準備
任意のhtmlファイルのhead内に下記のコードを追記してください。
<script src="phina.min.js"></script>
続いてphina.jsで実行するjsファイルを作成し、下記のコードを追加しましょう!
// app.js
// phina.js をグローバルに展開
phina.globalize();
// MainScene を定義
phina.define('MainScene', {
    superClass: 'CanvasScene',
    init: function() {
        this.superInit();
        this.backgroundColor = '#185674'; // 任意の背景色
    }
});
// メインの処理
phina.main(function() {
    // アプリケーションを生成
    var app = GameApp({
        startLabel: 'main'
    });
    app.run();
});
これが終わったら、一度お手元のブラウザで動いているかどうか確認してみましょう!
背景色として設定した、色のCanvasが表示されていれば成功です!
phina.js スタートアップ
下準備が完了したので、phina.jsを使うための基礎的な部分をいくつか説明したいと思います!
ラベルの表示
ゲームスタートやゲームオーバー、リザルト画面などのテキスト表示によく使えると思います。
var label = Label('表示させたいテキスト').addChildTo(親要素);
上記の書き方によってラベルをつ表示させることができます。
さきほど作成した、jsファイルのメインシーン部分に追加してみましょう!
// 省略
--------------------------------------
    // MainScene を定義
    phina.define('MainScene', {
        superClass: 'CanvasScene',
        init: function() {
            this.superInit();
            this.backgroundColor = '#185674'; // 任意の背景色
            var x_grid = this.gridX; // x座標
            var y_grid = this.gridY; // y座標
        // ラベルを生成
        var label = Label({
            text: 'Hello!!, Get strat phina.js!',
            fill: 'white',
            fontSize: 40
        }).addChildTo(this);
        label.setPosition(x_grid.center(),y_grid.center()); // 上下左右センタリング
            }
        });
    // メインの処理
    phina.main(function() {
    --------------------------------------
    // 省略
先ほどのCanvasに指定したテキストが出てきていれば大丈夫です!
Labelというクラスの中には、fill, fontSize, strokeといった指定も可能になっています。
図形の描写、画像の表示
デフォルトで様々な図形も描写できます! また、画像の表示も容易にできます。
図形の描写
図形を描写させるためのコード
var shape = デフォルトの図形クラス(options).addChildTo(親要素);
使用できるデフォルトで図形のクラスは下記のようなものがあります!
- CircleShape: 円
 - RectangleShape: 四角形
 - TriangleShape: 三角形
 - StarShape: 星形
 - PolygonShape: 多角形
 - HeartShape: ハート型
 
それぞれオプションも付けつつ、表示させてみましょう!
ラベルのときと同様にMainscene部分に記述しましょう。
// 図形の描写
   var circle = CircleShape({
        fill: 'yellow',
        radius: 50
   }).addChildTo(this);
   circle.setPosition(x_grid.center(-4), y_grid.center(-2));
    var rect = RectangleShape({
        fill: 'green',
        stroke: '#fff',
        width: 100,
        height: 100
    }).addChildTo(this);
    rect.setPosition(x_grid.center(), y_grid.center(-2));
    var triangle = TriangleShape({
        backgroundColor: 'gray',
        fill: 'red',
        width: 80,
        height: 80
    }).addChildTo(this);
    triangle.setPosition(x_grid.center(4), y_grid.center(-2));
    var star = StarShape({
        stroke: 'gold',
        sideIndent: 0.7
    }).addChildTo(this);
    star.setPosition(x_grid.center(-4), y_grid.center(2));
    var polygon = PolygonShape({
        fill: '#66ffcc',
        sides: 5
    }).addChildTo(this);
    polygon.setPosition(x_grid.center(), y_grid.center(2));
    var heart = HeartShape({
        fill: '#ff82b2',
        cornerAngle: 30
    }).addChildTo(this);
    heart.setPosition(x_grid.center(4), y_grid.center(2));
画像が実行したときの表示になります。

画像の表示
画像を表示させるコード
画像や音楽などは、GameAppを作成するときに同時に渡すことができます。
var app = GameApp({
    startLabel: 'main',
    assets: img // アセット名はなんでもよい
});
表示させたい画像などを[キー名: 読み込みたいアセットのパス]のように指定させる
// 例
var img = {
    image: {'キー名': '読み込みたいアセットのパス'}
};
その後、Mainscene内で
var usagi = Sprite('usagi').addChildTo(this); // ('usagi')内が指定したキー名に相当する
usagi.setPosition(x_grid.center(), y_grid.center());
usagi.width = 240;
usagi.height = 240;
このように記述して読み込みたい画像が表示されてくれればOKです!!
ちょっとした動きをつけてみよう!
要素の移動や回転などの動きをつけてみたいと思います。
要素の移動
移動させたい要素のupdate変数に関数をつけることで簡単に動かす処理ができます!
先ほど表示させた画像に上下移動させる動きをつけたいと思います!(図形とかでも全然構わないです。)
// 画像の表示
        var usagi = Sprite('usagi').addChildTo(this);
        usagi.setPosition(x_grid.center(), y_grid.center());
        usagi.width = 150;
        usagi.height = 150;
        // 移動する速度
        usagi.speed = 15;
        // 動かす処理
        usagi.update = function() {
            this.y += this.speed;
            // 指定範囲からはみ出さないように
            if(this.top <= 300) {
                this.top = 300;
                this.speed *= -1;
            } else if(this.bottom >= 550) {
                this.bottom = 550;
                this.speed *= -1;
            }
        }
usagi.update変数の記述以下が追加したコードになります。
これを実際にブラウザで見てみた結果がこれです…!

rotationプロパティを使用して回転を加えるとこうなります…。
なんとも気持ち悪いですね…!(笑)

イベントをつけてみよう!
今回は、タッチ系のイベントを発火させてみましょう。
el.setInteractive(true);
このように指定することで、タッチ系のイベントを有効にすることができます。
下に書いてあるようなイベントを登録することができます!
// タッチ開始時
el.onpointstart = function() {
}
// タッチ移動時
el.onpointmove = function() {
}
// タッチ終了時
el.onpointend = function() {  
}
// 複数登録も可能
el.on('pointstart', function() {  
});
タッチイベントを適用させたデモです!

画像のランダム表示は結構難しかったです。。。
当たり判定をしてみる!
ゲームといえば当たり判定はつきものですね!
難しいと思うことなく、比較的簡単に当たり判定を実装できちゃいます!
hitTestElement()を使うことによって、他要素との当たり判定を行えるようになります。
// あたり判定コード 例
var a;
var b;
if(a.hitTestElement(b)) {
  // 当たったときの処理
}
当たり判定のデモです。

TweenAnimationをつけてみる!
tweenerというプロパティを使用することで要素にアニメーションを付け加えることができます。
面白いところだと思うので、一緒にやってみましょう!
Tweenアニメーションは下記のコードで適用されます!
el.to({y: 200}, 5000, 'easeOutElastic') // y軸を5秒かけて200に変化
先ほどの当たり判定のデモを編集してジャンプモーションとBoxに当たったときのTweenerアニメーションを追加してみました!

まとめ
phina.jsいかがでしたか?
そこまで複雑なコードを書かなくても、簡単にアニメーションや動きをつけられるのはすごいですよね!!
少しでも面白そうだなって思った人は、ぜひ使ってみてください! やってて楽しいですよ!
今回は基本編でしたが、もうちょっと応用の部分も紹介できたらと思います。
それでは、これにてっ!
LIGはWebサイト制作を支援しています。ご興味のある方は事業ぺージをぜひご覧ください。