目次
スプライトシートアニメーションの基本的な手順
アニメーションの表現では、たとえばゲームキャラクターの動きなどに”スプライトシート”がよく使用されます。スプライトシートとは、動かしたいアニメーションの全フレーム(コマ)を1枚の画像として用意し、プログラミングから各コマを順番に”切り出して”高速に切り替えて描画することで、アニメーションに見せる方法を言います。下図は「Segel Artwork」からダウンロードしたPNG形式のスプライトシートです。
p5.jsのキャンバスに、p5.play.jsを使ってスプライトシートアニメーションを描画する基本的な手順は次の通りです。
- スプライトシートアニメーションに使用するPNG画像を用意する。
- p5.jsのpreload()関数で、p5.play.jsのloadSpriteSheet()を使ってスプライトシート画像を読み込み、その結果をloadAnimation()に渡す。
- 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);
}
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()に渡します。