7

見栄えの良い物理ゲームをコーディングしようとしています。

ボールの衝突は見栄えがしますが、ボールの衝突が遅すぎると、互いに「くっついて」しまいます。なぜ彼らがそうするのか、私にはわかりません。

これが私の衝突関数です:

private void checkForCollision(ArrayList<Ball> balls) {
    for (int i = 0; i < balls.size(); i++) {
        Ball ball = balls.get(i);
        if (ball != this && ball.intersects(this)) {
            this.collide(ball, false);
        }
    }
}

public boolean intersects(Ball b) {
    double dx = Math.abs(b.posX - posX);
    double dy = Math.abs(b.posY - posY);
    double d = Math.sqrt(dx * dx + dy * dy);
    return d <= (radius + b.radius);
}

private void collide(Ball ball, boolean b) {
    double m1 = this.radius;
    double m2 = ball.radius;
    double v1 = this.motionX;
    double v2 = ball.motionX;

    double vx = (m1 - m2) * v1 / (m1 + m2) + 2 * m2 * v2 / (m1 + m2);

    v1 = this.motionY;
    v2 = ball.motionY;
    double vy = (m1 - m2) * v1 / (m1 + m2) + 2 * m2 * v2 / (m1 + m2);

    if (!b)
        ball.collide(this, true);
    System.out.println(vx + " " + vy);
    motionX = vx * BOUNCEOBJECT;
    motionY = vy * BOUNCEOBJECT;
}

しかし、低速で衝突するとこうなります。 ここに画像の説明を入力

アイデアはありますか?

編集:

Alnitakの更新は非常にうまく機能します...しかし、1 つの問題がまだ残っています...次のように重力を追加すると:

public void physic() {
    motionY += GRAVITY;                  // <= this part (GRAVITY is set to 0.3D)
    checkForCollision(screen.balls);
    keyMove();
    bounceWalls();

    posX += motionX;
    posY += motionY;
}

彼らはまだお互いに移動します。これは重力を追加する間違った方法だと思いますか、そうではありませんか?

そして、衝突式が正しくないため、衝突式で何か間違ったことをしたと思います。

!落ちるボール

そしてゆっくりと地面に沈んでいきます。

編集: すばらしいチュートリアルを見つけました: http://www.ntu.edu.sg/home/ehchua/programming/java/J8a_GameIntro-BounceBalls.html

4

3 に答える 3

8

これは、跳ねるボールのデルタ v が衝突ゾーンからボールを​​戻すのに不十分な場合があるために発生する一般的な問題です。

したがって、衝突ルーチンは再び方向を逆転させ、無限に他のボールの中に戻します。

新しく計算された位置が衝突しないように、(衝突力の方向に) 十分なオフセットをボールの位置に追加する必要があります。

または、新しい値を追加したときにボールが衝突するかどうかを確認します。motion

public boolean intersects(Ball b) {
    double dx = b.posX - (posX + motionX);  // no need for Math.abs()
    double dy = b.posY - (posY - motionY);
    double d = dx * dx + dy * dy;           // no need for Math.sqrt()
    return d < (radius + b.radius) * (radius + b.radius);
}

ball.intersects(this)に変更する必要がありますintersects(ball)

衝突が少し早すぎるように見えるかもしれませんが、動きの速いボールではおそらく見えないでしょう。

于 2012-08-29T18:20:19.223 に答える
1
(m1 - m2) * v1 / (m1 + m2) + 2 * m2 * v2 / (m1 + m2);

これは整数値 2 です。2.0f または 2.0d にしてからチェックしてください。それは小さな速度の問題に違いありません。整数定数は乗算された double を自動キャストするためです。

これでうまくいかない場合は、Alnitakの回答が役に立ちます。

本当に素晴らしい物理が必要な場合は、を使用してから、速度に変換してから変位に変換する必要があります。Runge KuttaEuler Integrationなどの積分手法を見てください。

Force-->acceleration-->velocity-->displacement

衝突が発生した場合は、力を更新するだけで、残りは流れます。

----> http://codeflow.org/entries/2010/aug/28/integration-by-example-euler-vs-verlet-vs-runge-kutta/ <-----

http://www.forums.evilmana.com/game-programming-theory/euler-vs-verlet-vs-rk4-physics/

http://www.newagepublishers.com/samplechapter/001579.pdf

http://cwx.prenhall.com/bookbind/pubbooks/walker2/

Verlet 積分は、 Runge-Kutta-4Euler 積分の間のポイントであり、できれば分子動力学に適しています (電場と結合を省略した場合の跳ねるボールの良い例です)。

于 2012-08-29T18:19:17.753 に答える
0

すばらしいチュートリアルを見つけました: http://www.ntu.edu.sg/home/ehchua/programming/java/J8a_GameIntro-BounceBalls.html

于 2012-09-20T20:12:33.260 に答える