我正在尝试创建一个弹跳球(在画布上)。如果球在上下起伏时会加速,我会很高兴。不知道如何使用setInterval执行此操作。这是我的代码:
setInterval(function animate() {
ctx.clearRect( 0, 0, canvas.width, canvas.height);
if (movement1 === true) {
dotHeight += 1;
if (dotHeight >= 100) movement1 = false;
} else {
dotHeight -= 1;
if (dotHeight <= 0) movement1 = true;
}
ctx.beginPath();
ctx.arc(canvas.width / 2, (canvas.height / 2) + dotHeight, dotSize, 0, 2 * Math.PI);
ctx.fillStyle = "white";
ctx.fill();
}, 4);
这导致线性运动。我希望有一个自然的运动。基本上快速启动并在到达顶部时变慢,反之亦然。
答案 0 :(得分:2)
基本原理是使用速度变量而不是恒定的高度增量。因此,除了dotHeight += 1
或dotHeight -= 1
之外,您可以在dotHeight += dotVelocity
处定义dotVelocity,并在球在空中时将其减去常数值(重力)。
var dotHeight = 0;
var dotVelocity = 3; // start out moving up, like in your example
var gravity = .1; // you can adjust this constant for stronger/weaker gravity
setInterval(function animate() {
ctx.clearRect( 0, 0, canvas.width, canvas.height);
if (dotHeight > 0) { // if it hit the ground, stop movement
dotVelocity -= gravity;
dotHeight += dotVelocity;
}
ctx.beginPath();
ctx.arc(canvas.width / 2, (canvas.height / 2) + dotHeight, dotSize, 0, 2 * Math.PI);
ctx.fillStyle = "white";
ctx.fill();
}, 4);
答案 1 :(得分:2)
您应该同时拥有speed
和gravity
(或acceleration
)变量:
speed
告诉您在当前更新中移动对象的单位数(此处为像素数)。gravity
告诉您每次更新时增加了speed
个单位。您想要一个常量gravity
,以便speed
在每次更新时增加相同数量的像素。这将为您提供变量speed
,以便您的对象(此处为点)在每次更新时移动更长或更短的距离,具体取决于其行进方向。
要使点反弹,只需更改其speed
到达地面时的方向。您只需要将其乘以-1
,或者相反,您可以将其乘以bouncingFactor
(-1 < bouncingFactor < 0
),以便在每次反弹时失去能量:
在这里你可以看到一个有效的例子:
var canvas = document.getElementById("canvas");
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
var ctx = canvas.getContext("2d");
var frames = 0; // Frame counter just to make sure you don't crash your browser while editing code!
// DOT STUFF:
var dotSize = 20;
var dotMinY = 0 + dotSize; // Start position
var dotMaxY = canvas.height - dotSize; // Floor
var dotY = dotMinY;
var dotSpeed = 0;
var dotLastBounceSpeed = 0; // You can use this to determine whether the ball is still bouncing enough to be visible by the user.
var center = canvas.width / 2; // Try to take every operation you can out of the animate function.
var pi2 = 2 * Math.PI;
// WORLD STUFF:
var gravity = .5;
var bounceFactor = .8; // If < 1, bouncing absorbs energy so ball won't go as high as it was before.
// MAIN ANIMATION LOOP:
function animate() {
ctx.clearRect( 0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.arc(center, dotY, dotSize, 0, pi2);
ctx.fillStyle = "red";
ctx.fill();
// First, dotSpeed += gravity is calculated and that returns the new value for dotSpeed
// then, that new value is added to dotY.
dotY += dotSpeed += gravity;
if(dotY >= dotMaxY ) {
dotY = dotMaxY;
dotSpeed *= -bounceFactor;
}
var dotCurrentBounceSpeed = Math.round(dotSpeed * 100); // Takes two decimal digits.
if(frames++ < 5000 && dotLastBounceSpeed != dotCurrentBounceSpeed) {
dotLastBounceSpeed = dotCurrentBounceSpeed;
setTimeout(animate, 16); // 1000/60 = 16.6666...
}
else alert("Animation end. Took " + frames + " frames.");
}
animate();
html, body, #canvas {
position:relative;
width: 100%;
height: 100%;
margin: 0;
overflow:hidden;
}
<canvas id="canvas"></canvas>
您还应该考虑使用setTimeout
requestAnimationFrame
。来自MDN doc:
Window.requestAnimationFrame()方法告诉浏览器您 希望执行动画并请求浏览器调用 指定在下次重绘前更新动画的函数。该 method将一个回调作为一个参数,在之前调用 重绘。
与var canvas = document.getElementById("canvas");
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
var ctx = canvas.getContext("2d");
var frames = 0; // Frame counter just to make sure you don't crash your browser while editing code!
// DOT STUFF:
var dotSize = 20;
var dotMinY = 0 + dotSize; // Start position
var dotMaxY = canvas.height - dotSize; // Floor
var dotY = dotMinY;
var dotSpeed = 0;
var dotLastBounceSpeed = 0; // You can use this to determine whether the ball is still bouncing enough to be visible by the user.
var center = canvas.width / 2; // Try to take every operation you can out of the animate function.
var pi2 = 2 * Math.PI;
// WORLD STUFF:
var gravity = .5;
var bounceFactor = .8; // If < 1, bouncing absorbs energy so ball won't go as high as it was before.
// MAIN ANIMATION LOOP:
function animate() {
ctx.clearRect( 0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.arc(center, dotY, dotSize, 0, pi2);
ctx.fillStyle = "red";
ctx.fill();
// First, dotSpeed += gravity is calculated and that returns the new value for dotSpeed
// then, that new value is added to dotY.
dotY += dotSpeed += gravity;
if(dotY >= dotMaxY ) {
dotY = dotMaxY;
dotSpeed *= -bounceFactor;
}
var dotCurrentBounceSpeed = Math.round(dotSpeed * 100); // Takes two decimal digits.
if(frames++ < 5000 && dotLastBounceSpeed != dotCurrentBounceSpeed) {
dotLastBounceSpeed = dotCurrentBounceSpeed;
//setTimeout(animate, 10);
window.requestAnimationFrame(animate); // Better!!
}
else alert("Animation end. Took " + frames + " frames.");
}
animate();
相同的示例:
html, body, #canvas {
position:relative;
width: 100%;
height: 100%;
margin: 0;
overflow:hidden;
}
<canvas id="canvas"></canvas>
setTimeout
如您所见,您只需要更改一行代码!但是,如果浏览器不支持requestAnimationFrame
,您可能需要requestAnimationFrame
才能回到requestAnimationFrame
。
您可以在polyfill中详细了解bundle
。它解释了基础知识以及如何设置自定义帧速率。
答案 2 :(得分:1)
您可以使用age_range
变量而不是常量age_range
来确定&#34; far&#34;移动球,像这样:
{{1}}