【问题标题】:Show PyMunk with PyGame - Python使用 PyGame 显示 PyMunk - Python
【发布时间】:2017-08-27 21:01:03
【问题描述】:

我正在尝试学习 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)

但它不会创建一个窗口,也不会显示任何东西。如何使用 PyGame 创建图形窗口?

【问题讨论】:

    标签: python python-3.x pygame pymunk


    【解决方案1】:

    该示例所做的是创建一个模拟,在其中添加一个盒子形状的对象,然后无限运行模拟。该代码不打印或绘制任何内容,因此您实际上不会看到输出。为了更好地理解屏幕上的内容,我建议您从教程开始:http://www.pymunk.org/en/latest/tutorials/SlideAndPinJoint.html

    Pymunk 是一个 2d 刚体物理库,这意味着它所做的是模拟对象如何在 2 维中移动和相互作用。它不是为绘制到屏幕或读取输入而设计的。

    您当然可以不加任何东西直接使用它,只需打印模拟结果即可。但更常见的是你想画到屏幕上,读取输入等等。一种方法是使用游戏库 Pygame,它有助于在屏幕上绘图、读取输入、拥有游戏循环等等。

    Pymunk 本身确实有一些辅助函数,因此您可以轻松地将它与 Pygame(以及其他几个库)连接起来,但这不是核心部分。通常,这些辅助函数适用于您想要一些快速n-dirty(例如原型)并且您不需要自定义绘图的情况。

    现在,这就是说,如果你想看到一些东西,你可以在 while 循环中添加一个 print 语句,所以它变成了这样:

    while True:
        space.step(0.02)
        print(body.position)
    

    然后它会打印出模拟的每一步球的位置,你可以看到它一直在变化(因为空间上设置的重力)。

    Pymunk 中包含更高级的示例,它们既可以交互又可以在屏幕上显示某些内容。这些示例主要依赖于 Pygame 或 Pyglet,但如果您想使用不同的库,原理是相同的。

    【讨论】:

    • 谢谢。你能给我一个如何将它连接到pygame的例子吗?我试图从这些例子中理解,但它们非常复杂。
    • 你看教程了吗?它在一个小演示中结合了 pymunk 和 pygame
    【解决方案2】:

    这是一个示例,展示了我如何将 Pymunk 与 pygame 结合使用。 Entity 类是 pygame.sprite.Sprite 子类,我附加了 pymunk.Bodypymunk.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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-22
      相关资源
      最近更新 更多