7

3つのビーチボールが画面上で跳ね返るアニメーション(Python)をコーディングしました。私は今、それらすべてを衝突させ、互いに跳ね返らせることができるようにしたいと思っています。私は本当に提供できるどんな助けにも感謝します。

import pygame
import random
import sys
class Ball:


    def __init__(self,X,Y):

        self.velocity = [1,1]
        self.ball_image = pygame.image.load ('Beachball.jpg'). convert()
        self.ball_boundary = self.ball_image.get_rect (center=(X,Y))
        self.sound = pygame.mixer.Sound ('Thump.wav')
        self.rect = self.ball_image.get_rect (center=(X,Y))

if __name__ =='__main__':

    width = 800
    height = 600
    background_colour = 0,0,0
    pygame.init()
    window = pygame.display.set_mode((width, height))
    pygame.display.set_caption("Bouncing Ball animation")
    num_balls = 3
    ball_list = []
    for number in range(num_balls):
        ball_list.append( Ball(random.randint(10, (width - 10)),random.randint(10, (height - 10))) )
    while True:
        for event in pygame.event.get():
                print event 
                if event.type == pygame.QUIT:
                        sys.exit(0)
        window.fill (background_colour)

        for ball in ball_list:
                if ball.ball_boundary.left < 0 or ball.ball_boundary.right > width:
                        ball.sound.play()
                        ball.velocity[0] = -1 * ball.velocity[0]
                if ball.ball_boundary.top < 0 or ball.ball_boundary.bottom > height:
                        ball.sound.play()
                        ball.velocity[1] = -1 * ball.velocity[1]

                ball.ball_boundary = ball.ball_boundary.move (ball.velocity)
                window.blit (ball.ball_image, ball.ball_boundary)
        pygame.display.flip()
4

7 に答える 7

10

任意の形状の衝突検出は、ピクセルが衝突するかどうかを把握する必要があるため、通常は非常に注意が必要です。

これは実際にはサークルを使用すると簡単です。半径r1とr2の2つの円がある場合、中心間の距離がr1 + r2未満の場合、衝突が発生しています。

2つの中心(x1、y1)と(x2、y2)の間の距離は、次のように計算および比較できます。

d = sqrt((y2-y1) * (y2-y1) + (x2-x1) * (x2-x1));
if (d < r1 + r2) { ... bang ... }

または、jfclavetteが指摘しているように、平方根は高価であるため、単純な操作を使用して計算する方がよい場合があります。

dsqrd = (y2-y1) * (y2-y1) + (x2-x1) * (x2-x1);
if (dsqrd < (r1+r2)*(r1+r2)) { ... bang ... }

現在の移動ベクトルと接触点を考慮する必要があるため、新しい移動ベクトル(特定のオブジェクトの(x、y)が時間の経過とともに変化する速度)を計算する際に注意が必要です。

最初のカットとして、衝突検出が最初に機能するかどうかをテストするために、移動ベクトルを逆にする必要があると思います。

次に、別の質問をします。回答をターゲットにできるように、個々の質問を具体的にすることをお勧めします。

于 2009-04-23T03:29:34.587 に答える
3

衝突の検出は最初のステップにすぎません。それを分解しましょう。

最も速い方法は、正方形のバウンディングボックスを計算し、それらが衝突するかどうかを確認することです。バウンディングボックスをオーバーラップさせるには、2つの側面を交差させる必要があります(1の上部と下部または2、1の左側と2の右側、またはその逆)。オーバーラップ、衝突はありません。

ここで、それらオーバーラップする場合、それらの間の距離を計算する必要があります。この距離がボールの半径の合計よりも大きい場合、衝突はありません。

わかった!2つのボールが衝突しています。何?まあ、彼らはお互いに跳ね返らなければなりません。どちらの方向に跳ね返るかは、いくつかの要因によって異なります。

