はりうすブログ (のすけのメモ)

湘南にある小さな会社 代表 ”のすけ”のブログです

babylon.js ステップ13 スプライト(Sprites)

babylon.js ステップ13はスプライトアニメーションです。

2Dではおなじみのこの技術。

もちろんbabylon.jsでも使えます


いきましょう!

2つのスプライト管理方法

スプライトは大量の2D画像を利用するため、パフォーマンス管理が重要です。

babylon.jsでは2つの管理方法があります

  • A uniform spritesheet (均一化されたスプライト)・・・SpriteManagerを利用
  • A packed spritesheet(パッケージされたスプライト)・・・SpritePackedManagerを利用

これらは、1枚のスプライトであってもManagerを使う必要があります。

スプライトマネージャー

f:id:hollywis:20200708221747p:plain

// 木の画像用のsprite managerの作成
var spriteManagerTrees = new BABYLON.SpriteManager("treesManager", "Assets/Palm-arecaceae.png", 2000, 800, scene);

treesManagerの部分は名前なのでユニークな名前を設定します。

「Assets/Palm-arecaceae.png」の木の画像を最大2000個作ることができる容量を確保します。

800の部分は画像のサイズに対応するセルサイズです。

最後に追加するsceneを設定します。

// プレイヤー用のsprite managerの作成
var spriteManagerPlayer = new BABYLON.SpriteManager("playerManager","Assets/Player.png", 2, {width: 64, height: 64}, scene);

上記では、セルサイズを[64x64]で設定しています。

f:id:hollywis:20200708221724p:plain

Picking(ピッキング)

次はピッキング(選択)を行います

完成図
https://www.babylonjs-playground.com/#9RI8CG#0

やり方

  • 必要なスプライトの選択をオンにします。 sprite.isPickable = true;
  • SpriteManagerがピッキングをサポートできるようにします。 spriteManager.isPickable = true;
// 選択されたスプライトを傾ける
var pickResult = scene.pickSprite(this.pointerX, this.pointerY);
if (pickResult.hit) {
    pickResult.pickedSprite.angle += 0.5;
}

sceneのpickSprite関数を使って、マウスポインタの選択を取得します。

そして、それがhit(衝突)している場合(ほぼ間違いなくhitしていますが)、スプライト画像を傾けます

multiPickSpriteを使用して、貫通系の複数選択も可能です

var pickResult = scene.multiPickSprite(this.pointerX, this.pointerY);
for (var i = 0; i < pickResult.length; i++) {
        pickResult[i].pickedSprite.angle += Math.PI / 4;
}

スプライトパックマネージャー(バージョン4.1から利用可能)

パックされたスプライトシートを用いる場合は、SpritePackedManagerを利用します

これは、JSONファイル(位置を含む)と画像ファイルが必要です。

// SpritePackedManager(名前,画像,インスタンス最大数,シーン)
var spm = new BABYLON.SpritePackedManager("spm", "pack1.png", 4, scene);

画像の例は次のような感じです。1枚の画像データに複数の画像を詰め込みます

f:id:hollywis:20200709010213p:plain

jsonファイルの中身はこんな感じで、その画像の始まりの座標と、横幅、縦幅でできています。

{   "frames": {
        "eye.png": {
            "frame": {"x":0,"y":148,"w":400,"h":400}
        },
        "redman.png": {
            "frame": {"x":0,"y":0,"w":55,"h":97}
            },
        "spot.png": {
            "frame": {"x":199,"y":0,"w":148,"h":148}
        },
        "triangle.png": {
            "frame": {"x":55,"y":0,"w":144,"h":72}
        }
    }
}

1枚の画像なのに、擬似的に複数の画像として扱うことができます。

var sprite = new BABYLON.Sprite("sprite", spm);
sprite.cellRef = "spot.png";

そして、このように該当画像を選んで使用できます

スプライトの設定

sprite.size = 0.3;  //大きさ
sprite.angle = Math.PI/4; //向き
sprite.invertU = -1; // 反射
sprite.width = 0.3; //幅
sprite.height = 0.4; //高さ
sprite.position.y = -0.3; //ポジション

スプライトアニメーション方法

スプライトの利点のアニメーションが簡単な事です。

均一なスプライトシートと(SpriteManager)を使用することです。

すべてのアニメーション画像を含む1つの大きな画像ファイルを次々にロードします。

マネージャーで指定したピクセルサイズは均一であることに注意してください。


たとえば、次のプレーヤーのスプライトシートでは、40以上のアクションを定義しています

f:id:hollywis:20200709011136p:plain

使い方:

// フレーム0からフレーム43までアニメーション化
// trueはループするかどうか
// 100はフレーム間の遅延時間
player.playAnimation(0, 43, true, 100);

実行例はこちら
https://www.babylonjs-playground.com/#9RI8CG

スプライトマップ

数千以上のアニメーションが必要な場合にはスプライトマップの利用を検討してください

spriteMapを利用すると情報をメモリに保存して高速な演算を可能にするようです。

var spriteMap = new BABYLON.SpriteMap(name, atlasJSON, spriteTexture, options, scene);

タイル表現に便利なスプライトマップタイル

マインクラフトの如く、同じサイズのタイルを使いたい場合にはスプライトマップタイルが便利です。

spriteMap.changeTiles(layerID, tileID, frameID)
  • layerID:システムのターゲットレイヤーの整数。
  • tileID:Vector2 | レイヤーのターゲットタイルのVector2 []。
  • frameID:変更するスプライトの整数フレームID。


タイル情報の保存やロード、アニメーション機能などもあります

spriteMap.saveTileMaps() // セーブ .tilemaps形式
spriteMap.saveTileMaps(url) //ロード


// アニメーション
spriteMap.addAnimationToTile(frameID, animationFrame, nextFrameID, animationFrameDisplayTiming, globalSpeed)

例はこちら
https://playground.babylonjs.com/#ARLADE

まとめ

スプライト表現について学びました。


babylon.jsでスプライト表現を行うためにはManagerを使う必要があり、全て同じピクセルの画像ならば、SpriteManagerで、異なるサイズの画像を扱うなら SpritePackedManagerを使います。


マネージャを定義したなら、Spriteインスタンスをnew BABYLON.Spriteで呼び出し
メッシュのように自由にサイズや位置などを設定できます。


また、アニメーションを使う場合にはplayAnimation関数でできました。


タイル表現には、SpriteMapが便利であることを学びました。


以上になります。

次回はパーティクル表現をやります!