Python Pygame面具碰撞仅在第一次碰撞时对基地造成伤害

Python Pygame面具碰撞仅在第一次碰撞时对基地造成伤害,python,python-3.x,pygame,collision-detection,mask,Python,Python 3.x,Pygame,Collision Detection,Mask,我正在写一个简单的入侵者游戏。为了增加底座的损伤,我想我可以在子弹撞击时在底座上打一个黑色的小表面,然后用面罩检查子弹是在损伤处还是底座上,但它不起作用,我觉得我误解了面罩。第一次碰撞被检测到,但之后它也检测到碰撞,但不会对基座造成任何损坏。我以为因为表面是黑色的,所以基本遮罩不包括它,但它不起作用。下面是一个简短的测试来演示这一点。按空格键(或任意键)向底部发射子弹。我想也许我应该为基地制作一个新的面具,但那不起作用。面具碰撞来自github上的pygame精灵代码 import sys, p

我正在写一个简单的入侵者游戏。为了增加底座的损伤,我想我可以在子弹撞击时在底座上打一个黑色的小表面,然后用面罩检查子弹是在损伤处还是底座上,但它不起作用,我觉得我误解了面罩。第一次碰撞被检测到,但之后它也检测到碰撞,但不会对基座造成任何损坏。我以为因为表面是黑色的,所以基本遮罩不包括它,但它不起作用。下面是一个简短的测试来演示这一点。按空格键(或任意键)向底部发射子弹。我想也许我应该为基地制作一个新的面具,但那不起作用。面具碰撞来自github上的pygame精灵代码

import sys, pygame, random
from pygame.locals import *

screenwidth = 600
screenheight = 400

pygame.init()
screen = pygame.display.set_mode((screenwidth, screenheight))
pygame.display.set_caption("shoot 'em up")

screenrect = screen.get_rect()

black = (0, 0, 0)

blue = (10, 10, 255)
yellow = (238, 238, 0)

base_width = 80
base_height = 40

bullet_width = 3
bullet_height = 10

class Bullet(pygame.Surface):
    
    def __init__(self, point):
        super().__init__((bullet_width, bullet_height), pygame.SRCALPHA)
        self.rect = self.get_rect()
        self.rect.midbottom = point
        self.fill(yellow)
        self.velocity = -5
        self.alive = True
        self.mask = pygame.mask.from_surface(self)
            
    def update(self):
        
        self.rect.top += self.velocity
        
    def draw(self, surf):
        surf.blit(self, self.rect)

class Base(pygame.Surface):

    def __init__(self, x, y, colour):
        super().__init__((base_width, base_height), pygame.SRCALPHA)
        self.rect = self.get_rect()
        self.rect.x = x
        self.rect.y = y 
        self.fill(colour)
        self.alive = True
        
    def add_damage(self, bullet):
        width = random.randint(3, 6)
        height = random.randint(8, 12)
        damage = pygame.Surface((width, height), pygame.SRCALPHA)
        damage.fill(black)
        rect = damage.get_rect()
        rect.x = bullet.rect.x - self.rect.x
        rect.y = bullet.rect.top - self.rect.top 
        self.blit(damage, rect)
        #self.mask = pygame.mask.from_surface(self) 
    
    def draw(self, surf):
        surf.blit(self, self.rect)
        
class Test(pygame.Surface):

    def __init__(self):
        super().__init__((600, 400))

        self. base = Base(50, 300, blue)
        self.bullets = []
        
    def run(self):
    
        while 1:
            self.get_events()
            self.update()
            self.draw()
                
    def get_events(self):

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            
            if event.type == pygame.KEYDOWN:
                bullet = Bullet((60, 380))
                self.bullets.append(bullet)
                    
    def update(self):
        if self.bullets:
            for bullet in self.bullets:
                bullet.update()
                self.collision_check(bullet)
            
            for bullet in self.bullets:
                if not bullet.alive:
                    self.bullets.remove(bullet)
                    
    def collision_check(self, bullet):
        if bullet.rect.colliderect(self.base):
            if self.collide_mask(bullet, self.base):
                print("collide")
                self.base.add_damage(bullet)
                bullet.alive = False
                
    def collide_mask(self, left, right):

        xoffset = right.rect[0] - left.rect[0]
        yoffset = right.rect[1] - left.rect[1]

        try:
            leftmask = left.mask
        except AttributeError:
            leftmask = pygame.mask.from_surface(left)
        try:
            rightmask = right.mask
        except AttributeError:
            rightmask = pygame.mask.from_surface(right)
    
        return leftmask.overlap(rightmask, (xoffset, yoffset))

    def draw(self):
        self.fill(black)
        self.base.draw(self)
        
        for bullet in self.bullets:
            bullet.draw(self)
            
        screen.blit(self, (0,0))
        
        pygame.display.flip()
        
if __name__=="__main__":
    t = Test()
    t.run()
正如您所见,这不是使用pygame精灵。

如果对象发生更改,则需要使用重新创建掩码。但是,遮罩是从曲面的alpha通道生成的。因此,需要使受损区域透明。创建一个完全透明的矩形(RGBA=0,0,0,0),并使用特殊标志
BLEND\u RGBA\u MULT
(或
BLEND\u RGBA\u MIN
)创建矩形。最后,重新创建掩码:

damage=pygame.Surface((宽度、高度),pygame.SRCALPHA)
自我。blit(伤害,矩形,特殊标志=pygame.BLEND\u RGBA\u MULT)
self.mask=pygame.mask.from_曲面(self)
添加损坏
方法:

类基(pygame.Surface):
# [...]
def附加伤害(自身、子弹):
宽度=random.randint(3,6)
高度=random.randint(8,12)
伤害=pygame.Surface((宽度、高度),pygame.SRCALPHA)
rect=损坏。get_rect()
rect.x=bullet.rect.x-self.rect.x
rect.y=bullet.rect.top-self.rect.top
自我。blit(伤害,矩形,特殊标志=pygame.BLEND\u RGBA\u MULT)
self.mask=pygame.mask.from_曲面(self)

为什么你从
pygame.Surface
衍生而来,而不是
pygame.sprite.sprite
?我被困在我的项目中,看到有人的初级版本写得如此糟糕,以至于不真实,所以我写这篇文章是为了向他们展示如何编写入侵者。在我发送后,我决定添加碱基,然后使碱基更好(他们的没有碱基)和伤害。我不认为pygame文档提到了alpha通道的事情。我会再看一眼,也许我错过了,你知道当你发疯的时候是什么感觉吗