如何在p5.js中以正确的顺序触发动画?

时间:2019-05-07 17:11:16

标签: javascript processing p5.js

当球从每个边缘反弹时,我试图在一个简单的乒乓球游戏中触发动画。但是,我正在努力使动画以我想要的方式出现。我希望椭圆按击中边缘的顺序相互重叠。有时会发生这种情况,但我相信问题是,当两个动画布尔值同时为真时,无论哪个动画出现在程序流程中的稍后会覆盖其他动画。因此,按照我下面的方法,如果两个都是正确的,蓝色将始终覆盖黄色,如果两个都是正确的,则红色将始终覆盖蓝色和黄色。

在此方面提供的任何帮助将不胜感激!谢谢。

var bg = 220;

var x = 0;
var y = 200;
var speed = 3;
var speedY = 4;

var leftAnim = false;
var leftX;
var leftY;
var leftDiam = 40;

var rightAnim = false;
var rightX;
var rightY;
var rightDiam = 40;

var topAnim = false;
var topX;
var topY;
var topDiam = 40;

function setup() {
  createCanvas(400, 400);
}

function draw() {

  background(bg);
  noStroke();

  edgeAnimation();

  fill("white");
  ellipse(x, y, 40, 40);
  x += speed;
  y += speedY;

  if (x > width) {
    //set rightAnim boolean to true to trigger right edge animation
    rightAnim = true;
    //update animating ellipse position variables to draw it at the same point where ball bounced
    rightX = x;
    rightY = y;
    //reverse x direction of ball
    speed *= -1;
  }

  if (x < 0) {
    leftAnim = true;
    leftX = x;
    leftY = y;
    speed *= -1;
  }
  // if the ball hits the top of the canvas, reverse the y direction of the ball    
  if (y < 0) {
    topAnim = true;
    topX = x;
    topY = y;
    speedY *= -1;
  }

  //if ball hits bottom of the canvas, stop the ball's motion
  if (y > height) {
    speed = 0;
    speedY = 0;
  }

  //conditional to check for collision with paddle
  if (x > mouseX && x < mouseX + 100 && y == height - 60) {
    speedY *= -1;
  }
  // Paddle
  rect(mouseX, height - 40, 100, 30);
}

function edgeAnimation() {
  if (leftAnim == true) {
    fill("gold");
    ellipse(leftX, leftY, leftDiam);
    leftDiam += 20;
    //if animating ellipse fills the canvas, change the background color to the ellipse color, change leftAnim boolean to false and reset the diameter's size
    if (leftDiam > 1150) {
      bg = "gold";
      leftAnim = false;
      leftDiam = 40;
    }
  }

  if (rightAnim == true) {
    fill("RoyalBlue");
    ellipse(rightX, rightY, rightDiam);
    rightDiam += 20;
    if (rightDiam > 1150) {
      bg = "RoyalBlue";
      rightAnim = false;
      rightDiam = 40;
    }
  }

  if (topAnim == true) {
    fill("crimson");
    ellipse(topX, topY, topDiam);
    topDiam += 20;
    if (topDiam > 1150) {
      bg = "crimson";
      topAnim = false;
      topDiam = 40;
    }
  }

}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/p5.js"></script>

1 个答案:

答案 0 :(得分:2)

不使用布尔状态,而是使用动画列表。

var animation = []

是否有新的边缘被击中,在动画列表的末尾(.push)附加了新的动画数据集:

function draw() {

    // [...]

    if (x > width) {
        animation.push( {color: "RoyalBlue", x: x, y: y, diam:40} );
        speed *= -1;
    }
    if (x < 0) {
        animation.push( {color: "gold", x: x, y: y, diam: 40} );
        speed *= -1;
    }  
    if (y < 0) {
        animation.push( {color: "crimson", x: x, y: y, diam: 40} );
        speedY *= -1;
    }

    // [...]

}

动画可以循环绘制。仅保留不超过限制的动画:

function edgeAnimation() {

    var keepAnimation = []
    for (let i = 0; i < animation.length; ++i) {
        fill( animation[i].color );
        ellipse( animation[i].x, animation[i].y, animation[i].diam );
        animation[i].diam += 20;
        if (animation[i].diam > 1150) {
            bg = animation[i].color;
        } else {
            keepAnimation.push(animation[i]);
        }
    }
    animation = keepAnimation;
}

请参见示例,在我将建议应用于问题代码时

var bg = 220;

var x = 0;
var y = 200;
var speed = 3;
var speedY = 4;

var animation = []

function setup() {
  createCanvas(400, 400);
}

function draw() {

    background(bg);
    noStroke();

    edgeAnimation();

    fill("white");
    ellipse(x, y, 40, 40);
    x += speed;
    y += speedY;

    if (x > width) {
        animation.push( {color: "RoyalBlue", x: x, y: y, diam:40} );
        speed *= -1;
    }
    if (x < 0) {
        animation.push( {color: "gold", x: x, y: y, diam: 40} );
        speed *= -1;
    }  
    if (y < 0) {
        animation.push( {color: "crimson", x: x, y: y, diam: 40} );
        speedY *= -1;
    }

    //if ball hits bottom of the canvas, stop the ball's motion
    if (y > height) {
        x = random(20, width-20);
        y = 20;
        speed = random(2,4);
        speedY = 6 - speed;
    }

    //conditional to check for collision with paddle
    if (x > mouseX && x < mouseX + 100 && y < height - 59 + speedY && y > height - 60) {
        speedY *= -1;
        y = height - 60
    }
    // Paddle
    rect(mouseX, height - 40, 100, 30);
}

function edgeAnimation() {

    var keepAnimation = []
    for (let i = 0; i < animation.length; ++i) {
        fill( animation[i].color );
        ellipse( animation[i].x, animation[i].y, animation[i].diam );
        animation[i].diam += 20;
        if (animation[i].diam > 1150) {
            bg = animation[i].color;
        } else {
            keepAnimation.push(animation[i]);
        }
    }
    animation = keepAnimation;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/p5.js"></script>