我想编写一个简单的JavaScript动画,使一些球在画布内移动。我想检测到与backbone.js处理的自定义事件的碰撞,而不是为环的嵌套检查每对球之间的碰撞。
var j;
for (j = 0; j < N_BALLS; j++) {
ball_center = new Point(..., ...);
ball_shape = new Circle(ball_center, ball_radius);
ball_velocity = ...;
ball_ID = j;
balls[j] = new Ball(ball_shape, ball_velocity, ball_ID);
_.extend(balls[j], Backbone.Events);
balls[j].on("imhere", balls[j].event_handler);
}
function animate() {
if (!paused) {
context.clearRect(0, 0, canvas.width, canvas.height);
var j;
for (j = 0; j < N_BALLS; j++){
balls[j].updatePosition();
balls[j].trigger("imhere", balls[j].shape, balls[j].ID);
}
for (j = 0; j < N_BALLS; j++)
balls[j].draw(context, '#0000ff');
window.requestNextAnimationFrame(animate);
}
}
event_handler是每个球对象的成员方法
Ball.prototype.event_handler = function(shape, ID) {
console.log("ball " + this.ID + " caught message from ball " + ID);
};
我希望有时候一个球会从另一个消息中抓住一个消息,但事实并非如此。
我想以某种方式安排事件处理程序可以:
- 当
this.ID == ID
时转发事件 - 停止事件传播如果
this.ID != ID
骨干事件
this.ID
可能是不确定的,因为骨干.on()
需要上下文作为最后一个参数
您还在球本身上注册比赛,并在球上也触发。
事件不是主干内的全局,您需要自己创建一个全局事件频道或使用插件。寻找事件总线或事件聚合器等。
一个快速的示例可能很简单:
var GlobalEvents = _.extend({}, Backbone.Events);
骨干本身是扩展Backbone.Events
功能的对象,但最好为您的用例创建本地事件通道。
说到使用Backbone.Events
对象,当您真的应该延长Ball
原型时,您正在扩展Ball
的每个实例。
_.extend(Ball.prototype, Backbone.Events);
您应该优先于listenTo
,而不是on
。
销毁球时,您可以致电ball.stopListening()
,并且可以避免内存泄漏。它还将解决event_handler
回调中的上下文问题。
所以,使用全球事件聚合器:
balls[j].listenTo(GlobalEvents, "imhere", balls[j].event_handler);
骨干事件不是DOM事件,也不会上下冒泡,因此没有stopPropagation
或preventDefault
。在后台,它只是骨干的香草JS。
碰撞检测
现在我们已经涵盖了事件部分,让我说这不是碰撞检测的最佳解决方案。
完全相同,就像您在更新位置时是否会在其他所有球上调用isCollindingWith(ball)
功能。这就是事件发生的事情,但是随着事件实施中隐藏的循环。
在此答案中处理优化的碰撞检测算法太宽了,所以我将链接到有关2D碰撞检测的精彩文章。
有趣的部分是在最后,他们谈论类似 Quad树,R-Trees或Spacial Hashmaps。