1つ目は弾力性です。互いに跳ね返る2つのゴム製のボールは、2つのガラス製のボールとは異なる方法で跳ね返ります。

2番目はそれらの初速度です。Inertiaは、彼らが始めたのとほぼ同じ方向に進み続けたいと述べています。

3番目はボールの質量です。質量が小さいボールは、速度が速くなると、はるかに大きい質量で跳ね返ります。

2番目と3番目の要素は絡み合っているので、最初にそれらを扱いましょう。

2つのボールが正確に死んでヒットすることはめったにありません。ちらっと一撃する可能性がはるかに高くなります。いずれの場合も、ボールが衝突する接線の法線に沿って衝撃が発生します。初期速度を考慮して、この法線に沿って両方のベクトル成分を計算する必要があります。これにより、両方のボールが衝突する通常の速度のペアが生成されます。合計して、便利な場所に保管してください。

ここで、各ボールがボールから何を奪うかを理解する必要があります。結果として得られる各ボールの法線速度は、与えられたボールの質量に反比例します。つまり、各ボールの質量の逆数を取り、両方の質量を合計してから、両方のボールの質量の逆数の合計に対するボールの質量の比率に基づいて、衝突から離れた結果​​の法線速度を分割します。次に、これに接線速度を追加すると、ボールの合成速度が得られます。

弾力性はほとんど同じですが、ボールが圧縮されてもボールがまだ動いているため、基本的な計算が必要です。関連する数学を見つけるのはあなたに任せます。

于 2009-04-23T03:49:51.933 に答える
1

衝突の検出は、Paxの回答で十分にカバーされていました。オブジェクトが互いに跳ね返るという点に関しては、弾性衝突、非弾性衝突、および反発係数に関する次のリンクを確認すること勧めます

編集: Python専用ではありませんが、これが別のSOの質問でカバーされていることに気づきました。また、いくつかの良いリンクを確認する必要があります。

于 2009-04-23T03:44:19.293 に答える
1

彼がpygameを使用していることを考えると、特にあなたたちが見逃しているもっと簡単なものがあると思います。

関数を呼び出すと、get_rectおそらく画像の境界を設定でき、Rectそれが作成され、画像の位置を計算するために使用されます。アニメーションに複数のオブジェクトがある場合は、衝突を検出するために使用できます。

colliderectrect使用できますが、問題は、特にボールの数が不明な場合にどのように実装するかわかりません。

それはpythonであることを覚えておいてください。

于 2009-04-23T04:30:17.797 に答える
0

Python 衝突検出 if ステートメントを作成しました。

if beach ball 1 x < beach ball 2 x + beach ball 1 width and beach ball 1 x + beach ball 2 width > beach ball 2 x and beach ball 1 y < beach ball 2 y + beach ball 1 height and beach ball 2 height + beach ball 1 y > beach ball 2 y:
    #put needed code here

あなたの場合、3 つの跳ねるボールがある場合、衝突検出が完璧であることを確認するために、ボールごとにこの形式の if ステートメントを 2 つ作成する必要があります。これが役立つことを願っています。

于 2016-08-21T02:02:06.707 に答える
0

まず、衝突を確認する必要がありますrect.colliderect(other_rect)

その後、衝突している場合は、ピクセルの完全な衝突を確認できます。したがって、オブジェクトの半径や形状をいじることはありません。

ピクセル パーフェクトな衝突チェックには、マスクを使用します。 で両方のマスク オブジェクトを作成しmask.from_surface、それらをMask.overlap機能させます。

于 2009-07-17T00:31:55.250 に答える
0

CPU サイクルが高価だった古き良き時代、コーダーは衝突を検出するために単純なトリックを使用していました。背景かオブジェクトかをピクセルの色から判断できるような色を使用していました。これは、少なくともいくつかの C64 ゲームで行われました。

あなたがこの道を進んで行くかどうかはわかりませんが..

于 2009-04-23T17:08:29.990 に答える