我相信这是一个稍微深入一点的答案,对你来说会更好,尤其是如果你对使用画布元素的游戏设计感兴趣的话。
这对您更有效的主要原因是因为它更侧重于 OOP(面向对象编程)方法。这允许在以后通过某些事件或环境来定义、跟踪和更改对象。它还允许轻松扩展您的代码,并且在我看来更具可读性和组织性。
基本上你在这里有两个形状碰撞。光标和它悬停的单个点/对象。对于基本的正方形、矩形或圆形,这还不错。但是,如果您要比较另外两个独特的形状,则需要阅读更多关于Separating Axis Theorem (SAT) 和其他碰撞技术的信息。那时优化和性能将成为一个问题,但目前我认为这是最佳方法。
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const width = canvas.width = window.innerWidth;
const height = canvas.height = window.innerHeight;
const cx = width / 2;
const cy = height / 2;
const twoPie = Math.PI * 2;
const points = []; // This will be the array we store our hover points in later
class Point {
constructor(x, y, r) {
this.x = x;
this.y = y;
this.r = r || 0;
}
}
class HoverPoint extends Point {
constructor(x, y, r, color, hoverColor) {
super(x, y, r);
this.color = color;
this.hoverColor = hoverColor;
this.hovered = false;
this.path = new Path2D();
}
draw() {
this.hovered ? ctx.fillStyle = this.hoverColor : ctx.fillStyle = this.color;
this.path.arc(this.x, this.y, this.r, 0, twoPie);
ctx.fill(this.path);
}
}
class Cursor extends Point {
constructor(x, y, r) {
super(x, y, r);
}
collisionCheck(points) {
// This is the method that will be called during the animate function that
// will check the cursors position against each of our objects in the points array.
document.body.style.cursor = "default";
points.forEach(point => {
point.hovered = false;
if (ctx.isPointInPath(point.path, this.x, this.y)) {
document.body.style.cursor = "pointer";
point.hovered = true;
}
});
}
}
function createPoints() {
// Create your points and add them to the points array.
points.push(new HoverPoint(cx, cy, 100, 'red', 'coral'));
points.push(new HoverPoint(cx + 250, cy - 100, 50, 'teal', 'skyBlue'));
// ....
}
function update() {
ctx.clearRect(0, 0, width, height);
points.forEach(point => point.draw());
}
function animate(e) {
const cursor = new Cursor(e.offsetX, e.offsetY);
update();
cursor.collisionCheck(points);
}
createPoints();
update();
canvas.onmousemove = animate;
我还想提出一件事。我还没有对此进行测试,但我怀疑使用一些简单的三角函数来检测我们的圆形物体是否碰撞会比 ctx.IsPointInPath() 方法更好。
但是,如果您使用更复杂的路径和形状,那么 ctx.IsPointInPath() 方法很可能是要走的路。如果不是我之前提到的其他更广泛的碰撞检测形式。
由此产生的变化将如下所示...
class Cursor extends Point {
constructor(x, y, r) {
super(x, y, r);
}
collisionCheck(points) {
document.body.style.cursor = "default";
points.forEach(point => {
let dx = point.x - this.x;
let dy = point.y - this.y;
let distance = Math.hypot(dx, dy);
let dr = point.r + this.r;
point.hovered = false;
// If the distance between the two objects is less then their combined radius
// then they must be touching.
if (distance < dr) {
document.body.style.cursor = "pointer";
point.hovered = true;
}
});
}
}
这是一个包含示例的链接以及与collision detection相关的其他链接
我希望你能看到这样的东西可以很容易地在游戏和其他任何东西中修改和使用。希望这会有所帮助。