I have made a putt-putt game and now I want to add a slanted wall type. Because of this, I need to use masks for the collision (until now I have just used rects). I have spent hours learning about masks and trying to figure out why my code won’t work. There are no errors, the collision just isn’t detected.
I have simplified my code down to something much smaller just as a way for me to test it efficiently. From everything I’ve seen this seems like it should work, but it doesnt. Here it is:
import pygame # Pygame init stuff pygame.init() wind_width = 1200 wind_height = 700 gameDisplay = pygame.display.set_mode((wind_width, wind_height)) pygame.display.set_caption("Mini Golf!") pygame.display.update() gameExit = False clock = pygame.time.Clock() # Class setups class Ball: def __init__(self, x, y): self.x = x self.y = y self.image = pygame.image.load("sball.png") self.rect = self.image.get_rect() self.mask = pygame.mask.from_surface(self.image) def render(self): self.rect.topleft = (self.x, self.y) gameDisplay.blit(self.image, self.rect) class Slant: def __init__(self, x, y): self.x = x self.y = y self.image = pygame.image.load("posslant.png") self.rect = self.image.get_rect() self.mask = pygame.mask.from_surface(self.image) def render(self): self.rect.topleft = (self.x, self.y) gameDisplay.blit(self.image, self.rect) # Creating objects ball = Ball(250, 250) slant = Slant(270, 250) # Game loop gameExit = False while not(gameExit): # Moves ball for event in pygame.event.get(): if event.type == pygame.QUIT: gameExit = True elif event.type == pygame.KEYDOWN: if event.key == pygame.K_UP: ball.y -= 1 elif event.key == pygame.K_DOWN: ball.y += 1 elif event.key == pygame.K_LEFT: ball.x -= 1 elif event.key == pygame.K_RIGHT: ball.x += 1 # Collision detection offset_x, offset_y = (slant.rect.x - ball.rect.x), (slant.rect.y - ball.rect.y) if slant.mask.overlap(ball.mask, (offset_x, offset_y)): print("hit") # Draws everything gameDisplay.fill((0, 0, 0)) ball.render() slant.render() pygame.display.update() clock.tick(100)
Advertisement
Answer
The offset parameter of the method overlap()
is the relative position of the othermask
in relation to the pygame.mask.Mask
object.
So the offset is calculated by subtracting the coordinates of slant
from the coordinates of ball
:
offset_x, offset_y = (slant.rect.x - ball.rect.x), (slant.rect.y - ball.rect.y)
offset = (ball.rect.x - slant.rect.x), (ball.rect.y - slant.rect.y) if slant.mask.overlap(ball.mask, offset): print("hit")
When you create the mask images, then I recommend to ensure that the image has per pixel alpha format by calling .convert_alpha()
:
class Ball: def __init__(self, x, y): self.x = x self.y = y self.image = pygame.image.load("sball.png") self.rect = self.image.get_rect() self.mask = pygame.mask.from_surface(self.image.convert_alpha()) # <---
class Slant: def __init__(self, x, y): self.x = x self.y = y self.image = pygame.image.load("posslant.png") self.rect = self.image.get_rect() self.mask = pygame.mask.from_surface(self.image.image.convert_alpha()) # <---
Minimal example: repl.it/@Rabbid76/PyGame-SurfaceMaskIntersect
See also: Mask