PyGame pygame.sprite.collide_mask не обнаруживает столкновения? - PullRequest
0 голосов
/ 02 июля 2018

Я пытаюсь создать простую версию Flappy Bird. Для обнаружения столкновений между моим кругом (Flappy Bird) и моими прямоугольниками (Pipes) я использовал pygame.sprite.collide_rect (), но мне нужен лучший способ обработки столкновений.

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

Вот мой код:

bird_group = pygame.sprite.Group()
pipe_group = pygame.sprite.Group()

class Bird(pygame.sprite.Sprite):
    def __init__(self, x_loc, y_loc, velocity):
        super(Bird, self).__init__()
        self.velocity = velocity
        self.x_loc = x_loc
        self.y_loc = y_loc
        self.image = pygame.image.load(os.path.join(game_folder,"index2.png")).convert()
        self.image.set_colorkey(WHITE)
        self.image = pygame.transform.scale(self.image,(60,65))
        self.rect = self.image.get_rect()
        self.rect.center = (x_loc,y_loc)
    def update(self):
        self.rect.y += self.velocity
        self.velocity = self.velocity+1
        self.mask = pygame.mask.from_surface(self.image)
    def jump(self):
        self.velocity = -10
    def boundary_collison(self):
        if self.rect.bottom+100>=display_height or self.rect.top<=0:
            return True

class UpperPipe(pygame.sprite.Sprite):
    """docstring for UpperPipe"""
    def __init__(self, pipe_x, pipe_height, pipe_speed):
        super(UpperPipe, self).__init__()
        self.pipe_speed = pipe_speed
        self.image = pygame.Surface((pipe_width, pipe_height))
        self.image.fill(GREEN)
        self.rect = self.image.get_rect()
        self.rect.x = (pipe_x)
        self.rect.y = (0)
    def update(self):
        self.rect.x -= self.pipe_speed
        self.mask = pygame.mask.from_surface(self.image)
    def x_cord(self):
        return self.rect.x

class LowerPipe(pygame.sprite.Sprite):
    """docstring for UpperPipe"""
    def __init__(self, pipe_x, pipe_height, pipe_speed):
        super(LowerPipe, self).__init__()
        self.pipe_speed = pipe_speed
        self.image = pygame.Surface((pipe_width, display_height-(pipe_gap+pipe_height)))
        self.image.fill(GREEN)
        self.rect = self.image.get_rect()
        self.rect.x = (pipe_x)
        self.rect.y = (pipe_height+pipe_gap)
    def update(self):
        self.rect.x -= self.pipe_speed
        self.mask = pygame.mask.from_surface(self.image)
    def x_cord(self):
        return self.rect.x

Следующий код, который я использую для создания спрайтов:

bird = Bird(x_loc,y_loc,velocity)
bird_group.add(bird)

pipe_list = []
init_pipe_x = 500
for make in range(pipe_count):
    pipe_x = init_pipe_x+((between_pipe+pipe_width)*make)
    pipe_height = (round(random.uniform(0.2,0.8), 2))*(display_height-pipe_gap)
    upper = UpperPipe(pipe_x,pipe_height,pipe_speed)
    lower = LowerPipe(pipe_x,pipe_height,pipe_speed)
    add_pipe = [upper,lower]
    pipe_list.append(add_pipe)
    pipe_group.add(upper)
    pipe_group.add(lower)

Для обнаружения внутри игрового цикла я использую следующий код:

bird_hits = pygame.sprite.spritecollide(bird,pipe_group,False,pygame.sprite.collide_mask)
if bird_hits:
    gameExit = True

Ответы [ 2 ]

0 голосов
/ 03 июля 2018

pygame.Surface s, которые вы передаете mask.from_surface, должны иметь альфа-канал. Это означает, что вам нужно либо вызвать метод convert_alpha или set_colorkey поверхностей.

class UpperPipe(pygame.sprite.Sprite):

    def __init__(self, pipe_x, pipe_height, pipe_speed):
        super(LowerPipe, self).__init__()
        self.pipe_speed = pipe_speed
        # Either call `convert_alpha` ...
        self.image = pygame.Surface((pipe_width, display_height-(pipe_gap+pipe_height))).convert_alpha()
        self.image.fill(GREEN)
        # ... or call `set_colorkey`.
        # I think surfaces converted with convert_alpha are blitted faster.
        # self.image.set_colorkey((0, 0, 0))

        # You also don't have to create the mask repeatedly in the
        # update method. Just call it once in the __init__ method.
        self.mask = pygame.mask.from_surface(self.image)
0 голосов
/ 02 июля 2018

Вы не определили ни одного collide_mask в своем классе: что-то вроде

self.mask = pygame.mask.from_surface(image) 

Так что, если прямоугольник вашей верхней и нижней трубы соответствует хитбиксу этих: просто используйте

bird_hits = pygame.sprite.spritecollide(bird,pipe_group,False)

или создайте собственную маску class для использования

bird_hits = pygame.sprite.spritecollide(bird,pipe_group,False,pygame.sprite.collide_mask)
...