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

Ari*_*ric 2 python pygame game-physics

我刚刚在这里检查以确保这个问题是允许的,而且似乎就是这样,我走了:

我目前正在将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
Run Code Online (Sandbox Code Playgroud)

该类有一个名为的方法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('')
Run Code Online (Sandbox Code Playgroud)

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

当我的代码运行时,我看到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()
Run Code Online (Sandbox Code Playgroud)

Wil*_*sem 5

简而言之:圆圈与自身发生碰撞.原因很简单,circles列表包含[c1,c2,c3]并因此对圆圈本身进行检查.

现在为c1你检查是否有碰撞,所以它迭代了circles它,它检查的第一件事是它是否与自身碰撞(因为它c1是列表中的第一个元素).显然它确实如此(你的测试看起来距离是否小于圆半径的总和,但距离是零).如果没有一个圆碰撞,那么将有三个感叹号(每个圆圈一个).

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

def CheckCollisions(self):
    for c in circles:
        if c is not self:
            distance = math.sqrt((c.x - self.x)*(c.x - self.x) + (c.y - self.y)*(c.y - self.y))
            #...
Run Code Online (Sandbox Code Playgroud)