Я здесь, чтобы ответить на вопросы людей, которые хотят научиться программированию. Если вопрос, очевидно, звучит как «дай мне код» или «Я скопировал какой-то код отсюда и здесь; теперь исправь это для меня!», Я не вкладываю много усилий в ответ. Итак, я надеюсь, вы понимаете, почему приведенный ниже ответ является в основном теоретическим и не содержит проверенного и отлаженного кода.
Я полагаю, вы говорите о 2D-игре с «гравитацией», когда игрок прыгает и как-то падает. Если вы говорите о 2D подобном румянцу (вид сверху вниз, без гравитации), некоторые из приведенных ниже обозначений могут быть немного неточными, но logi c то же самое.
Основанная на тайлах «карта» или «уровень» может рассматриваться как набор слоев. Я бы разделил спрайты с возможностью столкновения в отдельную группу спрайтов, назовем их platforms
. Декоративные плитки могут быть go в группу background
. Фон - это нижний слой, который, помимо необходимости рисования, в противном случае можно игнорировать. Одно фоновое изображение может быть лучше для этого, чем целая куча спрайтов.
Итак, всякий раз, когда игрок пытается двигаться, платформы необходимо проверять на столкновение с новым thoretical-location before движение завершено. В объекте PyGame Sprite есть удобная функция под названием pygame.sprite.spritecollideany()
. Это позволяет вашему коду довольно легко проверять наличие столкновений между одним спрайтом и группой спрайтов while:
collided_with = player_sprite.spritecollideany( platform_sprite_group )
if ( collided_with != None ):
print( "Player collided with sprite: " + str( collided_with ) )
Еще одна удобная функция - pygame.sprite.groupcollide()
, это отлично подходит для столкновения группы спрайтов с другой - например куча стрел против кучи врагов. Но вы также можете создать группу спрайтов с одним элементом и использовать его также на отдельных объектах.
На самом деле вам не нужно знать, с какой стороны игрока сталкивается с платформами. Это неявная информация, потому что вы уже знаете, в какую сторону движется игрок. Основа тестирования столкновений заключается в том, что понимание того, что перемещение спрайта более чем на 1 пиксель за раз, может перемещать игрока поверх существующего спрайта, даже не касаясь стороны. Скажем, игрок двигался очень быстро, его следующая позиция для движения может быть прямо в середине другого спрайта! Так в какую сторону он попал? (Сторона, с которой переместился игрок.)
Так, например: если игрок хотел переместиться на 10 пикселей влево, но край платформы находится на расстоянии 5 пикселей, игрок «сталкивается», но не касается. Как только происходит столкновение, код должен определить, каким было бы допустимое движение, и скорректировать движение в соответствии с этой дельтой. Поскольку объекты-спрайты PyGame основаны на объекте Rect , это достаточно простой тест с использованием Rect x
, y
и width
, height
. 'X' и 'y' представляют верхний левый угол, поэтому нам нужно учитывать ширину спрайтов:
# Player has tried to move delta_x and delta_y pixels
collided_with = player_sprite.spritecollideany( background_sprite_group )
if ( collided_with != None ):
print( "Player collided with sprite: " + str( collided_with ) )
if ( delta_x > 0 ): # moving right
# collides on right side
distance_to_sprite_x = player_sprite.rect.x + player_sprite.rect.width - collided_with.rect.x
elif ( delta_x < 0 ): # moving left
# collides on left side (take width of sprite into account)
distance_to_sprite_x = player_sprite.rect.x - collided_with.rect.x + collided_with.rect.width
else: # not moving horizontally
distance_to_sprite_x = 0
# Adjust the x-movement to make it rest against the sprite
delta_x = distance_to_sprite_x
# TODO: similarly for delta_y
Очевидно, что игрок движется достаточно быстро (много пикселей на frame) теоретически он мог «перепрыгнуть» всю платформу, а не столкнуться, пройдя сквозь нее. Приведенный выше код страдает этой скрытой ошибкой. Но большинству игр не нужно беспокоиться о подобной ситуации.
Так что я надеюсь, что logi c, представленного выше, достаточно, чтобы вы начали обрабатывать всевозможные коллизии. Просто попробуйте заставить код работать, это лучший способ научиться. Напишите что-нибудь, проверьте это, сделайте ошибки, задайте вопросы по этому поводу. Мы готовы помочь. Легко попасть в ловушку, просто скопировав и вставив чужой код (который иногда бывает среднего качества), чтобы получить это «быстрое решение». Но на самом деле это не поможет вам изучить основы.