2014-11-21 81 views
1

我正在與pymunk一個傍克隆爲了學習如何的lib作品。我把球從牆上正確地彈起,但槳仍然拒絕留在由線段定義的矩形內,屏幕的每一側都有一個。pymunk - 如何限制移動?

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

+0

您可以發佈,是有關該問題的代碼的其他人呢?例如。在那裏你設置段,你在哪裏處理鍵盤處理器的結果等。 – 2014-11-21 10:53:54

+0

如果你還沒有這樣做,可能值得在chipmunk論壇上發佈這個問題的鏈接。 – 2014-11-21 15:59:22

回答

1

的問題是,可以直接在所述主體的每個幀中設置的速度。這將爲碰撞解算器帶來問題,並允許槳板穿過牆壁。要麼你改變它,以便你改用衝動,或者以另一種方式限制它的移動。

我在pymunk的例子文件夾類似的例子,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

注意,設置每一幀的速度可能有其他副作用,但在你的情況下,我認爲它應該工作得很好,就像突破的例子。

+0

我嘗試添加GrooveJoint,但它沒有奏效。槳比聯合指定的座標更進一步移動。或者這是預期的行爲? – Jovito 2014-11-22 07:33:02

+0

你的代碼和我的代碼(我從一開始就沒有看到)之間的區別在於你在按下按鍵時設置了速度,而我只在按下按鍵時設置了它。這就是爲什麼它在我的例子中效果更好。請參閱我的其他答案以獲取其他解決方案 – viblo 2014-11-25 13:13:26

0

一種解決方案是增加一些檢測當該槳葉到達頂/底壁,並且如果擊中限制速度爲僅在相反方向上被允許。

要做到這一點,你可以創建牆壁和槳之間的衝突處理。然後在begin函數中設置一個變量touches_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.) 
+0

你能舉一個例子來說明如何做到這一點嗎? – Jovito 2014-12-01 08:32:04

+0

我用一個例子更新了答案 – viblo 2014-12-05 07:19:56