После столкновения между мячом из массива и объектом (прямоугольником) мяч, похоже, не имеет такого же эффекта отскока, как при ударе о землю.

При соприкосновении с объектом он, кажется, набирает скорость, внезапно выходит из строя и останавливается на земле.

Вопросы:

  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>
2
Peter_chura 19 Апр 2018 в 17:49

1 ответ

Лучший ответ

Основная проблема с кодом этого вопроса заключается в том, что нам нужно проверять наличие столкновений и разрешать обновления только тогда, когда мяч не сталкивается. Другая проблема заключалась в том, что при столкновении мы должны ограничивать силу тяжести, чтобы мяч не упал на землю.

Вот исправленный код:

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>
1
Charlie Wallace 14 Мар 2019 в 22:03