2_2:p5.play スプライトシート アニメーションの基本

スプライトシートアニメーションの基本的な手順

アニメーションの表現では、たとえばゲームキャラクターの動きなどに”スプライトシート”がよく使用されます。スプライトシートとは、動かしたいアニメーションの全フレーム(コマ)を1枚の画像として用意し、プログラミングから各コマを順番に”切り出して”高速に切り替えて描画することで、アニメーションに見せる方法を言います。下図は「Segel Artwork」からダウンロードしたPNG形式のスプライトシートです。

p5.jsのキャンバスに、p5.play.jsを使ってスプライトシートアニメーションを描画する基本的な手順は次の通りです。

  1. スプライトシートアニメーションに使用するPNG画像を用意する。
  2. p5.jsのpreload()関数で、p5.play.jsのloadSpriteSheet()を使ってスプライトシート画像を読み込み、その結果をloadAnimation()に渡す。
  3. p5.jsのdraw()関数で、p5.play.jsのanimation()を使って、アニメーションを表示する。

次のコードは、上記バードモンスターのスプライトシート画像を使って、スプライトシートアニメーションを表示します。

// スプライトシートからアニメーションを作成する
let spriteSheetAnim;

function preload() {
    // 1078 x 104 イラストは8個 1078 / 8 = 134.75
    // 各フレームの幅と高さ、フレーム数を指定して、スプライトシートを読み込む
    const spriteSheet = loadSpriteSheet('assets/monster_fly.png', 134.75, 104, 8);
    // アニメーションを読み込む
    spriteSheetAnim = loadAnimation(spriteSheet);
}

function setup() {
    createCanvas(500, 300);
}

function draw() {
    background(200)
        // スプライトシートアニメーションを表示する
    animation(spriteSheetAnim, 250, 150);
}

Segel Artwork

p5.play.loadSpriteSheet()を呼び出すときには、スプライトシート画像のほかに、描画するフレーム(コマ)の幅と高さ、これを1周とするフレーム数を指定します。

 loadSpriteSheet('assets/monster_fly.png', 134.75, 104, 8);

上図で示したmonster_fly.pngの幅は1078ピクセルで高さは104ピクセルです。またモンスターバードは8個描かれているので、最大で8フレームを1周とするフレーム数が指定できます。フレームの幅は、全幅をフレーム数で割って算出します(1078 / 8 = 134.75)。

リファレンスメモ
p5.play.loadSpriteSheet()

loadSpriteSheet ()
フレームの幅と高さ、フレーム数を指定して、スプライトシートを読み込む。通常はスケッチのpreload()関数内で使用する。

JSONデータを使ったスプライトシートアニメーション

loadSpriteSheet()にはまた、各フレームの情報を定義したJSONデータを渡すこともできます。JSONデータは、次の構造で作成し、拡張子.jsonをつけて保存します。

[
  {
    "name": "m000.png",	// フレーム名
    "frame": {		// フレーム情報
      "x": "0",		// 切り出すフレームの左上隅のx座標
      "y": "0",		// 切り出すフレームの左上隅のy座標
      "width": "106",	// 切り出すフレームの幅
      "height": "106"	// 切り出すフレームの高さ
    }
  },
  {
    "name": "m001.png",
    "frame": {
      "x": "115",
      "y": "0",
      "width": "106",
      "height": "106"
    }
  }
]

下図は次のサンプルで使用しているexplosion.pngファイルで、上記JSONデータの2つめのフレームを図示したものです。p5.playはこの情報を元に、explosion.pngの左上隅を原点として、点(115,0)を左上隅とする幅106、高さ106のフレーム用画像を切り出し、フレーム1のイメージとします。今の場合、フレームは正方形(106 x 106)ですが、長方形でも構いません。

次のコードは、explosion.jsonのフレーム情報を元に、explosion.pngから8個のフレーム用イメージを切り出し、スプライトシートアニメーションを表示します。

let spriteSheetAnim;

function preload() {
    loadJSON('assets/explosion.json', (framesDataJSON) => {
        const spriteSheet = loadSpriteSheet('assets/explosion.png', framesDataJSON);
        spriteSheetAnim = loadAnimation(spriteSheet);
    });
}

function setup() {
    createCanvas(500, 300);
}

function draw() {
    background(200)
        // スプライトシートアニメーションを表示する
    animation(spriteSheetAnim, 250, 150);
}
[
  {
    "name": "m000.png",
    "frame": {
      "x": "0",
      "y": "0",
      "width": "106",
      "height": "106"
    }
  },
  {
    "name": "m001.png",
    "frame": {
      "x": "115",
      "y": "0",
      "width": "106",
      "height": "106"
    }
  },{
    "name": "m002.png",
    "frame": {
      "x": "233",
      "y": "0",
      "width": "106",
      "height": "106"
    }
  },{
    "name": "m003.png",
    "frame": {
      "x": "357",
      "y": "0",
      "width": "106",
      "height": "106"
    }
  },{
    "name": "m004.png",
    "frame": {
      "x": "0",
      "y": "125",
      "width": "106",
      "height": "106"
    }
  },{
    "name": "m005.png",
    "frame": {
      "x": "120",
      "y": "125",
      "width": "106",
      "height": "106"
    }
  },{
    "name": "m006.png",
    "frame": {
      "x": "237",
      "y": "125",
      "width": "106",
      "height": "106"
    }
  },{
    "name": "m007.png",
    "frame": {
      "x": "360",
      "y": "125",
      "width": "106",
      "height": "106"
    }
  }
]

p5.jsのpreload()関数では、p5.jsのloadJSON()関数の第2引数にコールバック関数を渡しています((framesDataJSON) => { から }まで)。これは、.jsonファイルの解析に時間がかかるので、それを待つ必要があるからです。

function preload() {
  loadJSON('assets/explosion.json', (framesDataJSON) => {
    const spriteSheet = loadSpriteSheet('assets/explosion.png', framesDataJSON);
    spriteSheetAnim = loadAnimation(spriteSheet);
  });
}

コールバック関数には引数として解析後のJSONデータが渡されるので、それをそのままloadSpriteSheet()に渡します。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA