Pygame 与面具的碰撞

Pygame collision with masks

我做了一个推杆游戏,现在我想添加一个倾斜的墙类型。因此,我需要为碰撞使用遮罩(直到现在我才使用矩形)。我花了几个小时学习掩码并试图弄清楚为什么我的代码不起作用。没有错误,只是没有检测到碰撞。

我已将我的代码简化为更小的代码,以便我对其进行有效测试。从我所看到的一切来看,这似乎应该可行,但事实并非如此。这是:

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)

方法overlap() is the relative position of the othermask in relation to the pygame.mask.Mask对象的偏移量参数。
所以偏移量就是ball的坐标减去slant的坐标:

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")
    

当您创建蒙版图像时,我建议通过调用 .convert_alpha():

来确保图像具有每像素 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()) # <---

最小示例: repl.it/@Rabbid76/PyGame-SurfaceMaskIntersect

另请参阅:Mask