#python #pygame #collision-detection
#python #pygame #обнаружение столкновения
Вопрос:
Я пытаюсь добавить платформу в свою игру, чтобы после того, как вы нажмете на нее, игрок оставался на платформе, пока она не упадет, и в этом случае она упала бы на землю. Переход работает, но столкновения нет
Я попытался добавить некоторые из приведенных ниже типичных типов детекторов столкновений, но все они имеют недостатки
class Platform:
def __init__(self, x, y, background):
self.xpos = x
self.ypos = y
self.picture = background
self.picture = pygame.transform.scale(self.picture, (500, 100))
self.rect = self.picture.get_rect()
def draw(self):
screen.blit(self.picture, (self.xpos, self.ypos))
class Player:
def __init__(self, x, y, pic_one, pic_two, pic_three, pic_four):
self.xpos = x
self.ypos = y
self.speed_y = 0
self.speed_x = 0
self.picture = pic_one
self.picture_one = pic_one
self.picture_two = pic_two
self.picture_three = pic_three
self.picture_four = pic_four
self.on_ground = True
self.picture = pygame.transform.scale(self.picture, (100, 100))
self.rect = self.picture.get_rect()
def update(self):
self.xpos = self.speed_x
self.ypos = self.speed_y
GRAVITY = 0.9
self.speed_y = GRAVITY # Accelerate downwards.
self.xpos = self.speed_x
self.ypos = self.speed_y
if self.ypos >= 620:
self.ypos = 620
self.speed_y = 0
self.on_ground = True
if self.on_ground == True:
self.speed_y = 0
def jump(self):
if self.on_ground:
self.on_ground = False
self.speed_y = -20#Makes you move upwards
def draw(self):
screen.blit(self.picture, (self.xpos, self.ypos))
def is_collided_with(self, sprite):
return self.rect.colliderect(sprite.rect)
player_one = Player(30, 600, player_one_first_pic)
wood_platform = Platform(400, 400, platform_pic)
while True:
[...]
это типичный тип столкновения, который я бы попытался использовать, но, похоже, оператор if никогда не выполняется
if player_one.rect.bottom == wood_platform.rect.top:
player_one.on_ground = True
другой, на котором я пробовал, который определяет, сталкиваются ли прямоугольники
и оператор if является истинным, даже если прямоугольники не сталкиваются
if player_one.is_collided_with(wood_platform):
player_one.on_ground = True
этот метод мне неудобен, потому что его недостаточно
if player_one.ypos == 600:
player_one.on_ground = True
Фактические результаты для метода, который я использовал, заключались в том, что проигрыватель вообще не сталкивался с деревянной платформой
(Вот диаграмма, если вам нужно немного больше понимания:) Проверяет наличие столкновения, но, похоже, не работает
if player_one.rect.y == wood_platform.rect.y:
print(True)
player_one.on_ground = True
on_platform = True
else:
on_platform = False
изменения после каждого обновления
self.rect.x = self.xpos
self.rect.y = self.ypos
Ответ №1:
Что касается меня, проблема в том, что вы используете self.xpos
, self.ypos
для перемещения объекта и не меняете значения в self.rect
( self.rect.x
, self.rect.y
), но вы используете self.rect
для проверки столкновения.
Вы должны установить
self.rect.x = self.xpos
self.rect.y = self.ypos
прежде чем проверять столкновение.
И вы должны сделать это для всех движущихся объектов. Может быть, лучше делать это после каждого хода.
Вы могли бы использовать только self.rect.x
, self.rect.y
(вместо self.xpos, self.ypos
), но он может сохранять только целочисленные значения. Вы используете значение с плавающей точкой в gravity и self.rect.x
, self.rect.y
округляете позицию в меньшую сторону и получаете не очень плавную анимацию.
Но объекты, которые не используют силу тяжести с плавающей точкой или скорость с плавающей точкой, могут использовать только self.rect
для сохранения положения.
Комментарии:
1. Итак, если я сейчас сделаю, если player_one.rect.y (игрок один является объектом) == wood_platform.rect. будет ли это работать, потому что это то, что я чувствую себя наиболее комфортно
2. вы можете это сделать, но это может не сработать, если вы перемещаете игрока более чем на один пиксель за каждый ход. В один момент
player_one.rect.y
может быть меньше, чемwood_platform.rect.y
(поэтому оно не сталкивается), а в следующий момент оно может быть больше, чемwood_platform.rect.y
(поэтому оно сталкивается) и==
не будет его перехватывать. Лучше использоватьself.rect.colliderect(other.rect)
. Он также может распознавать столкновение слева / справа или когда вы прыгаете и голова игрока касается платформы внизу — поэтому он должен прекратить движение вверх и начать движение вниз.3. Хорошо, я добавил приведенный выше блок кода, но, похоже, этого все еще не происходит
4. используете ли вы
self.rect.x
,self.rect.y
в плеере и на платформе?5. Да, я могу подтвердить, что я делаю
Ответ №2:
У меня часто возникает такая же проблема в моей работе. Проверка равенства чисел может завершиться ошибкой при использовании чисел с плавающей точкой. Вы могли бы попытаться изменить это
if player_one.rect.bottom == wood_platform.rect.top:
player_one.on_ground = True
к этому:
margin = 0.001 # Whatever amount you feel comfy with.
if wood_platform.rect.top*(1-margin) <= player_one.rect.bottom <= wood_platform.rect.top*(1 margin):
player_one.on_ground = True