电子游戏与面具的碰撞

2022-02-22 00:00:00 python pygame mask collision-detection

问题描述

我做了一个推杆-推杆游戏,现在我想添加一个斜墙类型。正因为如此,我需要使用遮罩来进行碰撞(到目前为止,我只使用了RECT)。我花了几个小时学习面具,并试图弄清楚为什么我的代码不能工作。没有错误,只是没有检测到冲突。

我已经将我的代码简化为小得多的代码,以此作为我有效测试它的一种方式。从我所看到的一切来看,这似乎应该奏效,但事实并非如此。这就是:

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()的偏移量参数是othermask相对于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

相关文章