圆对象注册碰撞,但它们不接触

2024-06-16 14:00:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我刚刚检查了here以确保这个问题是允许的,似乎是这样,我来了:

我目前正在做一个二维物理引擎作为一个小项目。我有一个名为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()

Tags: theinselfforifdefmathpygame
1条回答
网友
1楼 · 发布于 2024-06-16 14:00:37

简而言之:一个圆与其自身相撞。原因很简单,因为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))
            #...

相关问题 更多 >