1

I am having trouble with circle to circle collision resolution.

First, i detect the collision, then if the balls collide, i separate them by the sum of their radii and set the velocities. That's easy.

My problem is when gravity is acting and a ball collides with another ball from above. It's suposed to bouce off but instead it slides very slowly until it drops in the ground.

Whats hapning is that afer the colision resolution, gravity pushes the ball down and causes another colision. I've tried separating the ball by the sum of their radii + x but it just slides a little faster.

You can watch the video at http://www.youtube.com/watch?v=tk7qQ9KDFp0&feature=youtu.be.

And here's the code that hadles colision:

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)

I made a vector class to handle this:

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()函数没有多大意义,我怀疑它做的不是你想要的(在这种情况下你不是在测试你的代码)。

这两行:

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()只用一个参数调用,并且您在简单案例起作用之前将摩擦和质量比带入图片中,并且rel_pos在多次转换后重用,并且物理学是非牛顿的(即错误到需要从一张白纸重新开始)。

于 2013-04-03T23:37:39.940 回答