Posted at

PlainElementでCanvas描画

More than 1 year has passed since last update.


はじめに

この記事は、phina.js Advent Calendar 2016 の5日目の記事です。


phina.jsの描画機能

phina.jsの描画機能は、HTML5 Canvasがベースになっています。Canvasをある程度知っている人は、phina.jsを使ってみてピンと来るところがあると思います。加えて、phina.jsにはデフォルトのCanvasの機能を拡張したphina.graphics.Canvasというクラスが用意されており、デフォルトのメソッドに加え、簡単に線を描画できるdrawLineなど便利なメソッド群が追加で実装されています。

phina.jsCanvasのメソッドを使用したい場合は、phina.graphics.Canvasのインスタンスを作ってそこに描画する方法がありますが、多少手間がかかるところがありますので、今回は手軽にCanvasの機能が使えるPlainElementというクラスを紹介したいと思います。


PlainElementクラス

phina.display.PlainElementは、内部にCanvasクラスを持っているだけのシンプルなクラスで、Shapeの親クラスとして位置付けられています。

内部にCanvasを持っているので、Canvasで使えるメソッドは一通り使うことができます。


PlainElementクラスの使用例(簡単なお絵描き風プログラム)

お絵描きと呼べる程ではありませんが、今回は、マウスドラッグで線が引けるだけの簡単なサンプルを作ってみました。

コードは以下のとおりです。

phina.globalize();

// メインシーン
phina.define('MainScene', {
superClass: 'DisplayScene',
// コンストラクタ
init: function() {
// 親クラス初期化
this.superInit();
// 背景色
this.backgroundColor = 'black';
// canvas要素描画用
var elem = PlainElement({
width: this.gridX.width,
height: this.gridY.width,
}).addChildTo(this).setPosition(this.gridX.center(), this.gridY.center());
// canvasパラメータ指定
elem.canvas.context.strokeStyle = 'white';
elem.canvas.context.lineWidth = 4;
// 参照用
this.elem = elem;
},
// タッチ開始
onpointstart: function(e) {
// タッチされた位置を記憶
this.prev = Vector2(e.pointer.x, e.pointer.y);
},
// タッチ移動中
onpointmove: function(e) {
// 現在のタッチ位置を記憶
var current = Vector2(e.pointer.x, e.pointer.y);
// 前の位置から現在の位置まで線を引く
this.elem.canvas.drawLine(this.prev.x, this.prev.y, current.x, current.y);
// 前の位置を現在の位置に更新
this.prev = current;
},
// タッチ終了
onpointend: function() {
// 位置情報をクリア
this.prev = null;
},
});
// メイン
phina.main(function() {
var app = GameApp({
startLabel: 'main',
});
app.run();
});

[runstantで確認]


コード説明


PlainElementの追加

    // canvas要素描画用

var elem = PlainElement({
width: this.gridX.width,
height: this.gridY.width,
}).addChildTo(this).setPosition(this.gridX.center(), this.gridY.center());



  • PlainElementを作成して、Sceneに追加しています。

  • コンストラクでは、横と縦のサイズを指定します。今回は、画面と同じサイズにして重ねています。


canvasのcontext指定

// canvasパラメータ指定

elem.canvas.context.strokeStyle = 'white';
elem.canvas.context.lineWidth = 4;



  • PlainElement内部のCanvasには、canvasプロパティでアクセスできます。

  • ここではcanvascontextを経由して、線の色と幅を指定しています。


タッチ開始時処理

// タッチ開始

onpointstart: function(e) {
// タッチされた位置を記憶
this.prev = Vector2(e.pointer.x, e.pointer.y);
},


  • イベントからマウスが押された位置を取得します。

  • 線の始点の座標をVector2クラスを使って記憶します。


タッチ移動時処理

// タッチ移動中

onpointmove: function(e) {
// 現在のタッチ位置を記憶
var current = Vector2(e.pointer.x, e.pointer.y);
// 前の位置から現在の位置まで線を引く
this.elem.canvas.drawLine(this.prev.x, this.prev.y, current.x, current.y);
// 前の位置を更新
this.prev = current;
},


  • 現在のタッチ位置を線の終点として記憶します。


  • canvasdrawLineメソッドで線を引きます。

  • 最後の前の位置を現在の位置に更新します。


タッチ終了時処理

// タッチ終了

onpointend: function() {
// 位置情報をクリア
this.prev = null;
},


  • 線を引き終わった後は、始点の位置情報をクリアします。


補足

phinajsには他にPathShapeというクラスがあります。線の描画に特化したクラスで、座標値データ群を与えるだけでその点を結んだ線を自動で描画してくれる優れものです。こちらはまた別の機会に紹介したいと思います。


おわりに

phina.jsでゲームを作るときはSprite画像を使うことが多いかもしれませんが、上で説明したPlainElement、つまり、Canvasの機能を併用することで、よりゲームの表現性が増すのではないでしょうか。可能であれば、今回のアドベントカレンダーの期間内で簡単なサンプルゲームを作ってみたいと思います。