2016-10-02 77 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>