Вопрос-Ответ

Why is my collision test always returning 'true' and why is the position of the rectangle of the image always wrong (0, 0)?

Почему мой тест на столкновение всегда возвращает 'true' и почему положение прямоугольника изображения всегда неправильное (0, 0)?

Моя функция collide_rect не работает должным образом. Она всегда возвращает True, когда это не предполагается. Я пробовал искать в Интернете, но у меня ничего не работает. Я думаю, что collide rect каким-то образом не использовал фактические координаты для двух спрайтов. Кто-нибудь может помочь с этим?

import pygame
import pygame.sprite
import sys


gameDisplay = pygame.display.set_mode((800,600))
pygame.display.set_caption("test_collision")
clock = pygame.time.Clock()
crashed = False


class Ball(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("ball.png")
self.rect = self.image.get_rect()
self.x = 280
self.y = 475
self.col = False
def update(self):
gameDisplay.blit(self.image, (self.x,self.y))
self.rect = self.image.get_rect()
def test_collisions(self,sprite):
self.col = pygame.sprite.collide_rect(self,sprite)
class Obstacle(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.x = 1000
self.y = 483
self.image = pygame.image.load("obstacle.png")
self.time = pygame.time.get_ticks()
self.rect = self.image.get_rect()
def change_x(self):
self.time = pygame.time.get_ticks()
self.x = -(self.time/5) + 800
def update(self):
self.rect = self.image.get_rect()
gameDisplay.blit(self.image,(self.x,self.y))


obstacle = Obstacle()
ball = Ball()
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
gameDisplay.fill((255,255,255))
ball.update()
obstacle.change_x()
obstacle.update()
ball.test_collisions(obstacle)
if ball.col:
print("colided")
pygame.display.flip()
clock.tick(1000)


pygame.quit()
sys.exit()

P.S Это мой первый пост :)

Переведено автоматически
Ответ 1

pygame.Surface.get_rect.get_rect() возвращает прямоугольник с размером объекта Surface, но он возвращает прямоугольник, который всегда начинается с (0, 0), поскольку объект Surface не имеет позиции.
Поверхность размещается в определенном месте на дисплее с помощью blit функции.

Вы должны установить местоположение прямоугольника либо с помощью аргумента ключевого слова, например:

self.rect = self.image.get_rect(topleft = (self.x, self.y))

или присвоение виртуальному атрибуту (см. pygame.Rect), например:

self.rect = self.image.get_rect()
self.rect.topleft = (self.x, self.y)

Абсолютно нет необходимости добавлять некоторые дополнительные атрибуты self.x и self.y. Вместо этого используйте расположение прямоугольника. например:

class Ball(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("ball.png")
self.rect = self.image.get_rect(topleft = (280, 475))
self.col = False
def update(self):
gameDisplay.blit(self.image, self.rect)
def test_collisions(self,sprite):
self.col = pygame.sprite.collide_rect(self,sprite)

class Obstacle(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("obstacle.png")
self.time = pygame.time.get_ticks()
self.rect = self.image.get_rect(topleft = (1000, 483))
def change_x(self):
self.time = pygame.time.get_ticks()
self.rect.x = -(self.time/5) + 800
def update(self):
gameDisplay.blit(self.image, self.rect)

Далее обратите внимание, что вы можете избавиться от методов Ball.update() соответственно Obstacle.update() (вы можете удалить их), если вы используете pygame.sprite.Group и вызов .draw(), который использует .image и .rect свойства содержащихся в нем спрайтов, для их рисования. например:

obstacle = Obstacle()
ball = Ball()
all_sprites = pygame.sprite.Group([obstacle, ball])

while not crashed:

# [...]

gameDisplay.fill((255,255,255))

all_sprites.draw(gameDisplay)

pygame.display.flip()
clock.tick(1000)
python pygame