首页 > 解决方案 > 出于某种原因,PyGame 物理模拟所有物体都以相同的速度移动

问题描述

我目前正在学习可汗学院的一些自然模拟课程,并试图在 python 中重现他们的 JavaScript 代码。在下面的代码中,我试图在两个不同质量的物体上模拟重力和风。但是,即使在apply_force()我除以物体质量的方法中,当我运行模拟时,两个物体都以完全相同的速度移动。风应该使较小的身体比较大的身体移动得更快,但事实并非如此。

#init pygame library
import pygame
import random

pygame.init()

window_width = 800
window_height = 800

FPS = 500

screen = pygame.display.set_mode([window_width, window_height])

clock = pygame.time.Clock()

running = True

#basic vector class class
class Vector2f:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def add(self, v2):
        self.x = self.x + v2.x
        self.y = self.y + v2.y

    def mult(self, v2):
        self.x = self.x * v2.x
        self.y = self.y * v2.y

#mover class
class Mover:
    def __init__(self, mass, position, velocity, acceleration):
        self.mass = mass
        self.position = position
        self.velocity = velocity
        self.acceleration = acceleration

    def apply_force(self, force):
        f = Vector2f((force.x/float(self.mass)), (force.y/float(self.mass)))
        self.acceleration.add(f)

    def update(self):
        self.velocity.add(self.acceleration)
        self.position.add(Vector2f(self.velocity.x, self.velocity.y))
        self.acceleration.mult(Vector2f(0,0))

    def draw(self):
        pygame.draw.circle(screen, (50, 50, 50), (int(round(self.position.x)),                                         int(round(self.position.y))), self.mass)

    def check_edges(self):
        if self.position.x > window_width:
            self.position.x = window_width
            self.velocity.x = self.velocity.x * -1
        elif self.position.x < 0:
            self.position.x = 0
            self.velocity.x = self.velocity.x * -1

        if self.position.y > window_height:
            self.velocity.y = self.velocity.y * -1
            self.position.y = window_height


m_position = Vector2f(30, 30)
m_velocity = Vector2f(0, 0)
m_acceleration = Vector2f(0, 0)

m1 = Mover(30, m_position, m_velocity, m_acceleration)
m2 = Mover(5, m_position, m_velocity, m_acceleration)


#simulation loop
while running:
    clock.tick(FPS)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    screen.fill((255,255,255))


    wind = Vector2f(.003, 0)
    gravity = Vector2f(0, .005)

    m1.apply_force(wind)
    m1.apply_force(gravity*m1.mass)

    m1.update()
    m1.draw()
    m1.check_edges()

    m2.apply_force(wind)
    m2.apply_force(gravity*m2.mass)

    m2.update()
    m2.draw()
    m2.check_edges()



    pygame.display.flip()


pygame.quit()

此外,当我减小较小动子 ( m2) 的质量时,不知何故,速度m1正在增加。

标签: pythonpygamephysics

解决方案


m_position您为、m_velocity和创建向量m_acceleration。实例对象m1m2共享这个向量。,position和属性指的是相同的对象velocityacceleration如果您更改其中一个对象的属性,其他对象的属性似乎也会发生神奇的变化。

m1创建和m2对象时,为参数制作向量的副本:

class Vector2f:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def copy(self):
        return Vector2f(self.x, self.y)

    # [...]
m_position = Vector2f(30, 30)
m_velocity = Vector2f(0, 0)
m_acceleration = Vector2f(0, 0)

m1 = Mover(30, m_position.copy(), m_velocity.copy(), m_acceleration.copy())
m2 = Mover(5, m_position.copy(), m_velocity.copy(), m_acceleration.copy())

旁注:PyGame分别为二维和三维向量提供类pygame.math.Vector2和。pygame.math.Vector3


推荐阅读