二维碰撞检测
检测二维游戏中碰撞的算法取决于可以发生碰撞的形状类型(例如,矩形与矩形,矩形与圆形,圆形与圆形)。通常,您将有一个简单的通用形状来覆盖称为“命中框”的实体,即使碰撞不完全像素完美,它看起来也足够好,并且在多个实体之间具有性能。本文回顾了在二维游戏中提供碰撞检测的最常用技术。
轴对齐包围盒
碰撞检测的一种更简单的形式是在两个轴对齐的矩形之间,这意味着没有旋转。该算法通过确保两个矩形的 4 个边之间没有间隙来工作。任何间隙意味着不存在碰撞。
js
Crafty.init(200, 200);
const dim1 = { x: 5, y: 5, w: 50, h: 50 };
const dim2 = { x: 20, y: 10, w: 60, h: 40 };
const rect1 = Crafty.e("2D, Canvas, Color").attr(dim1).color("red");
const rect2 = Crafty.e("2D, Canvas, Color, Keyboard, Fourway")
.fourway(2)
.attr(dim2)
.color("blue");
rect2.bind("EnterFrame", function () {
if (
rect1.x < rect2.x + rect2.w &&
rect1.x + rect1.w > rect2.x &&
rect1.y < rect2.y + rect2.h &&
rect1.y + rect1.h > rect2.y
) {
// Collision detected!
this.color("green");
} else {
// No collision
this.color("blue");
}
});
圆形碰撞
碰撞检测的另一个简单形状是在两个圆形之间。该算法通过取两个圆形的中心点,并确保中心点之间的距离小于两个半径加在一起的距离来工作。
js
Crafty.init(200, 200);
const dim1 = { x: 5, y: 5 };
const dim2 = { x: 20, y: 20 };
Crafty.c("Circle", {
circle(radius, color) {
this.radius = radius;
this.w = this.h = radius * 2;
this.color = color || "#000000";
this.bind("Move", Crafty.DrawManager.drawAll);
return this;
},
draw() {
const ctx = Crafty.canvas.context;
ctx.save();
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(
this.x + this.radius,
this.y + this.radius,
this.radius,
0,
Math.PI * 2,
);
ctx.closePath();
ctx.fill();
ctx.restore();
},
});
const circle1 = Crafty.e("2D, Canvas, Circle").attr(dim1).circle(15, "red");
const circle2 = Crafty.e("2D, Canvas, Circle, Fourway")
.fourway(2)
.attr(dim2)
.circle(20, "blue");
circle2.bind("EnterFrame", function () {
const dx = circle1.x - circle2.x;
const dy = circle1.y - circle2.y;
const distance = Math.sqrt(dx * dx + dy * dy);
const colliding = distance < circle1.radius + circle2.radius;
this.color = colliding ? "green" : "blue";
});
分离轴定理
这是一种碰撞算法,可以检测任何两个凸多边形之间的碰撞。它的实现比以上方法更复杂,但功能更强大。这种算法的复杂性意味着我们需要考虑性能优化,这将在下一节中介绍。
实现 SAT 超出了本页面的范围,因此请查看下面推荐的教程
碰撞性能
虽然一些碰撞检测算法很简单,但测试每个实体与每个其他实体可能会浪费循环。通常游戏会将碰撞分为两个阶段,粗略阶段和精细阶段。
粗略阶段
粗略阶段应该为您提供一个可能发生碰撞的实体列表。这可以通过空间数据结构来实现,该数据结构将为您提供实体存在的粗略位置及其周围存在的实体。空间数据结构的一些例子包括四叉树、R 树或空间哈希表。
精细阶段
当您有一小部分实体要检查时,您将想要使用精细阶段算法(如上面列出的算法)来确定是否存在碰撞。