使用 PyGame - Python 显示 PyMunk
Show PyMunk with PyGame - Python
我正在尝试学习 PyMunk,我使用了网站上的基本示例:
import pymunk
space = pymunk.Space()
space.gravity = 0,-1000
body = pymunk.Body(1,1666)
body.position = 50,100
poly = pymunk.Poly.create_box(body)
space.add(body, poly)
while True:
space.step(0.02)
但它不创建 window,不显示任何内容。如何使用PyGame创建图形window?
这个例子所做的是创建一个模拟,在里面添加一个盒子形状的对象,然后 运行 无限地模拟。该代码不打印或绘制任何内容,因此您实际上看不到输出。为了更好地理解屏幕上的内容,我建议您从教程开始:http://www.pymunk.org/en/latest/tutorials/SlideAndPinJoint.html
Pymunk 是一个二维刚体物理库,这意味着它所做的是模拟物体如何在二维空间中移动和相互作用。它不是为绘制到屏幕或读取输入而设计的。
你当然可以直接使用,直接打印模拟结果即可。但更常见的是你想在屏幕上绘图、读取输入等。一种方法是使用游戏库 Pygame,它有助于在屏幕上绘图、读取输入、进行游戏循环等等。
Pymunk 本身确实有一些辅助函数,因此您可以轻松地将它与 Pygame(以及其他几个库)连接起来,但这不是核心部分。通常这些辅助函数适用于您想要一些快速的东西(例如原型)并且您不需要自定义绘图。
现在,这就是说,如果你想看一些东西,你可以在 while 循环中添加一个 print 语句,所以它变成这样:
while True:
space.step(0.02)
print(body.position)
然后它会在模拟的每一步打印出球的位置,你可以看到它一直在变化(因为space上设置的重力)。
Pymunk 中包含更多高级示例,它们既可以交互又可以在屏幕上显示一些内容。这些示例主要依赖于 Pygame 或 Pyglet,但原则是相同的,以防您有不同的库要使用它。
这是一个示例,展示了我如何将 Pymunk 与 pygame 结合使用。 Entity
class 是一个 pygame.sprite.Sprite
subclass,我附加了一个 pymunk.Body
和一个 pymunk.Shape
以及对 pm.Space
,以便可以从中添加和删除主体和形状。精灵矩形的位置在每一帧都设置为 self.body.position
,这样我们就可以得到 self.image
的正确 blit 位置,并且可以通过调用 self.sprite_group.draw(self.screen)
简单地绘制所有精灵。
import math
import pygame as pg
import pymunk as pm
from pymunk import Vec2d
def flipy(p):
"""Convert chipmunk coordinates to pygame coordinates."""
return Vec2d(p[0], -p[1]+600)
class Entity(pg.sprite.Sprite):
def __init__(self, pos, space):
super().__init__()
self.image = pg.Surface((46, 52), pg.SRCALPHA)
pg.draw.polygon(self.image, (0, 50, 200),
[(0, 0), (48, 0), (48, 54), (24, 54)])
self.orig_image = self.image
self.rect = self.image.get_rect(topleft=pos)
vs = [(-23, 26), (23, 26), (23, -26), (0, -26)]
mass = 1
moment = pm.moment_for_poly(mass, vs)
self.body = pm.Body(mass, moment)
self.shape = pm.Poly(self.body, vs)
self.shape.friction = .9
self.body.position = pos
self.space = space
self.space.add(self.body, self.shape)
def update(self, dt):
pos = flipy(self.body.position)
self.rect.center = pos
self.image = pg.transform.rotate(
self.orig_image, math.degrees(self.body.angle))
self.rect = self.image.get_rect(center=self.rect.center)
# Remove sprites that have left the screen.
if pos.x < 20 or pos.y > 560:
self.space.remove(self.body, self.shape)
self.kill()
def handle_event(self, event):
if event.type == pg.KEYDOWN:
if event.key == pg.K_a:
self.body.angular_velocity = 5.5
elif event.key == pg.K_w:
self.body.apply_impulse_at_local_point(Vec2d(0, 900))
class Game:
def __init__(self):
self.done = False
self.clock = pg.time.Clock()
self.screen = pg.display.set_mode((800, 600))
self.gray = pg.Color('gray68')
self.red = pg.Color('red')
# Pymunk stuff.
self.space = pm.Space()
self.space.gravity = Vec2d(0.0, -900.0)
self.static_lines = [
pm.Segment(self.space.static_body, (60, 100), (370, 100), 0),
pm.Segment(self.space.static_body, (370, 100), (600, 300), 0),
]
for lin in self.static_lines:
lin.friction = 0.8
self.space.add(self.static_lines)
# A sprite group which holds the pygame.sprite.Sprite objects.
self.sprite_group = pg.sprite.Group(Entity((150, 200), self.space))
def run(self):
while not self.done:
self.dt = self.clock.tick(30) / 1000
self.handle_events()
self.run_logic()
self.draw()
def handle_events(self):
for event in pg.event.get():
if event.type == pg.QUIT:
self.done = True
if event.type == pg.MOUSEBUTTONDOWN:
self.sprite_group.add(Entity(flipy(event.pos), self.space))
for sprite in self.sprite_group:
sprite.handle_event(event)
def run_logic(self):
self.space.step(1/60) # Update physics.
self.sprite_group.update(self.dt) # Update pygame sprites.
def draw(self):
self.screen.fill(pg.Color(140, 120, 110))
for line in self.static_lines:
body = line.body
p1 = flipy(body.position + line.a.rotated(body.angle))
p2 = flipy(body.position + line.b.rotated(body.angle))
pg.draw.line(self.screen, self.gray, p1, p2, 5)
self.sprite_group.draw(self.screen)
# Debug draw. Outlines of the Pymunk shapes.
for obj in self.sprite_group:
shape = obj.shape
ps = [pos.rotated(shape.body.angle) + shape.body.position
for pos in shape.get_vertices()]
ps = [flipy((pos)) for pos in ps]
ps += [ps[0]]
pg.draw.lines(self.screen, self.red, False, ps, 1)
pg.display.flip()
if __name__ == '__main__':
pg.init()
Game().run()
pg.quit()
我正在尝试学习 PyMunk,我使用了网站上的基本示例:
import pymunk
space = pymunk.Space()
space.gravity = 0,-1000
body = pymunk.Body(1,1666)
body.position = 50,100
poly = pymunk.Poly.create_box(body)
space.add(body, poly)
while True:
space.step(0.02)
但它不创建 window,不显示任何内容。如何使用PyGame创建图形window?
这个例子所做的是创建一个模拟,在里面添加一个盒子形状的对象,然后 运行 无限地模拟。该代码不打印或绘制任何内容,因此您实际上看不到输出。为了更好地理解屏幕上的内容,我建议您从教程开始:http://www.pymunk.org/en/latest/tutorials/SlideAndPinJoint.html
Pymunk 是一个二维刚体物理库,这意味着它所做的是模拟物体如何在二维空间中移动和相互作用。它不是为绘制到屏幕或读取输入而设计的。
你当然可以直接使用,直接打印模拟结果即可。但更常见的是你想在屏幕上绘图、读取输入等。一种方法是使用游戏库 Pygame,它有助于在屏幕上绘图、读取输入、进行游戏循环等等。
Pymunk 本身确实有一些辅助函数,因此您可以轻松地将它与 Pygame(以及其他几个库)连接起来,但这不是核心部分。通常这些辅助函数适用于您想要一些快速的东西(例如原型)并且您不需要自定义绘图。
现在,这就是说,如果你想看一些东西,你可以在 while 循环中添加一个 print 语句,所以它变成这样:
while True:
space.step(0.02)
print(body.position)
然后它会在模拟的每一步打印出球的位置,你可以看到它一直在变化(因为space上设置的重力)。
Pymunk 中包含更多高级示例,它们既可以交互又可以在屏幕上显示一些内容。这些示例主要依赖于 Pygame 或 Pyglet,但原则是相同的,以防您有不同的库要使用它。
这是一个示例,展示了我如何将 Pymunk 与 pygame 结合使用。 Entity
class 是一个 pygame.sprite.Sprite
subclass,我附加了一个 pymunk.Body
和一个 pymunk.Shape
以及对 pm.Space
,以便可以从中添加和删除主体和形状。精灵矩形的位置在每一帧都设置为 self.body.position
,这样我们就可以得到 self.image
的正确 blit 位置,并且可以通过调用 self.sprite_group.draw(self.screen)
简单地绘制所有精灵。
import math
import pygame as pg
import pymunk as pm
from pymunk import Vec2d
def flipy(p):
"""Convert chipmunk coordinates to pygame coordinates."""
return Vec2d(p[0], -p[1]+600)
class Entity(pg.sprite.Sprite):
def __init__(self, pos, space):
super().__init__()
self.image = pg.Surface((46, 52), pg.SRCALPHA)
pg.draw.polygon(self.image, (0, 50, 200),
[(0, 0), (48, 0), (48, 54), (24, 54)])
self.orig_image = self.image
self.rect = self.image.get_rect(topleft=pos)
vs = [(-23, 26), (23, 26), (23, -26), (0, -26)]
mass = 1
moment = pm.moment_for_poly(mass, vs)
self.body = pm.Body(mass, moment)
self.shape = pm.Poly(self.body, vs)
self.shape.friction = .9
self.body.position = pos
self.space = space
self.space.add(self.body, self.shape)
def update(self, dt):
pos = flipy(self.body.position)
self.rect.center = pos
self.image = pg.transform.rotate(
self.orig_image, math.degrees(self.body.angle))
self.rect = self.image.get_rect(center=self.rect.center)
# Remove sprites that have left the screen.
if pos.x < 20 or pos.y > 560:
self.space.remove(self.body, self.shape)
self.kill()
def handle_event(self, event):
if event.type == pg.KEYDOWN:
if event.key == pg.K_a:
self.body.angular_velocity = 5.5
elif event.key == pg.K_w:
self.body.apply_impulse_at_local_point(Vec2d(0, 900))
class Game:
def __init__(self):
self.done = False
self.clock = pg.time.Clock()
self.screen = pg.display.set_mode((800, 600))
self.gray = pg.Color('gray68')
self.red = pg.Color('red')
# Pymunk stuff.
self.space = pm.Space()
self.space.gravity = Vec2d(0.0, -900.0)
self.static_lines = [
pm.Segment(self.space.static_body, (60, 100), (370, 100), 0),
pm.Segment(self.space.static_body, (370, 100), (600, 300), 0),
]
for lin in self.static_lines:
lin.friction = 0.8
self.space.add(self.static_lines)
# A sprite group which holds the pygame.sprite.Sprite objects.
self.sprite_group = pg.sprite.Group(Entity((150, 200), self.space))
def run(self):
while not self.done:
self.dt = self.clock.tick(30) / 1000
self.handle_events()
self.run_logic()
self.draw()
def handle_events(self):
for event in pg.event.get():
if event.type == pg.QUIT:
self.done = True
if event.type == pg.MOUSEBUTTONDOWN:
self.sprite_group.add(Entity(flipy(event.pos), self.space))
for sprite in self.sprite_group:
sprite.handle_event(event)
def run_logic(self):
self.space.step(1/60) # Update physics.
self.sprite_group.update(self.dt) # Update pygame sprites.
def draw(self):
self.screen.fill(pg.Color(140, 120, 110))
for line in self.static_lines:
body = line.body
p1 = flipy(body.position + line.a.rotated(body.angle))
p2 = flipy(body.position + line.b.rotated(body.angle))
pg.draw.line(self.screen, self.gray, p1, p2, 5)
self.sprite_group.draw(self.screen)
# Debug draw. Outlines of the Pymunk shapes.
for obj in self.sprite_group:
shape = obj.shape
ps = [pos.rotated(shape.body.angle) + shape.body.position
for pos in shape.get_vertices()]
ps = [flipy((pos)) for pos in ps]
ps += [ps[0]]
pg.draw.lines(self.screen, self.red, False, ps, 1)
pg.display.flip()
if __name__ == '__main__':
pg.init()
Game().run()
pg.quit()