弹跳球组件
Bouncing Ball Component
我有一个弹跳球功能,它显示一个绿色的弹跳球并在屏幕上来回弹跳。但是,反复使用这个功能,球似乎每次调用都在加速,球速急剧增加。
function throwBall() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (!ballState.paused) {
requestAnimationFrame(throwBall);
}
if (ballState.cx + ballRadius >= canvas.width) {
ballState.vx = -ballState.vx * damping;
ballState.cx = canvas.width - ballRadius;
} else if (ballState.cx - ballRadius <= 0) {
ballState.vx = -ballState.vx * damping;
ballState.cx = ballRadius;
}
if (ballState.cy + ballRadius + floor >= canvas.height) {
ballState.vy = -ballState.vy * damping;
ballState.cy = canvas.height - ballRadius - floor;
// traction here
ballState.vx *= traction;
} else if (ballState.cy - ballRadius <= 0) {
ballState.vy = -ballState.vy * damping;
ballState.cy = ballRadius;
}
ballState.vy += gravity;
ballState.cx += ballState.vx;
ballState.cy += ballState.vy;
ctx.beginPath();
ctx.arc(ballState.cx, ballState.cy, ballRadius, 0, 2 * Math.PI, false);
ctx.fillStyle = '#2ed851';
ctx.fill();
}
我们将不胜感激。
However, on repeated use of this function, the ball seems to gather speed upon every call and the ball speed increases drastically.
我认为问题出在这里:
function throwBall() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (!ballState.paused) {
requestAnimationFrame(throwBall);
}
你调用这个函数一次,然后它通过 requestAnimationFrame(throwBall);
为之后的每一帧调用它自己。如果你再次调用这个函数,那么你现在又在做同样的事情,现在每帧调用两个 throwBall
函数,每帧更新位置和速度两次。然后,如果您第三次调用它,您将每帧更新三次位置和速度。
您通常想要做的是将每帧更新和渲染与会更改动画的事件分开。你在这里的功能实际上只是更新球的值,然后渲染球。它实际上并没有“抛出”任何东西。
那么让我们重命名该函数:
function updateAndDrawBall() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (!ballState.paused) {
requestAnimationFrame(updateAndDrawBall);
}
//...
}
然后在 canvas 存在时只调用一次:
updateAndDrawBall();
现在要“扔”球,您需要做的就是改变它的速度,updateAndDrawBall
将在下次渲染时对这些新值进行操作。
function throwBall() {
ballState.vx = 10
ballState.vy = -10
}
现在,当你想推球时就调用它,次数不限。
工作示例:
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const ballState = {
cx: 100,
cy: 100,
vx: 10,
vy: -10,
paused: false
};
const floor = 0;
const ballRadius = 20;
const damping = 0.85;
const traction = 0.9;
const gravity = 0.2;
function updateAndDrawBall() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (!ballState.paused) {
requestAnimationFrame(updateAndDrawBall);
}
if (ballState.cx + ballRadius >= canvas.width) {
ballState.vx = -ballState.vx * damping;
ballState.cx = canvas.width - ballRadius;
} else if (ballState.cx - ballRadius <= 0) {
ballState.vx = -ballState.vx * damping;
ballState.cx = ballRadius;
}
if (ballState.cy + ballRadius + floor >= canvas.height) {
ballState.vy = -ballState.vy * damping;
ballState.cy = canvas.height - ballRadius - floor;
// traction here
ballState.vx *= traction;
} else if (ballState.cy - ballRadius <= 0) {
ballState.vy = -ballState.vy * damping;
ballState.cy = ballRadius;
}
ballState.vy += gravity;
ballState.cx += ballState.vx;
ballState.cy += ballState.vy;
ctx.beginPath();
ctx.arc(ballState.cx, ballState.cy, ballRadius, 0, 2 * Math.PI, false);
ctx.fillStyle = "#2ed851";
ctx.fill();
}
updateAndDrawBall(); // call this only once
function throwBall() {
ballState.vx = 10
ballState.vy = -10
}
document.getElementById('throw')?.addEventListener('click', throwBall)
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
</head>
<body>
<button id="throw" value="Throw Ball">Throw Ball</button>
<br />
<canvas id="canvas" width="200" height="200" />
<script src="src/index.ts"></script>
</body>
</html>
我有一个弹跳球功能,它显示一个绿色的弹跳球并在屏幕上来回弹跳。但是,反复使用这个功能,球似乎每次调用都在加速,球速急剧增加。
function throwBall() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (!ballState.paused) {
requestAnimationFrame(throwBall);
}
if (ballState.cx + ballRadius >= canvas.width) {
ballState.vx = -ballState.vx * damping;
ballState.cx = canvas.width - ballRadius;
} else if (ballState.cx - ballRadius <= 0) {
ballState.vx = -ballState.vx * damping;
ballState.cx = ballRadius;
}
if (ballState.cy + ballRadius + floor >= canvas.height) {
ballState.vy = -ballState.vy * damping;
ballState.cy = canvas.height - ballRadius - floor;
// traction here
ballState.vx *= traction;
} else if (ballState.cy - ballRadius <= 0) {
ballState.vy = -ballState.vy * damping;
ballState.cy = ballRadius;
}
ballState.vy += gravity;
ballState.cx += ballState.vx;
ballState.cy += ballState.vy;
ctx.beginPath();
ctx.arc(ballState.cx, ballState.cy, ballRadius, 0, 2 * Math.PI, false);
ctx.fillStyle = '#2ed851';
ctx.fill();
}
我们将不胜感激。
However, on repeated use of this function, the ball seems to gather speed upon every call and the ball speed increases drastically.
我认为问题出在这里:
function throwBall() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (!ballState.paused) {
requestAnimationFrame(throwBall);
}
你调用这个函数一次,然后它通过 requestAnimationFrame(throwBall);
为之后的每一帧调用它自己。如果你再次调用这个函数,那么你现在又在做同样的事情,现在每帧调用两个 throwBall
函数,每帧更新位置和速度两次。然后,如果您第三次调用它,您将每帧更新三次位置和速度。
您通常想要做的是将每帧更新和渲染与会更改动画的事件分开。你在这里的功能实际上只是更新球的值,然后渲染球。它实际上并没有“抛出”任何东西。
那么让我们重命名该函数:
function updateAndDrawBall() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (!ballState.paused) {
requestAnimationFrame(updateAndDrawBall);
}
//...
}
然后在 canvas 存在时只调用一次:
updateAndDrawBall();
现在要“扔”球,您需要做的就是改变它的速度,updateAndDrawBall
将在下次渲染时对这些新值进行操作。
function throwBall() {
ballState.vx = 10
ballState.vy = -10
}
现在,当你想推球时就调用它,次数不限。
工作示例:
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const ballState = {
cx: 100,
cy: 100,
vx: 10,
vy: -10,
paused: false
};
const floor = 0;
const ballRadius = 20;
const damping = 0.85;
const traction = 0.9;
const gravity = 0.2;
function updateAndDrawBall() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (!ballState.paused) {
requestAnimationFrame(updateAndDrawBall);
}
if (ballState.cx + ballRadius >= canvas.width) {
ballState.vx = -ballState.vx * damping;
ballState.cx = canvas.width - ballRadius;
} else if (ballState.cx - ballRadius <= 0) {
ballState.vx = -ballState.vx * damping;
ballState.cx = ballRadius;
}
if (ballState.cy + ballRadius + floor >= canvas.height) {
ballState.vy = -ballState.vy * damping;
ballState.cy = canvas.height - ballRadius - floor;
// traction here
ballState.vx *= traction;
} else if (ballState.cy - ballRadius <= 0) {
ballState.vy = -ballState.vy * damping;
ballState.cy = ballRadius;
}
ballState.vy += gravity;
ballState.cx += ballState.vx;
ballState.cy += ballState.vy;
ctx.beginPath();
ctx.arc(ballState.cx, ballState.cy, ballRadius, 0, 2 * Math.PI, false);
ctx.fillStyle = "#2ed851";
ctx.fill();
}
updateAndDrawBall(); // call this only once
function throwBall() {
ballState.vx = 10
ballState.vy = -10
}
document.getElementById('throw')?.addEventListener('click', throwBall)
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
</head>
<body>
<button id="throw" value="Throw Ball">Throw Ball</button>
<br />
<canvas id="canvas" width="200" height="200" />
<script src="src/index.ts"></script>
</body>
</html>