2014-11-21 5 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_UP или K_DOWN нажатия клавиш. Если это так, он возвращает новый вектор с требуемой скоростью, который затем присваивается paddle.body.velocity. Проблема заключается в том, что когда весло достигает верхней или нижней части экрана, вместо того, чтобы останавливаться на этих координатах, оно идет немного дальше (или вниз) до тех пор, пока соответствующий ключ не будет отпущен, и в этот момент он медленно возвращается в противоположную сторону направление. Кажется, что сегмент предлагает какое-то сопротивление весле, но ему удается остановить его на полпути от экрана.

out

Почему это происходит? Как я могу ограничить движение весла так, чтобы он двигался только в пределах, установленных окружающими сегментами?


Источник: game.py | paddle.py

+0

Вы можете разместить остальную часть кода, которая имеет отношение к проблеме? Например. где вы настраиваете сегменты, где вы обрабатываете результат обработчика клавиатуры и т. д. –

+0

Если вы этого еще не сделали, возможно, стоит опубликовать ссылку на этот вопрос на форуме chipmunk. –

ответ

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

+0

Разница между вашим кодом и моим (что я не видел с самого начала) заключается в том, что вы устанавливаете скорость, пока нажата клавиша, в то время как я только устанавливаю ее на клавишу вниз. Вот почему он работал лучше в моем примере. См. Мой другой ответ для другого решения. – viblo

0

Одним из решений является добавление некоторого обнаружения, когда лопасть достигает верхних/нижних стенок и, если удар ограничивает скорость, допускается только в противоположном направлении.

Для этого вы можете создать столкновение между стенами и веслом. Затем в функции begin задайте переменную 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.) 
+0

Можете ли вы привести пример о том, как это сделать? – Jovito

+0

Я обновил ответ на примере – viblo

 Смежные вопросы

  • Нет связанных вопросов^_^