圆形物体记录碰撞,但它们没有碰到

时间:2017-02-07 20:21:05

标签: python pygame game-physics

我刚检查了here以确保允许这个问题,而且似乎就是这样,我去了:

我目前正在将2D物理引擎作为一个小项目。我有一个名为circle的类,它具有半径,旋转,位置和速度等属性:

class circle():
    def __init__(self, radius = 10, r = 0.0, x = 0, y = 0, Vr = 0, Vx = 0, Vy = 0):

        self.radius = radius

        self.r = r
        self.x = x
        self.y = y

        self.Vr = Vr
        self.Vx = Vx
        self.Vy = Vy

该类有一个名为CheckCollisions()的方法,用于检查其中心与另一个圆心的距离是否小于其半径的总和:

def CheckCollisions(self):
    for c in circles:
        distance = math.sqrt((c.x - self.x)*(c.x - self.x) + (c.y - self.y)*(c.y - self.y))
        if distance < self.radius + c.radius:
            print('!')
        else:
            print('')

这个想法是,在检测到碰撞时,可以将力作为矢量应用于每个物体,作为对撞击的响应。

当我的代码运行时,我看到shell中出现了不断的感叹号,尽管圆圈没有碰撞。是什么造成的?也许我的距离计算中的某些内容不正确?

完整代码:

import pygame, random, math
from pygame.locals import*

# set up pygame window
(width, height) = (1000, 800)
screen = pygame.display.set_mode((width,height))
pygame.display.set_caption('Impulse Physics v0.1 BETA')

pen = pygame.image.load('Pen.png').convert()
background = (0, 0, 0)

class circle():
    def __init__(self, radius = 10, r = 0.0, x = 0, y = 0, Vr = 0, Vx = 0, Vy = 0):

        self.radius = radius

        # position and rotation
        self.r = r
        self.x = x
        self.y = y

        # velocity
        self.Vr = Vr
        self.Vx = Vx
        self.Vy = Vy

    def CheckCollisions(self):
        for c in circles:
            # use pythagoras to find direct distance between centres
            distance = math.sqrt((c.x - self.x)*(c.x - self.x) + (c.y - self.y)*(c.y - self.y))
            if distance < self.radius + c.radius:
                print('!')
            else:
                print('')

    def Move(self):
        # apply slight "air resistance"
        self.Vx = self.Vx * 0.9999
        # gravity. REMEMBER y axis is inverted in pygame!
        self.Vy = self.Vy + 0.15

        # move object
        self.x = self.x + self.Vx
        self.y = self.y + self.Vy
        self.r = self.r + self.Vr

        self.CheckCollisions()

        # check if colliding with the sides of the window
        if self.y + self.radius > height:
            self.Vy = self.Vy * -0.98
            self.y = self.y + self.Vy

        if (self.x + self.radius > width) or (self.x - self.radius < 0):
            self.Vx = self.Vx * -0.98
            self.x = self.x + self.Vx

    def Render(self):
        penX = self.x
        penY = self.y
        penR = self.r
        screen.blit(pen, (penX, penY))

        # draw the radius of the circle
        for counter in range(self.radius):
            penX = self.x + (math.sin(penR) * counter)
            penY = self.y - (math.cos(penR) * counter)
            screen.blit(pen, (penX, penY))

        # draw the circumference of the circle
        for counter in range(self.radius * 20):
            penR = counter * (360 / self.radius * 20)
            penX = self.x + (math.sin(penR) * self.radius)
            penY = self.y + (math.cos(penR) * self.radius)
            screen.blit(pen, (penX, penY))

circles = []

#create objects here

c1 = circle(100, 0, 400, 400, 0.1, 4)
circles.append(c1)

c2 = circle(50, 0, 50, 50, 0.08, 10)
circles.append(c2)

c3 = circle(10, 0, 300, 200, 0.02, -3)
circles.append(c3)

running = True
while running:
    screen.fill(background)
    for obj in circles:
        obj.Move()
        obj.Render()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    pygame.display.flip()

pygame.quit()

1 个答案:

答案 0 :(得分:5)

简而言之:一个圆圈与自身相撞。原因很简单,circles列表包含[c1,c2,c3],因此会对圈子本身进行检查。

现在c1检查是否存在冲突,以便它在circles上进行迭代,它检查的第一件事是是否与自身发生冲突(自{{ 1}}是列表中的第一个元素)。显然它确实如此(你的测试看起来距离是否小于圆半径的总和,但距离是零)。如果没有一个圆碰撞,那么就会有三个感叹号(每个圆圈一个)。

您可以先执行引用相等性检查来解决此错误:

c1