0

したがって、次のような Ball クラスがあります。

   class Ball(object):
    def __init__(self,n,x0,y0,dx,dy,r,c):
        self.xc = x0
        self.yc = y0
        self.dx = dx
        self.dy = dy
        self.radius = r
        self.area = math.pi*((r)**2)
        self.color = c
        self.name = n
    def position(self):
        return (self.xc,self.yc)
    def move(self):
        self.xc+=self.dx
        self.yc+=self.dy
    def collide(self,o,new_name):
        x = ((self.area*self.xc)+(o.area*o.xc))/(self.area+o.area)
        y = ((self.area*self.yc)+(o.area*o.yc))/(self.area+o.area)
        dx = ((self.area*self.dx)+(o.area*o.dx))/(self.area+o.area)
        dy = ((self.area*self.dy)+(o.area*o.dy))/(self.area+o.area)
        if self.area >= o.area:
            c = self.color
        else:
            c = o.color
        area = (self.area+o.area)
        r = math.sqrt(area/(math.pi))
        return Ball(new_name,x,y,dx,dy,r,c)
    def does_collide(self,o):
        if math.hypot((self.xc-o.xc),(self.yc-o.yc))<=(self.radius+o.radius):
            return True
        else:
            return False

そして、メイン コードで while ループを実行して、さまざまなボールをシミュレートしています。各ボールは、反復ごとに dx 値と dy 値で移動します。これを行うために、すべてのボール オブジェクトを保持する、balls というリストがあります。次のようになります。

    balls=[ball1,ball2,ball3,ball4...] and so forth

私がやりたいことは、ボール クラスで does_collide 関数を使用して、2 つのボールが衝突するかどうかを確認することです。2 つのボールが衝突する場合は、リストから 2 つのボールを削除し、衝突関数によって作成された新しいボールをリストに挿入します。衝突関数は、x、y、dx、および dy の値が 2 つのボールの加重平均であり、色が最大のボールの色である新しいボールを作成します。

リスト内のすべてのボールについて、dos_collide 関数を使用して 2 つのボールが衝突したかどうかを積極的にチェックし、それらをリストから削除するにはどうすればよいでしょうか? また、衝突関数の結果である新しいボールをリストに追加したいと思います。

私はこのようなことをしてみました:

         for ball1 in balls:
            for ball2 in balls:
                if ball1.name!=ball2.name:
                    if ball1.does_collide(ball2) == True:
                        ball = ball1.collide(ball2,(int(N)+1))
                        balls.append(ball)
                        balls.remove(ball1)
                        balls.remove(ball2)

しかし、それは非常に厄介なようで、衝突が発生するたびにクラッシュします。

4

2 に答える 2

3

注文は気になりますか?そうでない場合は、これを行う 1 つの方法があります。

import itertools

newballs = []
removed = set()
for b1, b2 in itertools.combinations(balls, 2):
    if b1 not in removed and b2 not in removed:
        if b1.does_collide(b2):
            removed.add(b1)
            removed.add(b2)
            newballs.append(b1.collide(b2))

balls = [b for b in balls if b not in removed] + newballs
于 2013-05-04T00:12:30.633 に答える
0

外側のループをリスト全体で実行させますが、内側のループは現在の外側のループ ball+1 からリストの最後までのみ実行させます。明らかに、ボール 5 (たとえば) がボール 8 (たとえば) と衝突する場合、ボール 8 はボール 5 と衝突するため、両方をチェックする必要はありません。

また、 listを繰り返し処理すると同時に、 list から項目を削除しています。これは安全ではありません。ループ内で削除を行う代わりに、どのボールを削除する必要があるかを示すフラグをループ内に設定し、別のループでそれらを削除します。

于 2013-05-04T00:12:53.787 に答える