2016-10-02 63 views
2

这里是JavaScript:球停止反弹后4-5秒

var 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; 
 

 
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; 
 
    }; 
 
} 
 
setInterval(update, 10);
body, html { 
 
    margin: 0; 
 
    padding: 0; 
 
} 
 
#canvas { 
 
    background-color: black; 
 
}
<canvas id="canvas"></canvas>

在此间举行的jsfiddle:https://jsfiddle.net/milosdacic/qh1ha085/

我不知道为什么会这样,代码似乎精细。

我以前做过这件事,但现在它不起作用。

任何帮助将不胜感激。

+0

你想让它永远反弹吗? –

+1

你预计会发生什么?你已经编码,在每次击球时,球的速度都会降低(摩擦)。所以在一段时间后球停止移动是正常的。 – trincot

+0

如果你不想松动高度,你需要跟踪每次反弹时的所有动能。这个答案http://stackoverflow.com/a/34187884/3877726演示如何做一个简单的弹跳球随着时间的推移不会消耗能量。 http://stackoverflow.com/a/34187884/3877726 – Blindman67

回答

3

简短的回答是,你会得到很多点击,因为你没有将球移离地面。下一帧它仍然会影响地面,并且随着你降低速度,它会慢慢下降。

在你的小提琴的第29行后面添加这个。

ay = canvas.height - radius; 

For more on bouncing a ball

+0

非常感谢。你们这里真棒:) –

1

我想你想的:

var 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; 
 

 
function drawArc() { 
 
    ctx.beginPath(); 
 
    ctx.fillStyle = "white"; 
 
    ctx.arc(ax, ay, radius, 0, 2 * Math.PI); 
 
    ctx.fill(); 
 
    ctx.closePath(); 
 
}; 
 

 
var hitTheGround = 0; 
 
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; 
 
    } 
 
    
 
    if(ay + radius >= canvas.height - 3) { 
 
    hitTheGround++; 
 
    } 
 
    else { 
 
    hitTheGround = 0; 
 
    } 
 
    
 
    if(hitTheGround == 100) { // if it jumps near the ground too frequently 
 
    return setTimeout(function() {clearInterval(interval)}, 1000); 
 
    } 
 
} 
 
var interval = setInterval(update, 10);
body, html { 
 
    margin: 0; 
 
    padding: 0; 
 
} 
 
#canvas { 
 
    background-color: black; 
 
}
<canvas id="canvas"></canvas>

点点脏修复停止调用比它跳(振动)附近的地面N次之后更新。

+0

没有看到最后的评论,修复... – num8er

+0

我不想要无限的弹跳我只是想正常弹跳,而不是在几次落地之后冻结。只要看球弹跳5-6秒,你会看到有一点球刚刚冻结在地板上。 –

+0

好吧,等待我正在修复 – num8er

0

好吧,首先,该工程的代码。

<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 

最后编辑,我承诺。我其实有很多乐趣。问题并非如此简单,以至于您只需放入仿真物理并获得球弹跳的良好模拟。即使你输入所有正确的方程,你仍然会得到一个小的永久反弹,因为这是现实生活中发生的。当球足够慢地移动并且足够靠近地面时,其他力(不是重力,但强,弱和电磁吸引力)占主导地位,并导致球停止移动。所以,我再一次轻扫一下,改善了物理学。这并不完美,但在某些时候,你必须要问的是,模拟的FIDELITY比平滑行为与我想要看到的要更重要。希望这可以帮助。

<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>