PyMunk

PyMunk是一个模拟物理的库。

注意,PyMunk只是进行物理模拟,不包含可视化的功能。如果需要可视化,可使用pygame等库。

可用pip安装pymunk
pip install pymunk

Pygame基础10-物理模拟_开发语言

pymunk中的概念

  • space: 物理空间。 包含gravity 模拟重力,update更新空间。
  • Body: 原子物体(一个点,没有形状),受到力的影响。
  • Shape:形状,包围在Body周围,用于检测碰撞。

pymunk中有3种类型的Body

  • static:静止的,不会移动,但是可以产生碰撞。
  • dynamic:动态的,受到力的影响。
  • kinematic:受玩家控制(或非物理控制)的影响。

Pygame基础10-物理模拟_开发语言_02

模拟的过程

  1. 创建空间
space = pymunk.Space()
space.gravity = (0.0, 100.0)
  1. 创建Body和shape, 并加入到空间中
def create_apple(space, pos):
    body = pymunk.Body(mass=1, moment=10, body_type=pymunk.Body.DYNAMIC) # DYNAMIC 类型的物体会受到力的影响
    body.position = pos
    shape = pymunk.Circle(body, radius=10)
    space.add(body, shape)
    return shape

(如果使用pygame可视化)绘制物体:

def draw_apple(apples):
    for apple in apples:
        pos_x = int(apple.body.position.x)
        pos_y = int(apple.body.position.y)
        pygame.draw.circle(screen, (255, 0, 0), (pos_x, pos_y), 10)
  1. 更新空间
...
# 在每一帧中更新空间
space.step(1/60.0)

案例

下面是一个完整示例,模拟苹果掉落的过程。

Pygame基础10-物理模拟_pygame_03

import sys
import pygame
import pymunk


pygame.init()
screen_size = (800, 600)
screen = pygame.display.set_mode(screen_size)
clock = pygame.time.Clock()

space = pymunk.Space()
space.gravity = (0.0, 100.0)


def create_apple(space, pos):
    body = pymunk.Body(mass=1, moment=10, body_type=pymunk.Body.DYNAMIC) # DYNAMIC 类型的物体会受到力的影响
    body.position = pos
    shape = pymunk.Circle(body, radius=10)
    space.add(body, shape)
    return shape


def draw_apple(apples):
    for apple in apples:
        pos_x = int(apple.body.position.x)
        pos_y = int(apple.body.position.y)
        pygame.draw.circle(screen, (255, 0, 0), (pos_x, pos_y), 10)



def create_static_ball(space, pos):
    body = pymunk.Body(body_type=pymunk.Body.STATIC) # STATIC 类型的物体 不会移动
    body.position = pos
    shape = pymunk.Circle(body, radius=10)
    space.add(body, shape)
    return shape

def draw_balls(balls):
    for ball in balls:
        pos_x = int(ball.body.position.x)
        pos_y = int(ball.body.position.y)
        pygame.draw.circle(screen, (0, 255, 0), (pos_x, pos_y), 10)

apples =[]

balls = []
balls.extend([create_static_ball(space, (400, 300)),
             create_static_ball(space, (500, 400))
            ])

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type == pygame.MOUSEBUTTONDOWN:
            pos = pygame.mouse.get_pos()
            apple = create_apple(space, pos)
            apples.append(apple)

    screen.fill((35, 35, 35))
    draw_apple(apples)
    draw_balls(balls)

    space.step(1/60.0)

   
    pygame.display.flip()
    clock.tick(60)