p5.js collision/object 互动。球弹跳

p5.js collision/object interaction. Ball bounce

阵列中的球与物体(矩形)发生碰撞后,球的反弹效果似乎与撞击地面时不同。

当与物体接触时,它似乎加快了速度,突然闪过并停在地上。

问题:

  1. 为什么它似乎想停在地面上而不是物体本身?
  2. 如何使球在接触物体时具有与接触地面时相同的弹跳效果?

代码:

    var balls = [];
    var obstacle;

    function setup() {
      createCanvas(400, 400);
      obstacle = new Obstacle();
    }

    function draw() {
      background(75);
      obstacle.display();
      for (var i = 0; i < balls.length; i++) {
        balls[i].display();
        balls[i].update();
        balls[i].edges();
        RectCircleColliding(balls[i], obstacle);
        //console.log(RectCircleColliding(balls[i], obstacle));
      }
    }

    function mousePressed() {
      balls.push(new Ball(mouseX, mouseY));
    }

    function Ball(x, y) {
      this.x = x;
      this.y = y;
      this.r = 15;
      this.gravity = 0.5;
      this.velocity = 0;
      this.display = function() {
        fill(255, 0, 100);
        stroke(255);
        ellipse(this.x, this.y, this.r * 2);
      }
      this.update = function() {
        this.velocity += this.gravity;
        this.y += this.velocity;
      }
      this.edges = function() {
        if (this.y >= height - this.r) {
          this.y = height - this.r;
          this.velocity = this.velocity * -1;
          this.gravity = this.gravity * 1.1;
        }
      }
    }

    function Obstacle() {
      this.x = width - width;
      this.y = height / 2;
      this.w = 200;
      this.h = 25;

      this.display = function() {
        fill(0);
        stroke(255);
        rect(this.x, this.y, this.w, this.h);
      }
    }

    function RectCircleColliding(Ball, Obstacle) {
      // define obstacle borders
      var oRight = Obstacle.x + Obstacle.w;
      var oLeft = Obstacle.x;
      var oTop = Obstacle.y;
      var oBottom = Obstacle.y + Obstacle.h;

      //compare ball's position (acounting for radius) with the obstacle's border
      if (Ball.x + Ball.r > oLeft) {
        if (Ball.x - Ball.r < oRight) {
          if (Ball.y + Ball.r > oTop) {
            if (Ball.y - Ball.r < oBottom) {
              Ball.y = Obstacle.y - Ball.r * 2;
              Ball.velocity = Ball.velocity * -1;
              Ball.gravity = Ball.gravity * 1.1;
              Ball.velocity += Ball.gravity;
              Ball.y += Ball.velocity;

              return (true);
            }
          }
        }
      }
      return false;
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.min.js"></script>

这个问题的代码的主要问题是我们需要检查碰撞并且只允许在球没有碰撞时更新。另一个问题是,当发生碰撞时,我们必须限制重力以防止球一直坠落到地面。

这是更正后的代码:

var balls = [];
var obstacle;

function setup() {
  createCanvas(400, 400);
  obstacle = new Obstacle();
}

function draw() {
  background(75);
  obstacle.display();
  for (var i = 0; i < balls.length; i++) {
    balls[i].display();
 if (!RectCircleColliding(balls[i], obstacle)){
    balls[i].update();
    balls[i].edges();
 }
    
    //console.log(RectCircleColliding(balls[i], obstacle));
  }
}

function mousePressed() {
  balls.push(new Ball(mouseX, mouseY));
}

function Ball(x, y) {
  this.x = x;
  this.y = y;
  this.r = 15;
  this.gravity = 0.5;
  this.velocity = 0;
  this.display = function() {
    fill(255, 0, 100);
    stroke(255);
    ellipse(this.x, this.y, this.r * 2);
  }
  this.update = function() {
    this.velocity += this.gravity;
    this.y += this.velocity;
  }
  this.edges = function() {
    if (this.y >= height - this.r) {
      this.y = height - this.r;
      this.velocity = this.velocity * -1;
      this.gravity = this.gravity * 1.1;
    }
  }
}

function Obstacle() {
  this.x = width - width;
  this.y = height / 2;
  this.w = 200;
  this.h = 25;

  this.display = function() {
    fill(0);
    stroke(255);
    rect(this.x, this.y, this.w, this.h);
  }
}

function RectCircleColliding(Ball, Obstacle) {
  // define obstacle borders
  var oRight = Obstacle.x + Obstacle.w;
  var oLeft = Obstacle.x;
  var oTop = Obstacle.y;
  var oBottom = Obstacle.y + Obstacle.h;

  //compare ball's position (acounting for radius) with the obstacle's border
  if (Ball.x + Ball.r > oLeft) {
    if (Ball.x - Ball.r < oRight) {
      if (Ball.y + Ball.r > oTop) {
        if (Ball.y - Ball.r < oBottom) {
         let oldY = Ball.y;
         Ball.y = oTop - Ball.r;
         Ball.velocity = Ball.velocity * -1;
         if (Ball.gravity < 2.0){
          Ball.gravity = Ball.gravity * 1.1;  
         } else {
           Ball.velocity = 0;
           Ball.y = oldY;
         }   
         return (true);
        } 
      }
    }
  }
  return false;
  }
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.min.js"></script>