【Pixi.js】PNGファイルのアニメーション

Pixi.jsでアニメーションするだけ Pixi.js
Pixi.jsでアニメーションするだけ

はじめに

Pixi.jsについて学んだことの備忘録。
PNGファイルのアニメーションの動かし方について。

ここではPixi.jsのver4を使用しています。
最新版では書き方が全然違うため動かないため注意が必要です。

PNGファイルのアニメーション

5円はスルー、ボールは打つ!の制作時、ボールのアニメーションを作っていました。

ボールのアニメーション
ボールのアニメーション

ボールが回転する8枚の絵です。
Pixi.jsで動かすとこんな感じになります。

コードは下記のとおり。

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Asepriteアニメーション Pixi.js</title>
    <script src="../../pixi.min.js"></script>
</head>

<body style="margin: 0; overflow: hidden;">
    <script>
        // Pixi.jsのアプリケーションを作成
        const app = new PIXI.Application({
            width: 360,                 // 画面の横幅
            height: 548,                // 画面の縦幅
            backgroundColor: 0xcccccc,  // 背景色を設定
        })

        // appをbodyに追加
        document.body.appendChild(app.view);

        // loaderでファイルを読み込む
        PIXI.loader
            .add('spriteSheet', 'ball_a.png')   // PNG画像
            .load(onAssetsLoaded);              // ロード後に実行される処理

        // ロード後に実行される処理
        function onAssetsLoaded(loader, resources) {
            // スプライトシートのロード
            const textureArray = [];
            const frameWidth = 16;  // 1フレームあたりの横幅
            const frameHeight = 16; // 1フレームあたりの縦幅
            const totalFrames = 8;  // フレーム数

            // 1フレームずつ読み込んでtextureArrayに格納する
            for (let i = 0; i < totalFrames; i++) {
                textureArray.push(new PIXI.Texture(PIXI.Texture.from('spriteSheet').baseTexture, new PIXI.Rectangle(i * frameWidth, 0, frameWidth, frameHeight)));
            }
            // アニメーションの作成
            const sprite_a = new PIXI.Sprite(textureArray[0]);  // スプライトの定義
            sprite_a.x = 64;                // スプライトのx座標(左上だと見づらいかと思って少しずらした)
            sprite_a.y = 64;                // スプライトのy座標(左上だと見づらいかと思って少しずらした)
            sprite_a.scale.x = 2;           // スプライトの横幅の倍率(元の大きさは16だけど小さくて見づらいので2倍にした)
            sprite_a.scale.y = 2;           // スプライトの縦幅の倍率(元の大きさは16だけど小さくて見づらいので2倍にした)
            app.stage.addChild(sprite_a);   // 画面に追加

            // アニメーション(時間で更新)
            let currentFrame = 0;   // 現在フレーム番号
            const frameDelay = 100; // フレーム切り替えの間隔(ミリ秒)
            // 指定した間隔でアニメーション
            setInterval(() => {
                currentFrame = (currentFrame + 1) % totalFrames;    // 次のフレーム番号を設定(最大フレームを超えないように調整)
                sprite_a.texture = textureArray[currentFrame];      // スプライトに表示するフレーム番号を変更
            }, frameDelay);

        }
    </script>
</body>

</html>

アニメーションの関連処理だけ抜粋します。

0.pngファイルを読み込む
(「ball_a.png」を「spriteSheet」という名前で読み込み)

// loaderでファイルを読み込む
PIXI.loader
    .add('spriteSheet', 'ball_a.png')   // PNG画像

1.pngファイルの中身を定義する
ボールのアニメーション
この画像は16×16サイズの画像を8枚並べて1つのPNGファイルにしています。
そこで、PNGファイルを読み込むための情報を事前に定義します。

// スプライトシートのロード
const textureArray = [];
const frameWidth = 16;  // 1フレームあたりの横幅
const frameHeight = 16; // 1フレームあたりの縦幅
const totalFrames = 8;  // フレーム数

2.PNG画像を分解して1枚ずつ配列(textureArray)に格納する
画像の中に複数の絵があるため、1つずつ分解して配列に格納します。

// 1フレームずつ読み込んでtextureArrayに格納する
for (let i = 0; i < totalFrames; i++) {
    textureArray.push(new PIXI.Texture(PIXI.Texture.from('spriteSheet').baseTexture, new PIXI.Rectangle(i * frameWidth, 0, frameWidth, frameHeight)));
}

3.スプライトに画像を設定して画面に表示
PNG画像の一番左の絵をスプライトに設定しています。

// アニメーションの作成
const sprite_a = new PIXI.Sprite(textureArray[0]);  // スプライトの定義
app.stage.addChild(sprite_a);   // 画面に追加

4.時間経過でアニメーション
指定した時間ごとに呼ばれる関数を実行して、スプライトに設定する画像を順番に変更します。
これで、アニメーションしているように見えます。

// アニメーション(時間で更新)
let currentFrame = 0;   // 現在フレーム番号
const frameDelay = 100; // フレーム切り替えの間隔(ミリ秒)
// 指定した間隔でアニメーション
setInterval(() => {
    currentFrame = (currentFrame + 1) % totalFrames;    // 次のフレーム番号を設定(最大フレームを超えないように調整)
    sprite_a.texture = textureArray[currentFrame];      // スプライトに表示するフレーム番号を変更
}, frameDelay);

おわりに

凄くシンプルなPNGファイルのアニメーションでした。
今回は用意した画像を順番にアニメーションするだけのサンプルです。

応用すればRPGの主人公みたいに、向きによってアニメーションを変えることも可能です。
ただ、複数のアニメーションを制御するときには、JSONファイルを使うことが多いようです。
JSONファイルには、PNGファイルの絵の何番目が何の動きをするか、という定義をします。
プログラムはJSONファイルのアニメーション定義を指定するだけで済むので、何番目の絵が何の動きをするか覚えなくて済むので管理がしやすいとか。

まだアニメーションが必要なゲームを作っていないので、ここまでは試せていませんが。。。
いつか扱ってみたいですね。絵を描くのが面倒だからやりたくないかも…

おわり

コメント

タイトルとURLをコピーしました