好的,首先,工作的代码。
<html>
<head>
<style>
body, html {
margin: 0;
padding: 0;
}
#canvas {
background-color: black;
}
</style>
<script>
function drawArc() {
ctx.beginPath();
ctx.fillStyle = "white";
ctx.arc(ax, ay, radius, 0, 2 * Math.PI);
ctx.fill();
ctx.closePath();
};
function update() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawArc();
ax += avx;
ay -= avy;
avy -= 0.2;
if (ay + radius >= canvas.height) {
avy *= -0.8;
avx *= 0.9;
};
if (ax + radius >= canvas.width) {
avx = -avx;
};
if (ax - radius <= 0) {
avx = -avx;
};
}
function onload()
{
canvas = document.getElementById('canvas');
ctx = canvas.getContext('2d');
ax = 50;
ay = 50;
avx = 5;
avy = 2;
radius = 50;
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
setInterval(update, 10);
}
</script>
<style>
</style>
</head>
<body onload="onload()">
<canvas id="canvas"></canvas>
</body>
</html>
第二,问题是什么。我认为我遇到的最大问题是您提供的代码在全局上下文中具有变量和操作,这些变量和操作依赖于尚未创建的页面元素。这意味着canvas和cxt的变量不能被创建,因为canvas标签还没有被创建。我把所有这些都放到了一个函数中,当页面加载完毕并且一切正常时,我可以调用它。现在,当调用该函数时,画布已经存在,您可以使用它来创建上下文并执行其他所有操作。
第三基于你想知道它为什么停止弹跳的问题标题。我认为你已经正确地创建了一个弹跳球,它从墙壁和地板上反弹,但由于重力和与地面的非弹性碰撞而损失了能量。就个人而言,我没有完成代码,但它看起来很棒。你为什么要改变它。如果你想让它永远弹跳,那么与墙壁和地板的碰撞需要 100% 弹性——这意味着你不会失去任何能量,并且你的球弹跳得和以前一样高。在与 FLOOR 的交互中,您使用下面的代码。这具有阻尼效果,并最终将您的球降至零能量。
avy *= -0.8;//could be -1
avx *= 0.9;//could be 1
然而,这又产生了另一个问题。您正在使用的代码需要阻尼,否则每次弹跳时球只会弹得更高。这是因为你在这条线上加速并获得能量。
avy -= 0.2;
您的其他答案之一建议您减少阻尼,但不要通过更改这一行来完全消除它。您必须对其进行调整以使其具有您想要的行为。
avy *= -0.8;//-0.8 is too little? -1 is too much
最后一次编辑,我保证。我实际上玩得很开心。这个问题并不是微不足道的,您可以只输入伪物理并获得一个很好的球弹跳模拟。即使你输入了所有正确的方程,你仍然会得到一个小的永久反弹,因为这就是现实生活中发生的事情。当球移动得足够慢并且离地面足够近时,其他力(不是重力,而是强、弱和电磁吸引力)占主导地位并导致球停止移动。所以,我又刷了一遍,物理性能有了很大的提高。它并不完美,但在某些时候你不得不问模拟的保真度是否比平滑行为以匹配我想要看到的更重要。希望这会有所帮助。
<html>
<head>
<style>
body, html {
margin: 0;
padding: 0;
}
#canvas {
background-color: black;
}
</style>
<script>
function drawArc() {
ctx.beginPath();
ctx.fillStyle = "white";
ctx.arc(xPos, yPos, radius, 0, 2 * Math.PI);
ctx.fill();
ctx.closePath();
};
function update() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawArc();
var dx = xVel*timeStep;
var dy = yVel*timeStep;
if(yVel<radius && yVel>-radius && canvas.height-(yPos+radius) < .1)
{
yVel = 0;
yPos = canvas.height-radius;
dy=0;
//friction affects xVel
xVel *= fFloor;
}
else if (yPos + dy + radius >= canvas.height) {
//you will be below the floor; there is a bounce
//find the rest of the falling interval
var remainingY = canvas.height-(yPos+radius);
//find the rest of the time step
var remainingTime = remainingY / yVel;
//add acceleration for that time
yVel += gravity * remainingTime
//friction affects xVel
xVel *= fFloor;
//elasticity affects yVel
yVel *= eFloor;
//now you are bouncing up
//what is time up
remainingTime = timeStep - remainingTime;
//set final position
yPos = canvas.height + (yVel*remainingTime) - radius;
//add acceleration for that time
yVel += gravity * remainingTime;
}
else
{
//do not hit the floor, falling the whole time
yPos += dy;
yVel += gravity * timeStep;
}
if (xPos + dx + radius >= canvas.width)
{
//hit a wall; there is a bounce
//find the rest of the interval
var remainingX = canvas.width-(xPos+radius);
//find the rest of the time step
var remainingTime = remainingX / xVel;
//no horizontal acceleration
//friction affects yVel
yVel *= fWall;
//elasticity affects xVel
xVel *= eWall;
//now you are bouncing back
//what is time up
remainingTime = timeStep - remainingTime;
//set final position
xPos = canvas.width + (xVel*remainingTime) - radius;
//no horizontal acceleration
}
else if (xPos + dx - radius <= 0) {
//hit a wall; there is a bounce
//find the rest of the interval
var remainingX = (xPos - radius);
//find the rest of the time step
var remainingTime = remainingX / xVel;
//no horizontal acceleration
//friction affects yVel
yVel *= fWall;
//elasticity affects xVel
xVel *= eWall;
//now you are bouncing back
//what is time up
remainingTime = timeStep - remainingTime;
//set final position
xPos = xVel*remainingTime+radius;
//no horizontal acceleration
}
else {
//never hit a wall; flying the whole time
xPos += dx;
}
}
function onload()
{
canvas = document.getElementById('canvas');
ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
radius = 15;
xPos = Math.random()*(canvas.width-(2*radius))+radius;
yPos = Math.random()*(canvas.height-(2*radius))+radius;
xVel = Math.random()*100-50;
yVel = Math.random()*100-50;
gravity = 9.8;
eWall = -1;
eFloor = -.8;
fFloor = .9;
fWall = .9;
interval = 10;
timeStep = .1;//apparent time step
setInterval(update, interval);
}
</script>
<style>
</style>
</head>
<body onload="onload()">
<canvas id="canvas"></canvas>
</body>
</html>