圆之间的碰撞分辨率-缓慢滑动



我在圆对圆碰撞分辨率方面遇到了麻烦。

首先,我检测碰撞,然后如果两个球碰撞,我用它们的半径之和将它们分开,并设置速度。这很简单。

我的问题是当重力作用时,一个球从上面与另一个球碰撞。应该会被弹回来,但是滑动得非常慢,直到它掉到地面

发生的事情是,在碰撞解决后,重力将球向下推,导致另一次碰撞。我试过用半径加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)

我创建了一个vector类来处理这个:

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)

(我不懂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物理是非牛顿的(即错误到需要从头开始)。

最新更新