如何避免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
相关产品推荐
相关产品推荐

