困っていたこと
Pixi.jsでは、AnimatedSpriteというオブジェクトを用いることで、簡単にアニメーションする画像を表示できます。
ドット絵制作ソフトの「Aseprite」から生成されたファイルからでも生成が可能でゲーム開発にとても便利です。
しかし、再生速度は無視されてしまい、60fpsで毎回画像が更新されてしまいます。
これを何とかしましょう。
今回の解決方法はコマ送りが等速の場合のみ有効です。違う場合はtickerを使う必要が出てくるでしょう。
下準備
sample
├img
│ ├sample.aseprite
│ ├(sample.json)
│ └(sample.png)
├index.html
└index.js
ファイル構成はこんな感じ。
json,pngファイルの生成
まず、表示したい画像のasepriteファイル(sample.aseprite)からjsonファイルとpngファイルを生成します。
このサイトの「Exportする」までをやれば大丈夫です。
ソースを書く
<html>
<head>
<meta charset="utf-8" />
<title>pixi.js test</title>
<link rel="stylesheet" href="index.css" />
<!-- jQueryの読み込み -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<!-- pixi.jsの本体の読み込み -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/5.0.1/pixi.min.js"></script>
</head>
<body>
<main id="app">
<!-- ここに表示される -->
</main>
<script type="text/javascript" src="index.js"></script>
</body>
</html>
window.addEventListener('load', () => {
app = new PIXI.Application({
width: 600,
height: 600,
backgroundColor: 0x1099bb,
}); // global
$('#app').append(app.view);
app.loader.add('Piyo', './img/sample.json');
app.loader.load(setup);
});
function setup() {
let textures = app.loader.resources.Piyo.textures;
let textureArray = Object.keys(textures).map(id => textures[id]);
let sprite = new PIXI.AnimatedSprite(textureArray);
app.stage.addChild(sprite);
sprite.play();
}
この状態だと、画像は60fpsで毎回画像が更新されてしまいます。
解決方法
これを解消するためには、まず、元の再生速度を取得する必要があります。
Asepriteでの再生速度は、jsonファイルにちゃんと記録されています。
{ "frames": {
"sample 0.aseprite": {
"frame": { "x": 0, "y": 0, "w": 32, "h": 32 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
"sourceSize": { "w": 32, "h": 32 },
"duration": 100 // ←これ。単位はms
},
...
}
次にsprite.animationSpeedをいい感じにいじる必要があります。
これは、値が1のとき1フレームに1回、0.1のとき10フレームに1回と、間隔フレーム数の逆数を指定する必要があります。
このdurationの値をtとすると、60*(t/1000)が間隔フレーム数です。
よって、約分して指定するのは、50/(3*t)となります。
修正後のコードは、
...
function setup() {
let textures = app.loader.resources.Piyo.textures;
let textureArray = Object.keys(textures).map(id => textures[id]);
$.ajaxSetup({async: false});
$.getJSON('./img/sample.json', (jsonData) => {
textureArraySpeed = 50 / (3 * jsonData.frames['sample 0.aseprite'].duration);
});
$.ajaxSetup({async: true});
let sprite = new PIXI.AnimatedSprite(textureArray);
app.stage.addChild(sprite);
sprite.animationSpeed = textureArraySpeed;
sprite.play();
}
となります。
以上!!