0

物理/粒子シミュレーターを使い始めましたが、衝突検出に問題があります。

http://mmhudson.com/physics.html

コードの解決策を探しているわけではありませんが、問題を概念的に説明してくれる人がいます。

それが機能する方法は、パーティクルが次に移動されたときにオブジェクトの内側にあるか、オブジェクトと交差するかどうかを確認することです。そうである場合、重力の乗数が逆になるため、その方向が逆になります。

私が使用する運動の方程式は次のとおりです。

次の場所 = 現在の速度 + 重力の速度 + 現在の場所

速度が重力乗数である場合

うまくいけば、誰かが以前にこのような問題を見たことがあるか、私のページのソースをチェックアウトしたいと思っています.

どんな助けでも大歓迎です

4

2 に答える 2

2

概念的な説明はありませんが、ランダムな観察結果の束:

キャンバスの幅/高さの変数を追加して、それらをパーティクルの位置と比較することをお勧めします。現在、パーティクルがキャンバスから落ちても、パーティクルは落ち続けています。何かのようなもの:

if( particles[i][1] > height )
    particles.splice(i,1);

newPY < objects[k][2] + objects[k][3] + radius

本当に奇妙です。これから何を得ますか?オブジェクトの幅と高さと粒子の半径を追加しますか? この部分を外すと、「勢い」があればパーティクルが跳ね返ります。


運動量に関しては、パーティクルがオブジェクトを通って落ちるのを止める方法を理解したいと思っていると思います。現在のコードを考えると、次のようにします。5 番目の変数をパーティクルに追加します。既定値はキャンバスの高さです。そして、着弾していることがわかったら、着弾位置をパーティクルに保存し、ループ後にパーティクルがそのポイントより下にあるかどうかを確認します。その場合は、その時点までリセットしてください。汚い修正ですが、まあ、うまくいきます。私のために働いた以下の完全なループを追加しました。オブジェクトが clearRect メソッドによって一掃されるのを防ぐには、オブジェクトを再描画することを検討してください。


オブジェクトの上にあるパーティクルのみをチェックしていますが、「落下」の側面はあなたが尋ねたバグの一部であると想定しているため、現時点ではあまり重要ではありません:

particles[i][1] < objects[k][1] + objects[k][3] + radius 

ただし、いろいろ試して重力を減らすことにした場合は、代わりにパーティクルが勢いを増し、上のオブジェクトに跳ね返る可能性があります。


objCheck 変数に関しては、最後の && 部分で y の幅を混同しています。そのはず:

mY < objects[i][1] + objects[i][3] + radius 

それ以外の

mY < objects[i][2] + objects[i][3] + radius

現在、objCheck は機能していません。


また

for(var i=0; i < particles.length; i++) {
    var clrRadius = 2*radius;
    canvas.clearRect(particles[i][0]-radius, particles[i][1]-radius, clrRadius, clrRadius);
}

よりも良い

for(var i=0; i < particles.length; i++){
    var clrRadius = radius + 4;
    canvas.clearRect(particles[i][0]-(clrRadius/2), particles[i][1]-(clrRadius/2), clrRadius, clrRadius);
}

編集:私が最後にチェックして以来、コードを変更したようです。そのため、上記は関係ない可能性があります!

edit2: パーティクル停止の修正を追加。完全な重力ループは次のとおりです。

for(var i=0; i<particles.length; i++){
var clrRadius = 2*radius;
canvas.clearRect(particles[i][0]-radius, particles[i][1]-radius, clrRadius, clrRadius);
}

for(var i=0; i < particles.length; i++){
var newPY = particles[i][1] += particles[i][2] + particles[i][3];

for(var k=0; k<objects.length; k++){
    if(
        //particle
        particles[i][0] > objects[k][0] - radius && 
        particles[i][0] < objects[k][0] + objects[k][2] + radius && 
        particles[i][1] > objects[k][1] - radius &&
        particles[i][1] < objects[k][1] + objects[k][3] + radius //&& 
    ){
            //reverse gravity
            particles[i][2] = particles[i][2] * -1;
            particles[i][5] = objects[k][1] - radius;
    }
}


particles[i][2] += particles[i][3]*weight;
particles[i][1] += particles[i][2];

if( particles[i][1] > particles[i][5] )
    particles[i][1] = particles[i][5];

if( particles[i][1] > height )
    particles.splice(i,1);
}

for(var i=0; i <particles.length; i++){
canvas.fillStyle = "#000";
canvas.beginPath();
canvas.arc(particles[i][0], particles[i][1], radius, 0, Math.PI*2, true);
canvas.closePath();
canvas.fill();
}
于 2012-07-02T10:35:50.173 に答える
0

私は重力乗数を使用しません。

各オブジェクトは次のようになります。

var circle = {
    x: 0,   // x position
    y: 0,   // y position
    dx: 0,  // x velocity
    dy: 0   // y velocity
}

粒子を更新するには、速度 (dx, dy) に時間間隔を掛けて、これを現在の位置に追加します。

サイクルごとに、重力の結果として速度の変化を追加します。

衝突を検出した場合は、円が互いに跳ね返るように速度を変更します。この例は次のようになります。

// In a collision, simply reverse the direction of movement
// so the circles move away from each other.

function onCollision(circleA, circleB) {
    circleA.dx *= -1;
    circleA.dy *= -1;

    circleB.dx *= -1;
    circleB.dy *= -1;
}
于 2012-07-02T02:22:46.827 に答える