PixiJSはWebGLというブラウザでも高速に画像を描画できる技術を使えるライブラリです。
この記事では初めてPixiJSを使うときに知っておきたい基本的な使い方を一通り駆け足で解説します(ついでにpixi-sound.jsも)。
筆者はPixiJSを使ったゲーム制作をしているのでゲーム制作に興味のある方はこちらの記事も読んでみてください。
作ったゲームはこちらのサイトで公開しています。
目次
まずはindex.htmlを用意
index.htmlはこんな感じで。プログラムはmain.jsに書いていきます。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <script src="pixi.min.js"></script> <script src="pixi-sound.js"></script> <script src="main.js"></script> </head> <body> </body> </html>
この記事で使っているpixi.jsはバージョン5.3.7、pixi-soundはバージョン4.0.4です。
入手先はこちら ▷ pixi.js ▷ pixi-sound.js
※違うバージョンでは仕様が異なっていて記事の説明と違うところがある場合があります。
PixiJSの表示画面を作る
まずpixi.jsで画面を作ります。
window.onload = () => { const app = new PIXI.Application({ width: 600, height: 600, backgroundColor: 0x222222, resolution: 1, autoDensity: true }); document.body.appendChild(app.view); }
画面解像度と背景色、あと解像度系の謎プロパティを指定して画面を作ります。他にもプロパティがあるようですがとりあえずこれだけあればOK。
画面ができると同時にapp.stageという場所が作られていて画面に表示したいものはこのapp.stageに入れていきます。app.stage.addChild(表示したいもの)とすると画面に表示されます。
PixiJSの文字表示について
とりあえずお約束のHello World!。
const style = new PIXI.TextStyle({ fontFamily: 'sans-serif', fontSize: 32, fill: 0xffffff, fontWeight: 'bold', stroke: 0xFF0000,//縁取りの色 strokeThickness: 4,//縁取りの太さ }); const p = new PIXI.Text("Hello World!", style); p.anchor.set(0.5, 0.5); p.position.set(300, 300); app.stage.addChild(p);
PIXI.TextStyleで色や大きさなどを指定します。たくさんプロパティがあるので詳しくはドキュメントを見てください ▷ PIXI.TextStyle
PixiJSのロード方法いろいろ
画像などを使う場合はファイルを読み込む必要があります。pixi.jsでは読み込みの方法がいくつかあります。
必要な時に読み込む
一枚の画像を読み込んで表示したいとき。
const texture = new PIXI.Texture.from('player.png'); const player = new PIXI.Sprite(texture); app.stage.addChild(player);
まとめてロード1
たくさん読みこむ必要がある場合はまとめてロードできます。
PIXI.Loader.shared .add('player.png') .add('item.png') .load(() => { const texture = PIXI.Loader.shared.resources['player.png'].texture; const player = new PIXI.Sprite(texture); app.stage.addChild(player); });
読み込みが終わるとload()が実行されます。
使うときはPIXI.Loader.shared.resourcesにデータが入っているのでファイル名で指定して使いまます。
まとめてロード2
こちらは読みこむデータに名前を付けるやり方です。
PIXI.Loader.shared .add('player', 'player.png') .add('item', 'item.png') .load(() => { const texture = PIXI.Loader.shared.resources['player'].texture; const player = new PIXI.Sprite(texture); app.stage.addChild(player); });
まとめてロード3
まとめてロード1の変化版。配列で渡すやり方です。
const assets = [ 'player.png', 'item.png' ]; PIXI.Loader.shared.add(assets).load(() => { const texture = PIXI.Loader.shared.resources['player.png'].texture; const player = new PIXI.Sprite(texture); app.stage.addChild(player); });
まとめてロード4
名前を付けるやり方の便利な方法。
const assets = { player: 'player.png', item: 'item.png' }; for (let name in assets) { PIXI.Loader.shared.add(name, assets[name]); } PIXI.Loader.shared.load(() => { const texture = PIXI.Loader.shared.resources['player'].texture; const player = new PIXI.Sprite(texture); app.stage.addChild(player); });
PixiJSのSpriteクラスについて
画像ファイルなどを表示するときに使うクラスです。
読みこんだ画像データはPIXI.Loader.shared.resourcesにあります。画像データを使う場合は[○○].textureになります。
画像をそのまま表示
ロードした画像をそのまま表示します。
const texture = PIXI.Loader.shared.resources['player.png'].texture; const player = new PIXI.Sprite(texture); app.stage.addChild(player);
好きな大きさに切り取って表示
画像の好きな場所から好きな大きさで切り取って表示できます。
const texture = PIXI.Loader.shared.resources['player.png'].texture; const frame = new PIXI.Texture(texture, new PIXI.Rectangle(0, 0, 32, 32)); const player = new PIXI.Sprite(frame); app.stage.addChild(player);
PIXI.Rectangle(x, y, 幅, 高さ)で指定します。
PIXI.Texture(切り取りたいテクスチャー, PIXI.Rectangle(x, y, 幅, 高さ))で新しいテクスチャーを作ります。
JSONファイルを使う
jsonファイルに必要な情報を用意してそれに従って画像を切り取って表示します。
{ "frames": { "player-0": { "frame": { "x": 0, "y": 0, "w": 32, "h": 32 } }, "player-1": { "frame": { "x": 32, "y": 0, "w": 32, "h": 32 } } }, "meta": { "image": "player.png", "format": "RGBA8888", "size": { "w": 256, "h": 64 }, "scale": 1 } }
上のような感じに位置と大きさを指定したjsonファイルを作成します。
const assets = [ 'player.json', 'item.png' ]; PIXI.Loader.shared.add(assets).load(() => { onload();//読み込み完了でonload()実行 }); const onload = ()=>{ const texture = PIXI.Loader.shared.resources['player.json'].textures['player-1']; const player = new PIXI.Sprite(texture); app.stage.addChild(player); }
この場合はjsonファイル内のデータを見て画像ファイルを自動で読み込みこんでいるようなので画像ファイルを読み込む必要はありません。
PIXI.Loader.shared.resources['player.json'].textures['player-1']
のようにtextures[表示したい部分の名前]でjsonで指定した部分の画像が表示されます。
jsonファイルはお絵かきソフトの機能(asepriteにあるらしい?)をつかったり、作成ツールをググって作ってください(上の例のように書けば手書きでも一応できます)。
さらにSpriteの私なりの独自の使い方はこちらの記事に書いてあります。
PixiJSのプロパティいろいろ
Sprite、Containerなどのプロパティはだいたい共通しています。とりあえず良く使いそうなものだけ。
- x, y ・・addChildした先との相対座標。position.set(10, 10)という書き方もある。
- scalse・・拡大率。x方向・y方向がある。マイナスは反転
- anchor(Spriteのみ)・・・表示の際のスプライトの基準位置。(0, 0)だと画像の左上、(1, 1)で右下
- pivot・・anchorと同じ。ただしこれは座標で指定。
- rotation・・・回転。単位はラジアン
- width、height・・・幅、高さ
- visible・・・trueで表示、falseで非表示
- alpha・・・透明度。1で見える、0で見えなくなる
説明が抜けてましたがPIXI.Containerは入れ物みたいなものでこれ自体は見えませんが複数のSpriteをひとまとめにしたいときなどに使います。
UIなどをContainerに入れて配置するとContainerを移動させるとContainer内での配置を保ったまま移動させることができます。
PixiJSの画面更新処理について
アニメーションさせたり、ゲーム作ったりするときに必要な自動更新処理を行ってくれるようにします。
app.ticker.add((delta) => { //ここに処理を書く });
または
app.ticker.add(update); function update(delta){ //ここに処理を書く }
60FPS(1秒間に60回)で処理を実行してくれます。
PixiJSのタッチイベントについて
pixi.jsでのタッチイベントの使い方は
abcde.on('pointerup', () => { //処理 });
のようにonメソッドでイベント名を指定してコールバック処理を書けばそのイベントが発生したときに処理を行ってくれます。
interactiveをtrueにする
タッチイベントを使うには対象オブジェクトのinteractiveプロパティをtrueにする必要があります。
これを設定し忘れるとタッチイベントを作っても動いてくれません。
「あれぇ?なんで動かんのや?」ってときはだいたいこれを忘れています。
pointerでつくればPCもスマホもいける
pixi.jsではかなりたくさんのタッチ/マウスに関するイベントがあります。
参考 ▷▷▷ PIXI.interaction.InteractionManager
mousedownやtouchstartなどマウス・スマホ用にイベントがありますが、基本的にpointerで指定すればPCでもスマホでも動きます。
pointerdown、pointermove、pointerupを基本的に使っていけばOKです。
ただしpointermoveはPCの場合pointerdownしてようがしてなかろうが関係なしにマウスを動かせば発火するので押しているだけを判別して動かすには押している状態を管理するフラグが必要です。
スマホではpointeroutが効かない
対象のオブジェクトからポインターが外れたときに発生するpointeroutが残念ながらスマホでは使えないようです。
そして残念ながらtouchoutというものもないようです。
なのでスマホの場合はtouchmoveで動かした位置が対象のオブジェクトの大きさより外側になっているかをチェックして外側に出ていたら処理を行うようにする必要があります。
他にもpointerイベントでスマホでは動かないものがあるようです。
タッチの座標を取得
タッチの座標などの情報は下記のような感じに取得できます。
this.on('pointerdown', (event) => { const pos = event.data.getLocalPosition(event.currentTarget); ball.postion.set(pos.x, pos.y); });
getLocalPositionは引数に指定した要素上の座標になります。だいたいはタッチしたもの(event.currentTarget)か、もしくはその親(event.currentTarget.parent)の座標を取得することになると思います。
パブリングに注意
javascriptのタッチなどのイベントにはバブリングという機能があります。
これは例えばオブジェクトをタッチしたときにそのタッチで起こるイベントがそのタッチしたオブジェクトだけでなくそのオブジェクトの親オブジェクトでもイベントが起こる現象です。
もうちょっと具体的な例としては、例えば画面をタッチしたらキャラがジャンプするようにしていて、その画面の上にポーズボタンを作っていた場合、このポーズボタンを押すとキャラもジャンプしてしまう現象です。ポーズだけしてくれればいいのにキャラがジャンプしてしまう現象が起こります。
これの対処法は
pauseBtn.on("pointerdown", (e) => { e.stopPropagation();//eventの伝搬を止める //ボタンの処理 });
e.stopPropagation()を書いておくと親への伝搬を止めることができます。
Containerのタッチイベント
画面をタッチして動かす場合にPixi.ContainerにイベントをつけたいところですがContainerだけではタッチイベントは機能しないみたいです。
Containerにタッチイベントを仕込みたい場合はSpriteを画面の幅・高さに作ってaddChildしてやるとSpriteからのバブリングで使うことができます(画像は無しでもOK)。
マルチタッチについて
pixi.jsのマルチタッチについてはこっちの記事にまとめてあるので気になる方はどうぞ(‘ω’)ノ
PIXI-SOUNDで音の再生
pixi-soundもロードは上の例と同じようにできます。
読みこんだデータは同様にPIXI.Loader.shared.resourcesにあって、こっちは後ろに.soundをつけて扱います。.soundの後にプロパティかメソッドをつけて扱います([○○].sound.play()みたいな感じ)。
もしくはPIXI.soundという場所にもあるのでPIXI.sound.play(ファイル名)でも扱えます。
- loop・・trueにするとループします
- volume・・音量
- play()・・再生
- pause()・・ポーズ
- resume()・・再開
- stop()・・停止
より詳しく知りたい方は公式ページをどうぞ ▷ PixiSound Basics