pymunk - 如何限制运动?

时间:2014-11-21 09:54:25

标签: python pygame chipmunk pymunk

我正在用pymunk制作pong克隆,以了解lib的工作原理。我让球正确地从墙上弹起,但是桨仍然拒绝留在由段定义的矩形内,屏幕两侧各一个。

def handle_input(self):
    keys = pygame.key.get_pressed()
    if keys[K_UP]: return Vec2d(0, 200)
    elif keys[K_DOWN]: return Vec2d(0, -200)
    else: return Vec2d(0, 0)

此功能检测是否按下K_UPK_DOWN键。如果是,则返回具有所需速度的新矢量,然后将其分配给paddle.body.velocity。问题是,当桨到达屏幕的顶部或底部时,而不是停在那些坐标上,它会向上(或向下)进一步向上,直到释放相应的键,此时它会缓慢地返回到相反的位置。方向。该部分似乎对桨叶提供某种阻力,但只能设法将其停在屏幕中间。

out

为什么会这样? 如何限制球拍的移动,使其仅在周围区段建立的范围内移动?


来源game.py | paddle.py

2 个答案:

答案 0 :(得分:2)

问题是你每帧直接在身体上设置速度。这将为碰撞求解器带来问题,并允许桨叶穿过墙壁。要么你改变它以便你施加冲动,要么用另一种方式限制它的运动。

我在pymunk的examples文件夹中有一个类似的例子,breakout.py我用GrooveJoint来限制它的移动:

player_body = pymunk.Body(500, pymunk.inf)
player_shape = pymunk.Circle(player_body, 35)
player_shape.color = THECOLORS["red"]
player_shape.elasticity = 1.0
player_body.position = 300,100
# restrict movement of player to a straigt line 
move_joint = pymunk.GrooveJoint(space.static_body, player_body, (100,100), (500,100), (0,0))
space.add(player_body, player_shape, move_joint) 

此处的完整代码: https://github.com/viblo/pymunk/blob/master/examples/breakout.py

请注意,每帧设置速度可能会产生其他副作用,但在您的情况下,我认为它应该可以正常工作,就像突破示例一样。

答案 1 :(得分:0)

一种解决方案是在桨到达顶部/底部墙时添加一些检测,如果命中,则限制速度仅允许在相反方向。

要做到这一点,你可以在墙和桨之间创建一个碰撞处理程序。然后在begin函数中在paddle上设置一个变量touching_top / touching_bottom,并在另外设置变量为false。

这是桨上的一个基本示例,它使用这种技术每帧都设置速度,直到达到顶部:

import pymunk

space = pymunk.Space()

top = pymunk.Segment(space.static_body, (0,100), (100,100), 1)
space.add(top)
top.collision_type = 1

b = pymunk.Body(100,1000)
b.position = (50,50)
paddle = pymunk.Poly.create_box(b, (5,20))
paddle.collision_type = 2
space.add(b, paddle)

touching_top = False

def begin(space, arbiter, *args, **kwargs):
    global touching_top
    touching_top = True
    print "begin"
    return True

def separate(space, arbiter, *args, **kwargs):
    global touching_top
    touching_top = False
    print "separate"

space.add_collision_handler(1, 2, begin=begin, separate=separate)

for x in range(100):
    print paddle.body.position

    if not touching_top:
        paddle.body.velocity = (0,100)

    space.step(1/60.)