スプライトには複数のアニメーションを追加することができ、表示するアニメーションを変更することができます。たとえば、スプライトに鳥の怪物がホバリングしているidleアニメーションと、獲物を襲うattackアニメーションを追加します。idleアニメーションのときはスプライトの位置を変えず、あるタイミングでattackアニメーションに切り替え、スプライトを下方向に速く移動させると、空でホバリングしていた鳥の怪物が突然獲物に襲い掛かるアニメーションが表現できます。
目次
マウス位置でアニメーションを切り替える
スプライトにアニメーションを追加するときには、Sprite.addAnimation()の第1引数にラベル名、つまりほかのアニメーションと区別するためのそのアニメーションの名前を指定します。スプライトは、1番めに追加されたアニメーションを最初に使用します。
// スプライトにアニメーションを名前付きで追加
monsterSprite.addAnimation('idle', idleAnim);
monsterSprite.addAnimation('fly', flyAnim);
そしてあるタイミングで、Sprite.changeAnimation()メソッドに、切り替えるアニメーションの名前を渡して呼び出します。
monsterSprite.changeAnimation('fly');
次の例のスプライトは、マウス位置に反応して近づいてきます。マウスから遠いときには羽を羽ばたかせて速く近づき、マウスに近くなると羽ばたきを弱め、移動を止めます。またキャンバスの左上にはスプライトが現在使用しているアニメーションの名前を描画しています。
let idleAnim;
let flyAnim;
let monsterSprite;
const easing = 0.05;
const closeness = 10;
function preload() {
// アニメーションを2つ作成
idleAnim = loadAnimation('assets/monster/idle/000.png', 'assets/monster/idle/011.png');
flyAnim = loadAnimation('assets/monster/fly/000.png', 'assets/monster/fly/007.png');
}
function setup() {
createCanvas(800, 300);
// スプライトを作成
monsterSprite = createSprite();
// スプライトにアニメーションを名前付きで追加
monsterSprite.addAnimation('idle', idleAnim);
monsterSprite.addAnimation('fly', flyAnim);
setSpriteProperty(monsterSprite, 400, 150);
// 描画するテキストの大きさと色を設定
textSize(32);
fill(0, 102, 153);
}
function draw() {
// 背景色を描画
background(45, 187, 255);
// 現在使用中のアニメーション名を左上に描画
text(monsterSprite.getAnimationLabel(), 10, 50);
// スプライトの各種プロパティを更新
updateSprite();
// スプライトを描画
drawSprite(monsterSprite);
}
// スプライトを実際に描画する前の論理
function updateSprite() {
// マウスカーソルとモンスターの位置関係によって、
// モンスターのアニメーションと向き、移動方向を変える
// マウスカーソルがモンスターより左にあるなら
if (mouseX < monsterSprite.position.x - closeness) {
// 理解を助けるための補助線
line(mouseX, 100, monsterSprite.position.x - closeness, 100);
// flyアニメーションに変更
monsterSprite.changeAnimation('fly');
// 反転
monsterSprite.mirrorX(-1);
// イージングでマウスに近づく
monsterSprite.velocity.x = (mouseX - monsterSprite.position.x) * easing;
// マウスカーソルがモンスターより右にあるなら
}
else if (mouseX > monsterSprite.position.x + closeness) {
// 理解を助けるための補助線
line(mouseX, 100, monsterSprite.position.x + closeness, 100);
// flyアニメーションに変更
monsterSprite.changeAnimation('fly');
// 反転しない(元に戻す)
monsterSprite.mirrorX(1);
// イージングでマウスに近づく
monsterSprite.velocity.x = (mouseX - monsterSprite.position.x) * easing;
// 十分に近いなら
}
else {
// idleアニメーションに変更
monsterSprite.changeAnimation('idle');
// 止まる
monsterSprite.velocity.x = 0;
}
}
function setSpriteProperty(sp, xpos, ypos) {
sp.position.x = xpos;
sp.position.y = ypos;
sp.debug = true;
sp.onMouseOver = (() => {});
}
アニメーションはどのタイミングで切り替えるのかは、コードの記述者が決める問題です。たとえばボタンのクリックで切り替えるのなら、ボタンのクリックで呼び出される関数に記述します。今の場合、マウスの位置はユーザーの操作によってつねに変わるので、始終監視する必要があります。”始終”という意味では、高頻度で呼び出されるdraw()関数内で監視するのが適切でしょう。
上記の例では、マウスとモンスタースプライトの位置関係を次の3つに分けています。closenessは十分近いと見なす程度を決める変数です。マウスのX位置とモンスターのX位置を結ぶ直線を補助用に描いているので参考にしてください。
- マウスカーソルがモンスターより左にある場合
- マウスカーソルがモンスターより右にある場合
- それ以外の場合
上記1と2の場合には、モンスタースプライトのchangeAnimation()メソッドを呼び出して羽ばたくflyアニメーションに変更し、mirrorX()メソッドを使って進行方向に反転させ、イージングと呼ばれるテクニックを使ってマウス位置に近づけています。3の場合には移動しないので、changeAnimation()でidleアニメーションに変更し、velocity.xに0を代入して移動を止めています。
イージングの原理については「4_3:応答:イージングの導入 p5.js JavaScript」で述べています。
draw()関数では、描画を毎フレーム変えたい場合(前フレームの描画内容を一掃したいとき)はまずbackground()関数で背景色を塗ります。そして記述者が決めた論理にしたがってスプライトのプロパティを更新し、最後にdrawSprite()やdrawSprites()でスプライトを描画します。
リファレンスメモ
Sprite.getAnimationLabel()
getAnimationLabel () String
現在のアニメーションのラベルを返す。
戻り値
String:label – イメージ/アニメーションの識別子
Sprite.changeAnimation()
changeAnimation ( label )
表示されるアニメーションを変更する。
パラメータ
label String アニメーション識別子
Sprite.mirrorX()
mirrorX ( dir ) Number
スプライトの水平方向のミラーリングを設定する。イメージは、1の場合通常通り表示され、-1の場合水平方向に反転(フリップ)する。引数がない場合は、現在のxミラーリングが返される。
パラメータ
dir Number – 1か-1
戻り値
Number: パラメータが指定されない場合は現在のミラーリング
マウスプレスとキーボードでアニメーションを切り替える
引きつづき上記サンプルに手を加え、ページ画面のどこかをマウスで押しつづけている間はスプライトをまた別のアニメーション(hurtアニメーション)に変更し、同時にスプライトを回転させます。またキーボードの上下矢印キーの押し下げでスプライトをスケーリング(拡大縮小)します。
今マウスボタンが押されているかどうかは、p5.jsのmouseIsPressedシステム変数で分かります。また、上下矢印キーが今押されているかどうかは、p5.jsのkeyIsDown()関数に、p5.jsの定数UP_ARROW(上矢印キー)かDOWN_ARROW(下矢印キー)を渡すことで調べることができます。
以下は追加するコードです。
// 冒頭の変数宣言
let hurtAnim;
const rotationVal = 10;
const scaleVal = 0.05;
// preload()関数内、flyAnimの下に挿入
hurtAnim = loadAnimation('assets/monster/hurt/000.png', 'assets/monster/hurt/007.png');
// setup()関数内、'fly'アニメーションの下に挿入
monsterSprite.addAnimation('hurt', hurtAnim);
// updateSprite()関数内、マウスとモンスターの位置関係を調べて処理するifステートメントの後に挿入
// マウスプレス中は苦しんで回転する
if (mouseIsPressed) {
// アニメーションに回転する画像が含まれているわけではない
monsterSprite.rotation -= rotationVal;
monsterSprite.changeAnimation('hurt');
}
else {
monsterSprite.rotation = 0;
}
// キーボードの上下矢印キーでスケールを変更する
// イメージのスケーリングは画質を劣化させ、負の値にスケールするとイメージがひっくり返る。
if (keyIsDown(UP_ARROW)) {
monsterSprite.scale += scaleVal;
}
else if (keyIsDown(DOWN_ARROW)) {
monsterSprite.scale -= scaleVal;
}
リファレンスメモ
Sprite.rotation
rotation Number
ビジュアル要素(イメージやアニメーション)の度単位の回転。注意:これは移動の方向ではない。getDirection()を参照。デフォルトは0。
Sprite.scale
scale Number
スプライトのスケール(拡大縮小)を決める。例:2はビジュアルの元々のサイズを2倍し、0.5は半分にする。拡大するとイメージはぼやけて見える。デフォルトは1。