2016-07-25 201 views
4

我有一個圓圈,在上面一箱,以保持一個機構在另一個之上:如何使用Pymunk

Circle with box on top

圓是一個簡單的運動。我希望盒子能夠直接放在圓上。我嘗試了不同的約束條件,但是我的大部分嘗試都會導致盒子翻到一邊。

我最成功的嘗試是將box的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() 
+0

你可以發佈有問題的代碼嗎?用[mcve] –

+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值上繪製上部和下部精靈來僞造它。

+0

這個工程!謝謝。 –