スプライトシート
基本的なスプライトを理解したところで、それらを作成するより良い方法について説明します。それはSpritesheetクラスです。
スプライトシートは、スプライトをより効率的にダウンロードおよびレンダリングするためのメディア形式です。作成と使用がやや複雑になりますが、プロジェクトを最適化するための重要なツールです。
スプライトシートの構造
スプライトシートの基本的な考え方は、一連の画像を1つの画像にまとめ、各ソース画像がどこに収まるかを追跡し、その結合された画像を結果のスプライトの共有BaseTextureとして使用することです。
最初のステップは、結合したい画像を集めることです。スプライトパッカーは画像を収集し、新しい結合画像を作成します。
この画像が作成されると、それを構築するツールは、各ソース画像が格納されている矩形の場所を追跡します。次に、その情報を含むJSONファイルを出力します。
これらの2つのファイルは、組み合わせてSpriteSheetコンストラクターに渡すことができます。SpriteSheetオブジェクトは、JSONを解析し、ソース画像ごとに1つずつ、一連のTextureオブジェクトを作成し、JSONデータに基づいて各オブジェクトのソース矩形を設定します。各テクスチャは、ソースとして同じ共有BaseTextureを使用します。
二重の効率性
スプライトシートは、次の2つの方法でプロジェクトを支援します。
まず、ロードプロセスを高速化します。スプライトシートのテクスチャのダウンロードには同じ(またはわずかに多い!)バイト数の移動が必要ですが、それらは単一のファイルにグループ化されています。つまり、ユーザーのブラウザーは、同じ数のスプライトに対して、はるかに少ないファイルをリクエストしてダウンロードできます。ファイル数自体は、ダウンロード速度の重要な要因です。各リクエストにはWebサーバーへのラウンドトリップが必要であり、ブラウザーが同時にダウンロードできるファイル数には制限があるためです。プロジェクトを個々のソース画像から共有スプライトシートに変換すると、品質を損なうことなく、ダウンロード時間を半分に短縮できます。
次に、バッチレンダリングを改善します。WebGLレンダリング速度は、行われた描画呼び出しの数におおよそ比例します。複数のスプライトなどを単一の描画呼び出しにバッチ処理することは、PixiJSが驚くほど高速に実行できる主な秘密です。バッチ処理を最大化することは複雑なトピックですが、複数のスプライトがすべて共通のBaseTextureを共有している場合、それらをまとめてバッチ処理し、1回の呼び出しでレンダリングできる可能性が高くなります。
スプライトシートの作成
サードパーティツールを使用してスプライトシートファイルを組み立てることができます。ニーズに合う可能性のあるツールを2つ紹介します。
ShoeBox: ShoeBoxは、Adobe AIRベースの無料のスプライトパッキングユーティリティで、小規模なプロジェクトやスプライトシートの仕組みを学ぶのに最適です。
TexturePacker: TexturePackerは、高度な機能とワークフローをサポートする、より洗練されたツールです。PixiJS用のスプライトシートをパックするために必要なすべての機能を備えた無料版が利用可能です。大規模なプロジェクトやプロのゲーム開発、またはより複雑なタイルマッピング機能を必要とするプロジェクトに適しています。
スプライトシートデータは、手動またはプログラムで作成し、新しいAnimatedSpriteに提供することもできます。スプライトがすでに単一の画像に含まれている場合は、これがより簡単なオプションになる可能性があります。
// Create object to store sprite sheet data
const atlasData = {
frames: {
enemy1: {
frame: { x: 0, y:0, w:32, h:32 },
sourceSize: { w: 32, h: 32 },
spriteSourceSize: { x: 0, y: 0, w: 32, h: 32 }
},
enemy2: {
frame: { x: 32, y:0, w:32, h:32 },
sourceSize: { w: 32, h: 32 },
spriteSourceSize: { x: 0, y: 0, w: 32, h: 32 }
},
},
meta: {
image: 'images/spritesheet.png',
format: 'RGBA8888',
size: { w: 128, h: 32 },
scale: 1
},
animations: {
enemy: ['enemy1','enemy2'] //array of frames by name
}
}
// Create the SpriteSheet from data and image
const spritesheet = new Spritesheet(
Texture.from(atlasData.meta.image),
atlasData
);
// Generate all the Textures asynchronously
await spritesheet.parse();
// spritesheet is ready to use!
const anim = new AnimatedSprite(spritesheet.animations.enemy);
// set the animation speed
anim.animationSpeed = 0.1666;
// play the animation on a loop
anim.play();
// add it to the stage to render
app.stage.addChild(anim);