1

円から円への衝突の解決に問題があります。

最初に衝突を検出し、次にボールが衝突した場合、半径の合計でそれらを分離し、速度を設定します。簡単だ。

私の問題は、重力が作用していて、ボールが上から別のボールと衝突するときです。跳ね返るはず、地面に落ちるまで非常にゆっくりと滑ります。

何が起こっているのかというと、コリジョンの解決後、重力がボールを押し下げ、別のコリジョンを引き起こします。半径の合計 + x でボールを分離しようとしましたが、スライドが少し速くなります。

ビデオはhttp://www.youtube.com/watch?v=tk7qQ9KDFp0&feature=youtu.beで見ることができます。

そして、ここにコリジョンを処理するコードがあります:

for p in world.particle_list:

        if not p == self:

            if self.pos.sub(p.pos).get_length() <= self.radius * ppm + p.radius * ppm:

                p_mass_ratio = float(self.mass) / (self.mass + p.mass)
                self_mass_ratio = float(p.mass) / (self.mass + p.mass)

                rel_pos = p.pos.sub(self.pos)
                shift = rel_pos.set_length(- rel_pos.get_length() + self.radius * ppm + p.radius * ppm)
                p.pos = p.pos.add(shift.scale(0.50))
                self.pos = self.pos.add(shift.scale(-0.50))

                p_speed = p.speed
                self_speed = self.speed

                self.speed = p_speed.add(self.speed.norm_reflect(rel_pos.set_angle(rel_pos.get_angle() + 90).scale(-self.friction))).scale(0.50 * self_mass_ratio)
                p.speed = self_speed.add(p.speed.norm_reflect(rel_pos.set_angle(rel_pos.get_angle() + 90).scale(self.friction))).scale(0.50 * p_mass_ratio)

これを処理するためのベクトル クラスを作成しました。

def dcos(x):

    return cos(radians(x))

def dsin(x):

    return sin(radians(x))

def dtan(x):

    return tan(radians(x))

class Vec(object):

    def __init__(self, x, y):

        self.x = float(x)
        self.y = float(y)

        self.length = self.get_length()
        self.angle = self.get_angle()

    def get_length(self):

        return sqrt(self.x ** 2 + self.y ** 2)

    def get_angle(self):

        return atan2(self.y, self.x) * 180 / pi

    def add(self, vec1):

        new_x = self.x + vec1.x
        new_y = self.y + vec1.y

        return Vec(new_x, new_y)

    def sub(self, vec1):

        new_x = self.x - vec1.x
        new_y = self.y - vec1.y

        return Vec(new_x, new_y)

    def scale(self, k):

        return Vec(self.x * k, self.y * k)

    def set_angle(self, a):

        new_x = self.length * dcos(a)
        new_y = self.length * dsin(a)

        if a == -90 or a == 90:

            new_x = 0

        if a == 180 or a == 0 or a == -180:

            new_y = 0

        return Vec(new_x, new_y)

    def set_length(self, l):

        new_x = l * dcos(self.angle)
        new_y = l * dsin(self.angle)

        return Vec(new_x, new_y)

    def inverse(self):

        return Vec(- self.x, - self.y)


    def norm_reflect(self, vec1):

        if self.get_angle == vec1.get_angle():

            return Vec(self.x, self.y)

        if vec1.get_angle() >= 0:

            return self.set_angle(vec1.get_angle() - self.get_angle() + 90)

    else:

        return self.set_angle(vec1.get_angle() - self.get_angle() - 90)
4

1 に答える 1

0

(私は python を知りませんが、私は物理学を知っており、あなたは他の答えを得ていないので、私はそれに割ってみます。)

見る

if self.pos.sub(p.pos).get_length() <= self.radius * ppm + p.radius * ppm:
  ...
  rel_pos = p.pos.sub(self.pos)
  shift = rel_pos.set_length(- rel_pos.get_length() + self.radius * ppm + p.radius * ppm)
  p.pos = p.pos.add(shift.scale(0.50))
  self.pos = self.pos.add(shift.scale(-0.50))

長さを負の数に設定しているので、オブジェクト互いに近づけています。

このnorm_reflect()関数はあまり意味がなく、意図したものとは異なる動作をしているのではないかと思います (この場合、コードをテストしていません)。

これらの 2 行:

self.speed = p_speed.add(self.speed.norm_reflect(rel_pos.set_angle(rel_pos.get_angle() + 90).scale(-self.friction))).scale(0.50 * self_mass_ratio)
p.speed = self_speed.add(p.speed.norm_reflect(rel_pos.set_angle(rel_pos.get_angle() + 90).scale(self.friction))).scale(0.50 * p_mass_ratio)

norm_reflect()1 つの引数のみで呼び出しているように見え単純なケースが機能する前に摩擦と質量比を図に取り込んでおり、rel_pos複数の変換後に再利用しており、物理学は非ニュートンです (つまり、必要なほど間違っています) 。白紙の状態からやり直す)。

于 2013-04-03T23:37:39.940 に答える