在我的简单Python物理引擎中建模摩擦

2024-09-28 22:38:04 发布

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

我用Python在我的简单物理引擎中对摩擦力进行了建模,但它不是最好的。我的问题是,在一定的速度下,物体会经历摩擦,减速并停止,但停止后,它会继续来回振动。我认为问题是因为速度并不像在现实生活中那样平稳地减小,它以摩擦力引起的加速度的增量减小

在尝试制作这个简单的物理引擎时,我遇到了两个问题,第一个是边界问题,第二个是摩擦问题。我可以解决这些问题,但我的解决方案不是很好,它们是草率的,我的解决方案有点像数值解决方案(它是近似的),但你的解决方案像解析解决方案(它们是完美的),我如何防止这种情况

这是代码

import pygame as pyg
# from math import *
pyg.init()

win = pyg.display.set_mode((1500, 900))

pyg.display.set_caption('physics engine')

mainloop = True
jump = False


class Objects:
    def __init__(self, x, y, vel_x, vel_y, acc_x, acc_y, mass):
        self.x = x
        self.y = y
        self.vel_x = vel_x
        self.vel_y = vel_y
        self.acc_x = acc_x
        self.acc_y = acc_y
        self.mass = mass


circ = Objects(400, 750, 0, 0, 0, 0, 100)
rect = Objects(0, 890, 0, 0, 0, 0, 100)

F_x = 1250
F_y = 1750
coeff_fric = 0.3
friction_x = 0
friction_y = 0
g = 9.8

while mainloop:
    pyg.time.delay(50)

    for event in pyg.event.get():
        if event.type == pyg.QUIT:
            mainloop = False
    keys = pyg.key.get_pressed()

    if keys[pyg.K_LEFT]:
        circ.acc_x = -1 * F_x / circ.mass

    if keys[pyg.K_RIGHT]:
        circ.acc_x = F_x / circ.mass

    if keys[pyg.K_UP]:
        circ.acc_y = -1 * F_y / circ.mass

    if keys[pyg.K_DOWN]:
        circ.acc_y = F_y / circ.mass

    if keys[pyg.K_SPACE]:
        circ.vel_y = 0
        circ.vel_x = 0

    circ.vel_y += g
    circ.vel_x += circ.acc_x
    circ.vel_x += circ.acc_x
    circ.vel_y += circ.acc_y
    circ.vel_y += circ.acc_y

    win.fill((0, 0, 0))

    circ.x += circ.vel_x
    circ.y += circ.vel_y
    if circ.x < 50 or circ.x > 1450:
        circ.x = max(50, min(1450, circ.x))
        circ.vel_x = 0
    if circ.y < 50 or circ.y > 840:
        circ.y = max(50, min(840, circ.y))
        circ.vel_y = 0
    F_x = 1250
    F_y = 1750
    circ.acc_x = 0
    circ.acc_y = 0
    friction_x = coeff_fric * circ.mass * g
    friction_y = coeff_fric * circ.mass * g
    fric_force_x = F_x - friction_x
    fric_force_y = F_y - friction_y
    if circ.y >= 840:
        if circ.acc_x == 0:
            if round(circ.vel_x) == 0:
                circ.vel_x = 0
            if round(circ.vel_x) > 0:
                circ.acc_x = -1 * friction_x / circ.mass
                circ.vel_x += circ.acc_x
                if circ.vel_x < 0:
                    circ.vel_x = 0
                    circ.acc_x = 0
            if round(circ.vel_x) < 0:
                circ.acc_x = friction_x / circ.mass
                circ.vel_x += circ.acc_x
                if circ.vel_x > 0:
                    circ.vel_x = 0
                    circ.acc_x = 0

    print(circ.vel_x)
    objct = pyg.draw.circle(win, (50, 50, 255), (round(circ.x), round(circ.y)), 50)
    floor = pyg.draw.rect(win, (150, 75, 0), (rect.x, rect.y, 1500, 10))

    pyg.display.update()

pyg.quit()

Tags: rectselfifdisplaykeys解决方案winmass