如何使用 p5.js/p5.play 在精灵 collide/overlap 后显示动画

how to display animation after sprites collide/overlap using p5.js/p5.play

我试图在精灵之间发生碰撞时显示动画。我有我射击的小行星,当我射击它们时,当子弹碰撞或与小行星重叠时,小行星就会消失。我想在与小行星相撞后播放动画。我该怎么做?

查看下面的代码

function createAsteroids() { // code to spawn asteroids at random locations
    for (let i = 0; i < numAsteroids; i++) {
        asteroid = createSprite(random(0, 1000), random(-50, -350), 40, 40);
        asteroid.addImage(asteroidSprite)
        asteroidSprite.resize(65, 65);

        asteroid.maxSpeed = random(1, 3);
        rock.add(asteroid);
        asteroidArray.push(asteroid);
    }
}
function drawAsteroid() { // draws asteroids moving down and checking collision
    rock.overlap(turret, explode)
    for (let i = 0; i < asteroidArray.length; i++) {
        if (asteroidArray[i].position.y > height) {
            asteroidArray[i].position.y = 0;
            asteroidArray[i].position.x = random(0, 800);
        }
        asteroidArray[i].addSpeed(3, 90);   // code to move asteroids towards the turrets using attracttion point
        if (i % 3 == 0) {
            asteroidArray[i].attractionPoint(1, 100, 740);
        }
        if (i % 3 == 1) {
            asteroidArray[i].attractionPoint(1, 500, 740);
        }
        if (i % 3 == 2) {
            asteroidArray[i].attractionPoint(1, 1200, 740);
        }
    }
}
function createBullets() { // code to create bullet
    for (let i = 0; i < numBullets; i++) {
        bullets = createSprite(500, 740, 25, 25);
        bullets.addImage(bulletSprite)
        bullets.maxSpeed = 6;
        pew.add(bullets)
        bulletArray.push(bullets)
    }
}
function drawBullets() { // code to fire bullets
    pew.overlap(rock, explode)
    explodeSound.play()
    bulletArray[bullCount].attractionPoint(4, mouseX, mouseY);
    bullCount++;
}

function explode(sprite, obstical) { //code for explosion and collision and removal of sprites on collision
    sprite.remove()
    obstical.remove()
    explodeSound.play()
}

我相信我需要在 drawBullets() 函数或 explode 函数中实现一些东西。但不确定当子弹与小行星相撞时如何真正播放动画。

explosion = loadAnimation('assets/0.png', 'assets/1.png', 'assets/2.png', 'assets/3.png', 'assets/5.png', 'assets/6.png',
        'assets/7.png', 'assets/8.png', 'assets/9.png', 'assets/10.png', 'assets/11.png', 'assets/12.png', 'assets/13.png',
        'assets/14.png', 'assets/15.png', 'assets/16.png', 'assets/17.png', 'assets/18.png', 'assets/19.png', 'assets/20.png',
        'assets/21.png', 'assets/22.png', 'assets/23.png', 'assets/24.png', 'assets/25.png', 'assets/26.png', 'assets/27.png',
        'assets/28.png', 'assets/29.png', 'assets/30.png', 'assets/31.png', 'assets/32.png', 'assets/33.png', 'assets/34.png',
        'assets/35.png', 'assets/36.png', 'assets/37.png', 'assets/38.png', 'assets/39.png', 'assets/40.png', 'assets/41.png',
        'assets/42.png', 'assets/43.png', 'assets/44.png', 'assets/45.png', 'assets/46.png', 'assets/47.png');

当碰撞发生时,您可以创建一个新对象,其中包含有关碰撞的信息,以及您希望碰撞发生多长时间,然后将该对象添加到新的 explosions = []。像这样:

 explosions.push({
  x: towers[j].position.x,
  y: towers[j].position.y,
  time: 20
 });

当然,在您的示例中,您会希望在发生碰撞时在子弹的位置创建对象。

然后在您的 draw() 中,您可以简单地向后遍历该数组并显示动画:

function draw() {
  ...
  // loop backwards so we can remove from array
  for (let i = explosions.length - 1; i >= 0; i--) { 

    animation(explodeAnimation, explosions[i].x, explosions[i].y);
    explosions[i].time--;
    
    if (explosions[i].time <= 0) {
      explosions.splice(i, 1);
    }
  }
}

您也可以使用 setTimeout 但这可能更清楚。

这是我创建的一个示例(动画有点不可靠,我只是从 this animation reference 复制的):

let numAsteroids = 10;
let towers;
let rock;

let spriteSheet;

let explosions = [];
function setup() {
  createCanvas(400, 400);
  spriteSheet = loadSpriteSheet('spritesheet.png', 171, 158, 11);
  explodeAnimation = loadAnimation(spriteSheet);
  
  rock = Group();
  towers = Group();
  createTowers();
  createAsteroids();
}

function draw() {
  background(220);
  

  drawSprites(rock);
  drawSprites(towers);
  updateAsteroids();
  
 // loop backwards so we can remove from array
  for (let i = explosions.length - 1; i >= 0; i--) { 

    animation(explodeAnimation, explosions[i].x, explosions[i].y);
    explosions[i].time--;
    
    if (explosions[i].time <= 0) {
      explosions.splice(i, 1);
    }
  }

}

function createAsteroids() {
  // code to spawn asteroids at random locations
  for (let i = 0; i < numAsteroids; i++) {
    let asteroid = createSprite(random(0, width), random(-50, -350), 40, 40);
    asteroid.maxSpeed = random(1, 3);
    rock.add(asteroid);
    
    let tower = floor(random(3))
    
    asteroid.attractionPoint(asteroid.maxSpeed, towers[tower].position.x, towers[tower].position.y);
  }
}


function updateAsteroids() {
  // draws asteroids moving down and checking collision
  for (let i = rock.length - 1; i >= 0; i--) {
    if (rock[i].position.y > height) {
      rock[i].position.y = 0;
      rock[i].position.x = random(0, width);
    }
    
    for (let j = towers.length - 1; j >=0; j--) {
      if (rock[i].overlap(towers[j])) {
        rock[i].position.y = 0;
        rock[i].position.x = random(0, width);
        
        explosions.push({
          x: towers[j].position.x,
          y: towers[j].position.y,
          time: 20
        });
      }
    }
  }
}

function createTowers() {
  towers.push(createSprite(40, height - 30, 40, 90));
  towers.push(createSprite(width/2, height - 30, 40, 90));
  towers.push(createSprite(width-40, height - 30, 40, 90));
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/addons/p5.sound.min.js"></script>
        <script src="https://cdn.jsdelivr.net/gh/molleindustria/p5.play/lib/p5.play.js"></script>

    <link rel="stylesheet" type="text/css" href="style.css">
    <meta charset="utf-8" />

  </head>
  <body>
    <script src="sketch.js"></script>
  </body>
</html>

这是我为此创建的 p5.js editor sketch 的 link。