如何使用Pymunk将一个身体放在另一个身体之上

时间:2016-07-25 19:26:46

标签: python pymunk

我有一个圆圈,顶部有一个方框:

Circle with box on top

圆圈是一个简单的马达。我希望盒子直接留在圆圈上。我尝试过不同的约束,但是我的大多数尝试都会让盒子翻到一边。

我最成功的尝试是将框的body.moment设置为pymunk.inf,并将框固定到圆圈。这很接近,但是当我直接在圆圈的中心上方时,盒子仍然会左右移动。我可以在那里手动设置它,但似乎我应该能够通过某种约束来实现它。

有什么想法吗?下面是一些使用Pymunk和Arcade库的示例代码。

import arcade
import pymunk
import math

SCREEN_WIDTH = 1200
SCREEN_HEIGHT = 800
BOX_SIZE = 45

class MyApplication(arcade.Window):
    """ Main application class. """

    def __init__(self, width, height):
        super().__init__(width, height)
        arcade.set_background_color(arcade.color.DARK_SLATE_GRAY)

        # -- Pymunk space
        self.space = pymunk.Space()
        self.space.gravity = (0.0, -900.0)

        # Create the floor
        body = pymunk.Body(body_type=pymunk.Body.STATIC)
        self.floor = pymunk.Segment(body, [0, 10], [SCREEN_WIDTH, 10], 0.0)
        self.floor.friction = 10
        self.space.add(self.floor)

        # Create the circle
        player_x = 300
        player_y = 300
        mass = 2
        radius = 25
        inertia = pymunk.moment_for_circle(mass, 0, radius, (0, 0))
        circle_body = pymunk.Body(mass, inertia)
        circle_body.position = pymunk.Vec2d(player_x, player_y)
        self.circle_shape = pymunk.Circle(circle_body, radius, pymunk.Vec2d(0, 0))
        self.circle_shape.friction = 1

        self.space.add(circle_body, self.circle_shape)

        # Create the box
        size = BOX_SIZE
        mass = 5
        moment = pymunk.moment_for_box(mass, (size, size))
        moment = pymunk.inf
        body = pymunk.Body(mass, moment)
        body.position = pymunk.Vec2d(player_x, player_y + 49)
        self.box_shape = pymunk.Poly.create_box(body, (size, size))
        self.box_shape.friction = 0.3
        self.space.add(body, self.box_shape)

        # Create a joint between them
        constraint = pymunk.constraint.PinJoint(self.box_shape.body, self.circle_shape.body)
        self.space.add(constraint)

        # Make the circle rotate
        constraint = pymunk.constraint.SimpleMotor(self.circle_shape.body, self.box_shape.body, -3)
        self.space.add(constraint)

    def on_draw(self):
        """
        Render the screen.
        """
        arcade.start_render()

        # Draw circle
        arcade.draw_circle_outline(self.circle_shape.body.position[0],
                                   self.circle_shape.body.position[1],
                                   self.circle_shape.radius,
                                   arcade.color.WHITE,
                                   2)

        # Draw box
        arcade.draw_rectangle_outline(self.box_shape.body.position[0],
                                      self.box_shape.body.position[1],
                                      BOX_SIZE,
                                      BOX_SIZE,
                                      arcade.color.WHITE, 2,
                                      tilt_angle=math.degrees(self.box_shape.body.angle))

        # Draw floor
        pv1 = self.floor.body.position + self.floor.a.rotated(self.floor.body.angle)
        pv2 = self.floor.body.position + self.floor.b.rotated(self.floor.body.angle)
        arcade.draw_line(pv1.x, pv1.y, pv2.x, pv2.y, arcade.color.WHITE, 2)

    def animate(self, delta_time):

        # Update physics
        self.space.step(1 / 80.0)

window = MyApplication(SCREEN_WIDTH, SCREEN_HEIGHT)

arcade.run()

1 个答案:

答案 0 :(得分:2)

你可以使用两个针接头而不是一个,在盒子上展开锚点。在现实生活中如何使其稳定:)

# Create a joint between them
constraint = pymunk.constraint.PinJoint(self.box_shape.body, self.circle_shape.body, (-20,0))
self.space.add(constraint)

constraint = pymunk.constraint.PinJoint(self.box_shape.body, self.circle_shape.body, (20,0))
self.space.add(constraint)

如果它不够好,你可以尝试在约束条件下尝试较低的error_bias值,但我不确定它有多大帮助。如果你需要它像素完美我不认为关节可以做到,它们总是会有一些小错误。所以在这种情况下,我认为你必须通过在相同的x值上绘制上下精灵来伪造它。