You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免Pymunk刚体运行两帧后中心位置变为NaN?

问题原因及解决方案

核心问题:物理计算出现NaN

你的代码创建动态刚体后,未正确关联形状的质量属性,导致Pymunk物理引擎计算时出现数值异常,最终刚体位置变为Vec2d(nan, nan)并消失。具体来说:

  • 手动设置了body的mass=20,但添加的Circle形状未设置密度,也未让刚体根据形状更新质量参数,这会导致转动惯量等物理属性计算出错。

修复步骤

1. 正确关联刚体与形状的质量

有两种可行方案:

方案一:通过形状密度自动计算刚体质量

删除手动设置的mass参数,给Circle形状添加density属性,Pymunk会根据形状面积和密度自动计算刚体质量:

body = pymunk.Body(body_type=pymunk.Body.DYNAMIC)  # 不手动设置mass
shape = pymunk.Circle(body, 25, density=1)  # 添加density参数

方案二:手动设置质量后更新形状关联参数

若需手动控制刚体质量,在添加形状后调用update_mass_from_shapes()方法:

body = pymunk.Body(mass=20, body_type=pymunk.Body.DYNAMIC)
shape = pymunk.Circle(body, 25)
body.position = (250, 250)
body.update_mass_from_shapes()  # 新增该行,让刚体根据形状更新质量属性

2. 修正坐标系统差异(可选但符合预期)

Pygame的y轴向下(数值越大越靠下),而Pymunk的y轴向上(数值越大越靠上),直接使用body.position绘制会导致小球向上运动,不符合“下落”预期。需要转换坐标并调整重力方向:

# 调整重力方向为Pymunk的负y轴(对应Pygame的向下)
space.gravity = (0, -900)

# 绘制时转换坐标
draw_pos = (body.position.x, 500 - body.position.y)
pygame.draw.circle(screen, (0,0,0), draw_pos, 25)

完整修复代码

import pymunk
import pygame

screen = pygame.display.set_mode((500,500))
space = pymunk.Space()
space.gravity = (0, -900)

body = pymunk.Body(body_type = pymunk.Body.DYNAMIC)
shape = pymunk.Circle(body,25, density=1)
body.position = (250,250)

space.add(body,shape)

clock = pygame.time.Clock()
done = False
while not done:
    clock.tick(30)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True

    screen.fill((255,255,255))
    draw_pos = (body.position.x, 500 - body.position.y)
    pygame.draw.circle(screen,(0,0,0), draw_pos,25)
    pygame.display.flip()
    
    print(body.position)
    space.step(1/50)

内容的提问来源于stack exchange,提问作者Bad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 05:17:25