1
votes

I believe I'm not updating the masks location correctly, according to the images position in the screen. I can't understand why, because, after updating the images x and y coordinate, I redraw the mask to match their location. I believe it doesn't colide, even after drawing the mask, because the mask isn't being updated to match the image's coordinates. Is that what's happening here? The minimal code is posted below:

import pygame
import random

pygame.init()

black = (0, 0, 0)
height = 600
width = 800
screen = pygame.display.set_mode((width, height))
white = (255, 255, 255)
FPS = 60
clock = pygame.time.Clock()

class Player(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((40, 50))
        self.image.fill(black)
        self.rect = self.image.get_rect()
        self.rect.x = 0 + self.rect.x
        self.rect.y = height - self.rect.height
        self.lead_x_change = 0
        self.lead_y_change = 0
        self.speed = 5
        self.health = 100
        self.mask = pygame.mask.from_surface(self.image)

    def move_x(self):

        self.rect.x += self.lead_x_change
        self.mask = pygame.mask.from_surface(self.image)

    def move_y(self):

        self.rect.y += self.lead_y_change
        self.mask = pygame.mask.from_surface(self.image)

    def move_xd_change(self):
        self.lead_x_change += self.speed

    def move_xa_change(self):
        self.lead_x_change += -self.speed

    def move_yu_change(self):
        self.lead_y_change += -self.speed

    def move_yd_change(self):
        self.lead_y_change += self.speed

    def stop_x_change(self):
        self.lead_x_change = 0

    def stop_y_change(self):
        self.lead_y_change = 0

class Apple(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((40, 50))
        self.image.fill(black)
        self.rect = self.image.get_rect()
        self.rect.x = random.randint(100, 700)
        self.rect.y = random.randint(100, 500)
        self.mask = pygame.mask.from_surface(self.image)



apple = Apple()
player = Player()

all_sprites = pygame.sprite.Group()
all_sprites.add(player, apple)
gameExit = False

while not gameExit:

    screen.fill(white)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            gameExit = True
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_w:

                player.move_yu_change()

            if event.key == pygame.K_s:

                player.move_yd_change()

            if event.key == pygame.K_d:

                player.move_xd_change()

            if event.key == pygame.K_a:

                player.move_xa_change()

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_w or event.key == pygame.K_s:

                player.stop_y_change()

            if event.key == pygame.K_d or event.key == pygame.K_a:

                player.stop_x_change()

    player.move_x()
    player.move_y()
    all_sprites.draw(screen)

    hit = pygame.sprite.collide_mask(player, apple)
    if hit:
        apple.rect.x = random.randint((100, 700))
        apple.rect.y = random.randint((100, 500))
        apple.mask = pygame.mask.from_surface(apple.image)

    pygame.display.flip()
    clock.tick(FPS)

pygame.quit()
quit()
1

1 Answers

2
votes

pygame.mask.from_surface works only if the surface has an alpha channel. Either pass pygame.SRCALPHA as the flags (the second) argument to pygame.Surface

self.image = pygame.Surface((40, 50), pygame.SRCALPHA)

or call convert_alpha

self.image = pygame.Surface((40, 50)).convert_alpha()

or call set_colorkey

self.image.set_colorkey((0, 0, 0))

By the way, there's no reason to create new masks in the move_x and move_y methods. You only have to do this if you modify the self.image surface. It would be better for the performance to create the masks beforehand and just switch them when you need another one.