我想制作一个弹跳球,我可以在其中调整弹跳速度
这是我的原始代码
<script>
var context;
var x=100;
var y=200;
var dx=5;
var dy=5;
function init()
{
context= myCanvas.getContext('2d');
setInterval(draw,100);
}
function draw()
{
context.clearRect(0,0, 300,300);
context.beginPath();
context.fillStyle="#B76EB8";
// Draws a circle of radius 20 at the coordinates 100,100 on the canvas
context.arc(x,y,20,0,Math.PI*2,true);
context.closePath();
context.fill();
if( (x-20)<0 || (x+20)>300) dx=-dx;
if( (y-20)<0 || (y+20)>300) dy=-dy;
x+=dx;
y+=dy;
}
</script>
然而,当我通过setInterval
降低球速时,我发现动画滞后所以我用了
function init()
{
context= myCanvas.getContext('2d');
(function animloop(){
requestAnimFrame(animloop);
draw();
setTimeout(animLoop, 1);
})();
}
使动画更流畅
但是现在我根本无法调整弹跳球的速度,还有其他建议的方法可以实现我的目标吗?
由于
答案 0 :(得分:1)
超时/间隔应不小于约20毫秒,动画功能应根据 delta-time elapsed 设置动画。这将产生一致的动画(离散位置函数可能更好,但简单的delta时间方法通常可以很好地工作)。
然后可以控制整个球速(并且独立于)任何间隔量。请记住公式:d = d0 + v * t
。原始代码缺少t
( delta-time )组件,x+=dx
实际上等同于x = x0 + dx * 1
。但是,间隔之间的时间不必是恒定的,应该用一点数学来补偿。
考虑this demo:
var interval=20;
var x=100;
var y=200;
var dx=100/1000; // px/1000millis
var dy=100/1000;
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var w=canvas.getAttribute("width") || 0;
var h=canvas.getAttribute("height") || 0;
var prevTime = +(new Date)
function draw()
{
var now = +(new Date)
var delta = now - prevTime;
if (delta < 5) {
// Timeout occured too fast, we could be "stacking"
// setInterval events, abort!
return;
}
prevTime = now;
// We now have "delta time millis" to get work done
// Do movement before draw
// (This bound check can actually get the
// ball stuck, but that's a different question!)
if( (x-20)<0 || (x+20)>w ) dx = -dx;
if( (y-20)<0 || (y+20)>h ) dy = -dy;
// Apply delta time
x = x + dx * delta;
y = y + dy * delta;
context.clearRect(0, 0, w, h);
context.beginPath();
context.fillStyle="#B76EB8";
context.arc(x,y,20,0,Math.PI*2,true);
context.closePath();
context.fill();
}
// Uset setInterval because it will "reprime" the next timeout
// callback faster and more consistently.
setInterval(draw, interval);
请注意,更改间隔延迟会使动画更平滑,但不会影响整体球移动速度(由于边缘碰撞的处理方式,这有点谎言)。尝试将间隔从20改为10,50,100并观察结果。
答案 1 :(得分:1)
如果你想要更少的&#34;抖动&#34;以动画中较慢的移动为代价,然后设置dx&amp; dy == 1.
这样,用户以较小的增量观看球的移动,而不是#34;跳跃&#34;。
您可以考虑使用requestAnimationFrame来运行动画循环。它为您提供了一个时间戳,您可以使用该时间戳将动画限制为每秒帧数:
以下是示例代码:http://jsfiddle.net/m1erickson/Y9bYv/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" />
<script src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var context=canvas.getContext("2d");
var x=100;
var y=200;
var dx=1;
var dy=1;
var start;
var fps=30;
var delay=1000/fps;
requestAnimationFrame(animate);;
function draw(){
context.clearRect(0,0, 300,300);
context.beginPath();
context.fillStyle="#B76EB8";
// Draws a circle of radius 20 at the coordinates 100,100 on the canvas
context.arc(x,y,20,0,Math.PI*2,true);
context.closePath();
context.fill();
}
function animate(time) {
requestAnimationFrame(animate);
if(start===null){start=time;}
var elapsed=time-start;
if(elapsed<delay){return;}
draw();
start=time;
x+=dx;
y+=dy;
if(x<20){ dx=-dx; x=20; }
if(x>280){ dx=-dx; x=280; }
if(y<20){ dy=-dy; y=20; }
if(y>280){ dy=-dy; y=280; }
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=350 height=350></canvas>
</body>
</html>