javascript - 解决矩形和圆形之间的冲突
问题描述
我正在开发一款小型平台游戏。玩家是一个圆圈,我打算将障碍物实现为矩形。有谁知道如何确保玩家不能通过障碍物?我尝试了一些方法,但它们出现了故障。这是我到目前为止所拥有的(它有点长,所以我需要的方法在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
要检查一个盒子和圆是否碰撞,我们需要找到盒子上最近的点......在这里我们找到最近的 y 位置,就像我们找到 x 位置一样。如果盒子上最近的点和圆心之间的距离平方小于圆半径的平方,那么就会发生碰撞。
推荐阅读
- ios - How to add and remove UILabels in UIStackview
- java - 如何更改或设置新的活动启动器应用程序?(在 Java 中)
- r - 从数据框中删除行
- javascript - React-native 在设备上崩溃;致命信号 6 (SIGABRT)
- svg - 将文本格式化为圆形
- c - 如何使用 C 实现完整的二叉树
- node.js - Heroku pg:psql 说它正在连接但从不连接
- javascript - 如何下载此网址的来源?
- python - 从网络中提取子网并进行前馈传递
- webpack - 有没有办法通过 npm 共享 webpack 配置?