onMouseOverとonMouseOut
スプライトは、onMouseOverイベントハンドラプロパティと、それに対応するonMouseOutイベントハンドラプロパティを持っています。
スプライトのコライダー上にマウスカーソルが重なると、onMouseOverイベントハンドラプロパティに割り当てた関数が呼び出されます。その後マウスカーソルがスプライトのコライダーから出ると、onMouseOutイベントハンドラプロパテに割り当てた関数が呼び出されます。
次のサンプルでは、表示される花の写真の上にマウスカーソルを重ねると次の花の写真に変わります。
let flowerAnim;
let flowerSp;
function preload() {
flowerAnim = loadAnimation('assets/kurinsou/image1.png', 'assets/kurinsou/image3.png');
}
function setup() {
createCanvas(400, 300);
// 花スプライトを作成
flowerSp = createSprite();
// アニメーションには3つの画像が含まれている
flowerSp.addAnimation('idle', flowerAnim);
flowerSp.position.x = width / 2;
flowerSp.position.y = height / 2;
// アニメーションを止めておく
flowerSp.animation.stop();
// 花スプライトのマウスオーバーで
flowerSp.onMouseOver = function() {
print('mouseOver');
// カーソルをgrabに変更
cursor('grab');
// アニメーションを次のフレームに送る => スライドのようなもの
this.animation.nextFrame();
}
// 花スプライトのマウスアウトで、
flowerSp.onMouseOut = function() {
print('mouseOut');
// カーソルを元の矢印に戻す
cursor(ARROW);
}
}
function draw() {
background(200);
drawSprite(flowerSp);
}
ここでは花の写真を3つ持つAnimationオブジェクトを使って、スライドのような機能を実現しています。そのためにはまず、setup()でスプライトを作成した後すぐ、アニメーションの再生を止めます。
flowerSp.animation.stop();
そしてマウスオーバーイベントハンドラの定義で、Animationを次のフレームに送ります。
flowerSp.onMouseOver = function() {
cursor('grab');
this.animation.nextFrame();
}
onMousePressedとonMouseReleased
スプライトはまた、onMousePressedイベントハンドラプロパティと、それに対応するonMouseReleasedイベントハンドラプロパティを持っています。
スプライトの上でマウスボタンが押し下げられると、onMousePressedイベントハンドラプロパティに割り当てた関数が呼び出されます。その後マウスボタンが放されると、onMouseReleasedイベントハンドラプロパティに割り当てた関数が呼び出されます。
次のサンプルでは、画面下部の砲台を左クリックすると砲台が時計回りに回転し、右クリックすると反時計回りに回転します。マウスの真ん中のボタンを押すと、火の玉が連射できます。
let cannonimg;
let cannonSp;
let fireImg;
let fireSp;
let fireNum = 0;
function preload() {
cannonimg = loadImage('assets/cannon.png');
fireImg = loadImage('assets/fire.png');
}
function setup() {
createCanvas(400, 300);
// 砲台スプライトの作成
cannonSp = createSprite();
cannonSp.addImage(cannonimg);
cannonSp.myName = 'cannon';
cannonSp.position.x = width / 2;
cannonSp.position.y = height - cannonSp.width / 2;
// 砲台スプライトのマウスプレスで
cannonSp.onMousePressed = function() {
print('mousePressed');
// 左ボタンの場合
if (mouseButton === LEFT) {
print('LEFT');
// 時計回りに10度回転
this.rotation += 10;
// 右ボタンの場合
}
else if (mouseButton === RIGHT) {
print('RIGHT');
// 反時計回りに10度回転
this.rotation -= 10;
// センターボタンの場合
}
else if (mouseButton === CENTER) {
print('CENTER');
// 火の玉を発射
fire(this.rotation);
}
}
// 砲台スプライトのマウスリリースで
cannonSp.onMouseReleased = function() {
print('mouseReleased');
}
// コンテキストメニューを表示しない
document.oncontextmenu = function() {
return false;
}
textSize(15);
fill(255, 0, 0);
}
// 火の玉スプライトを作成し発射する
function fire(angle) {
fireNum++;
// 火の玉スプライトを作成
fireSp = createSprite();
fireSp.addImage(fireImg);
fireSp.scale = 0.3;
// 砲台に重なるように位置取りする
fireSp.position.x = cannonSp.position.x
fireSp.position.y = height - cannonSp.width / 2;
// 時間がたてば自動的に削除されるようにしておく
fireSp.life = 100;
// 確認用のカスタムプロパティ
fireSp.myName = 'fire' + fireNum;
// 深度の交換 => 砲台が火の玉を隠すように
swapDepths(fireSp, cannonSp);
// 火の玉の進む角度を砲台に合わせる
fireSp.rotation = angle;
// angle + 270の方向に移動 => 砲台から火の玉が発射されるように見える
fireSp.setSpeed(5, angle + 270);
}
function draw() {
background(200);
update();
drawSprites();
}
// 渡された2つのスプライトの深度を交換
function swapDepths(sp1, sp2) {
const depth1 = sp1.depth;
const depth2 = sp2.depth;
sp1.depth = depth2;
sp2.depth = depth1;
}
function update() {
// 確認用にスプライトの深度を表示
let txt = '';
for (let i = 0; i < allSprites.length; i++) {
txt += '深度' + allSprites[i].depth + ': ' + allSprites[i].myName + '\n';
}
text(txt, 30, 30, 220, 300);
// 砲台スプライトだけの場合は、砲台スプライトの深度を1に戻す
if (allSprites.length === 1) {
allSprites[0].depth = 1;
fireNum = 0;
}
}
砲台スプライトをマウスダウンすると、次のイベントハンドラが発効します。
cannonSp.onMousePressed = function() {
// 左ボタンの場合
if (mouseButton === LEFT) {
// 時計回りに10度回転
this.rotation += 10;
// 右ボタンの場合
}
else if (mouseButton === RIGHT) {
// 反時計回りに10度回転
this.rotation -= 10;
// センターボタンの場合
}
else if (mouseButton === CENTER) {
// 火の玉を発射
fire(this.rotation);
}
}
mouseButtonはp5.jsのmouseButtonプロパティで、マウスダウンが押されたときどのボタン(LEFT, RIGHT, CENTER)が押されたかを自動的に追跡します。