解决矩形和圆形之间的碰撞

Resolve Collision between a Rectangle and a Circle

我正在开发一款小型平台游戏。玩家是一个圆圈,我打算将障碍物实现为矩形。有谁知道如何确保玩家无法通过障碍物?我尝试了一些方法,但它们出现故障。

这是我目前所拥有的(它有点长,所以我需要的方法在 resolveCollision 函数中):

var canvas = document.createElement("CANVAS");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas.id = "CANVAS";
document.body.appendChild(canvas);
document.body.style.margin = "0px 0px 0px 0px";
document.body.style.overflow = "hidden";
document.body.style.backgroundColor = "#202020";
var ctx = canvas.getContext("2d");
var objects = [];

var player = {
  x: window.innerWidth / 2 - 25,
  y: 0,
  height: 25,
  width: 25,
  old: {
    x: 0,
    y: 0,
  },
  velocity: {
    x: 0,
    y: 0,
  },
  jumping: true,
  color: "#ff0000",
};

var obstacle = {
  x: 50,
  y: 300,
  width: 50,
  height: 50
}

var control = {
  left: false,
  right: false,
  up: false,
  keyListener: function (event) {
    var keyState;
    if (event.type == "keydown") {
      keyState = true;
    } else {
      keyState = false;
    }
    switch (event.keyCode) {
      case 37:
        control.left = keyState;
        break;
      case 38:
        control.up = keyState;
        break;
      case 39:
        control.right = keyState;
        break;
    }
  }
};

var checkCollision = function (object) {
  var distX = Math.abs(player.x - object.x - object.width / 2);
  var distY = Math.abs(player.y - object.y - object.height / 2);

  if (distX > (object.width / 2 + (player.width + player.height) / 2)) { return false; }
  if (distY > (object.height / 2 + (player.width + player.height) / 2)) { return false; }

  if (distX <= (object.width / 2)) { return true; }
  if (distY <= (object.height / 2)) { return true; }

  var dx = distX - object.width / 2;
  var dy = distY - object.height / 2;
  return (dx * dx + dy * dy <= ((player.width + player.height) / 2 * (player.width + player.height) / 2));
}

var resolveCollision = function (object) {
  // Add Resolve Collision Code
  if (checkCollision(object)) {
    throw new SyntaxError("Couldn't resolve collision between player and object!");
  }
}
var renderFrame = function () {
  if (control.up && player.jumping == false) {
    player.velocity.y -= 20;
    player.jumping = true;
  }
  if (control.left) {
    player.velocity.x -= 0.5;
  }
  if (control.right) {
    player.velocity.x += 0.5;
  }

  player.velocity.y += 1.5;
  player.x += player.velocity.x;
  player.y += player.velocity.y;
  player.velocity.x *= 0.95;
  player.velocity.y *= 0.95;
  player.old.x = player.x - player.velocity.x * 1.2;
  player.old.y = player.y - player.velocity.y * 1.2;

  if (player.y > window.innerHeight - 25) {
    player.jumping = false;
    player.y = window.innerHeight - 25;
    player.velocity.y = 0;
  }

  ctx.clearRect(0, 0, window.innerWidth, window.innerHeight);
  ctx.fillStyle = player.color;
  ctx.beginPath();
  ctx.globalAlpha = 0.5;
  ctx.ellipse(player.old.x, player.old.y, player.width, player.height, Math.PI / 4, 0, 2 * Math.PI);
  ctx.fill();
  ctx.beginPath();
  ctx.globalAlpha = 1;
  ctx.ellipse(player.x, player.y, player.width, player.height, Math.PI / 4, 0, 2 * Math.PI);
  ctx.fill();
  ctx.fillRect(obstacle.x, obstacle.y, obstacle.width, obstacle.height);
  if (checkCollision(obstacle)) {
    resolveCollision(obstacle)
  }
  window.requestAnimationFrame(renderFrame);

};

renderFrame();

window.addEventListener("keydown", control.keyListener);
window.addEventListener("keyup", control.keyListener);

提前致谢!

编辑:我之前说得不够清楚,但我需要一种方法来在检测到冲突后解决冲突。我已经有了检测碰撞的方法。

你说的是边界框和边界圆计算。

这里是对每种几何类型的算法的真正简单解释:

https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection

当然,如果它们都是相同的形状可以简化它,一种解决方案是将圆圈转换为方框:

https://math.stackexchange.com/questions/2360970/how-to-calculate-a-bounding-box-of-a-circle

然后就用边界框碰撞检测。

但我认为如果您想同时支持两者,那么一般的策略是尝试检测圆是否与框相交。

下面是对该算法的描述: https://www.lazyfoo.net/tutorials/SDL/29_circular_collision_detection/index.php

To check if a box and circle collided we need to find the closest point on the box... Here we find the closest y position much like we did the x position. If the distance squared between the closest point on the box and the center of the circle is less than the circle's radius squared, then there is a collision.