我希望将我的碰撞检测方法更改为基于网格的碰撞方法,我将如何尽可能高效地执行此操作?

问题描述 投票:0回答:0

我的程序是一个粒子动力学模拟,它是通过用户在 Tkinter GUI 中输入的参数初始化模拟窗口而创建的。我的代码在我的所有测试标准下都有效(至少就我测试过的而言),但是,我希望改变我的碰撞检测方法。我目前正在使用将两个粒子之间的距离与它们的半径之和进行比较的方法。这特别是关于我的代码的粒子碰撞,因为即使我更改容器大小,与模拟边界的碰撞也能正常工作。在查看了不同的碰撞检测方法之后,我更喜欢基于网格的碰撞检测,而不是四叉树或我目前正在使用的这种蛮力方法。

所以这是我为整个粒子动力学模拟编写的代码。我目前的碰撞检测方法是有效的,但是,并不是每个粒子都相互碰撞,并且有些粒子通过或粘在一起。我怀疑这是检查每对粒子的方法的局限性。我正在尝试将此方法更改为更有效的方法,例如前面提到的基于网格的碰撞检测。这是我怀疑我需要进行最多编辑的代码的一部分:

导入数学 导入pygame 随机导入 将 tkinter 导入为 tk 从 tkinter 导入 ttk、消息框、文件对话框 进口泡菜

模拟类: def init(self, no_particles, vel, width, height, particle_radius): # 为 Sim 实例制作的参数 self.no_particles = no_particles self.vel = vel self.width = 宽度 self.height = 高度 self.particle_radius = particle_radius

    # Initialize pygame and define clock for FPS
    pygame.init()
    clock = pygame.time.Clock()

    # Create the pygame display
    screen = pygame.display.set_mode((self.width, self.height))

    # Setup particle color and list
    particle_color = (3, 215, 252)
    particles = []

    # Create the instance of class Particle
    for i in range(self.no_particles):

        pos = [random.randint(0, width), random.randint(0, height)]
        speed = [random.randint(-3 * vel, 3 * vel), random.randint(-3 * vel, 3 * vel)]
        particles.append(Particle(pos, speed, particle_radius, particle_color))

    # Main game loop
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            # Mouse interactions
            if event.type == pygame.MOUSEBUTTONDOWN:
                (Mx, My) = pygame.mouse.get_pos()
                select_p = find_p(particles, Mx, My)
                if select_p:
                    select_p.color = (252, 3, 3)

        # Movement of the particles
        for particle in particles:
            particle.move(width, height)
            particle.check_collision(width, height)

        # Check for collision with other particles
        for i, particle1 in enumerate(particles):
            for j, particle2 in enumerate(particles):
                if i == j:
                    continue
                particle1.part_collision(particle2)

        # Apply the color of the environment
        screen.fill((255, 255, 255))

        # Draw the particles
        for particle in particles:
            particle.draw(screen)

        # Update the display and set FPS limit
        clock.tick(60)
        pygame.display.update()

粒子类,定义粒子之间的运动和碰撞以及模拟的边界

类粒子: def init(self, pos, speed, radius, color): self.pos = pos self.speed = 速度 self.radius = 半径 self.color = 颜色

def move(self, width, height):
    self.pos[0] += self.speed[0]
    self.pos[1] += self.speed[1]
    if self.pos[0] > width - self.radius:
        self.pos[0] = width - self.radius
        self.speed[0] = -self.speed[0]
    elif self.pos[0] < 0:
        self.pos[0] = 0
        self.speed[0] = -self.speed[0]
    if self.pos[1] > height - self.radius:
        self.pos[1] = height - self.radius
        self.speed[1] = -self.speed[1]
    elif self.pos[1] < 0:
        self.pos[1] = 0
        self.speed[1] = -self.speed[1]

def check_collision(self, width, height):
    if self.pos[0] > width - self.radius or self.pos[0] < 0:
        self.speed[0] = -self.speed[0]
    if self.pos[1] > height - self.radius or self.pos[1] < 0:
        self.speed[1] = -self.speed[1]

def part_collision(self, particle2):
    # Calculate the distance between the centers of the two particles
    distance = ((self.pos[0] - particle2.pos[0]) ** 2 + (self.pos[1] - particle2.pos[1]) ** 2) ** 0.5
    # Calculate the sum of the radii of the two particles
    sum_of_radii = self.radius + particle2.radius
    # Check if the distance is less than the sum of the radii
    if distance <= sum_of_radii:
        # The particles are colliding, swap their speeds
        self.speed[0], particle2.speed[0] = particle2.speed[0], self.speed[0]
        self.speed[1], particle2.speed[1] = particle2.speed[1], self.speed[1]

def draw(self, window):
    pygame.draw.circle(window, self.color, (int(self.pos[0]), int(self.pos[1])), self.radius)

在 python 方面我不是最有经验的,我愿意接受任何建议。提前谢谢你!

python pygame collision-detection
© www.soinside.com 2019 - 2024. All rights reserved.