我在JS中有一个16个台球阵列,希望用它的方向和速度顺畅地移动每个球。
为此,我设置了一个计时器,每42毫秒调用UpdateThis()
(24 fps)
问题是UpdateThis()
需要53毫秒作为萤火虫状态。
现在UpdateThis
遍历每一个球,然后拨打UpdateBall(ball)
我认为存在问题。
UpdateBall看起来像这样:
function UpdateBall(ball)
{
if(ball.direction.x != 0 && ball.direction.y != 0) {
//ball moving!
for(var i = 0; i < balls.length; i++) {
//CheckCollision(ball, balls[i]); //even without this it takes 53 ms!
}
var ps = VAdd(ball.position, VMul(ball.direction, ball.speed)); //Multiply Direction with speed and add to position!
if(ps.x < Bx || ps.y < By || ps.x > Bw || ps.y > Bh) { //Bounce off the wall!
ball.direction = VMul(ball.direction, -1); //Invert direction
ball.speed *= 1;
ps = VAdd(ball.position, VMul(ball.direction, ball.speed)); //Calc new position!
}
ball.position = ps;
ball.MoveTo(); //See explanation at the bottom.
ball.speed *= GRK; //Gravity
if(ball.speed < 0.05) {
ball.speed = 0;
}
}
}
似乎在ball.MoveTo()
花费的时间最多,如下所示:
function()
{
this.image.style.left = this.position.x + "px";
this.image.style.top = this.position.y + "px";
}
- 更新 -
function UpdateThis() {
for(var i = 0; i < balls.length; i++) {
var cur = balls[i];
UpdateBall(cur);
balls[i] = cur;
}
}
和onload看起来像
nx = setInterval(function() { UpdateThis(); }, 42);
有人对如何提高速度有任何想法吗?
- 更新2 -
您可以下载包含HTML文件here(密码为密码)
的文件夹答案 0 :(得分:2)
移动功能可能很慢,因为它比简单的变量赋值有更多的事情要做。它必须实际渲染一些元素到其他地方。如果你在IE9上运行它,你可以测试这个。我预计它应该运行得更快,因为它使用硬件视频加速。
至于其他常规,我希望其他人会解剖它。 :)
你能描述一下球是如何移动的吗?偶尔?你如何为每个球打UpdateBall()
?你排队这些电话吗?
提供VMul
和VAdd
功能
你玩过造型吗?也许球的直接父母的相对定位可以加速渲染。并在其上设置overflow:hidden
。我不知道。取决于你是如何做到的。因此,JSFiddle会非常有帮助。
不是使用setInterval
来调用你的函数,你应该将它们排队并让它们尽可能快地执行。只是为了它,提供一个中央setInterval
和一些观察者,它们运行得不会太快。
但我猜它仍然会将你的处理器用于100%,这无论如何都不好。
非常重要的注意事项:启用Firebug时不要运行应用程序,因为众所周知,当Firebug运行时Javascript执行速度要慢得多。
答案 1 :(得分:2)
如何将位置更新与图纸分开?所以有类似的东西(未经测试的代码):
function DrawBall(ball)
{
ball.MoveTo(); //Take this line out of UpdateBall
}
-
function UpdateThis() {
for(var i = 0; i < balls.length; i++) {
var cur = balls[i];
UpdateBall(cur);
balls[i] = cur;
}
}
-
function DrawThis() {
for(var i = 0; i < balls.length; i++) {
DrawBall(balls[i]);
}
setTimeout(function() { DrawThis(); }, 42);
}
-
nx = setInterval(function() { UpdateThis(); }, 42);
setTimeout(function() { DrawThis(); }, 42);
如果确实是位置移动缓慢,这样逻辑更新仍然会在42ms发生,并且帧速率不会超过42ms,但它可以跳过帧。 (我实际上没有试过这个,所以这都是理论上的,你可能需要调整一些东西)
答案 2 :(得分:1)
这很难,如果MoveTo()实际上是你的瓶颈,因为那里没有很多东西。关于我能想到的唯一一件事,就是
1)缓存图像的样式属性和位置,以便更快地进行查找。每次在对象链中看到一个点时,都需要单步执行范围链。理想情况下,您可以在构造MoveTo()的父级时缓存此属性。
2)是否需要'px'字符串?它可能导致无效的CSS规范,但它仍然可以工作。我很难相信2弦串联会真的改变那么多。
这里的主要问题可能是,无论何时更改DOM,浏览器都会重新流动整个页面。您唯一的其他选择可能是重构,以便您实际上删除以前的内容,而不是更改样式,并将其替换为描述新状态的文档片段。这将导致整个步骤只有2个重新流动(1个用于移除,1个用于添加),而不是每个球2个。
编辑:关于上面的#1,当我说缓存时,我并不仅仅意味着在函数调用中本地。但也许作为父对象的闭包。例如:
var Ball = function(img){
var style = img.style;
var posX;
var posY;
function MoveTo(){
style.left = posX + "px";
style.right = posY + "px";
}
};