首页 > 解决方案 > 我使用 pygame.sprite.groupcollide 来检测 pygame 中的碰撞,但删除组精灵有问题

问题描述

我正在 pygame 上制作经典游戏,外星人舰队降落在屏幕上,当舰队侧身穿过屏幕并从屏幕上向下移动时,英雄的船需要击落外星人。我正在使用 pygame.sprite.groupcollide(ammunition, aliens, True, True) 函数。在我做的测试中,我注意到如果我用一枪击中外星人,当舰队到达屏幕边缘而没有被摧毁的外星人时,整个舰队就像一只虫子一样从屏幕上跑下来。如果我不消灭任何外星人,舰队就会正确移动,从右到左,然后在屏幕上下降一层,以此类推,直到它消失在屏幕底部。如果你用一枪击中外星人,整个舰队到达屏幕边缘并立即下降会出现问题。

代码:

入侵外星人.py

import pygame
from pygame.sprite import Group
from configuracoes import Configuracoes             #módulo configurações
from nave import Nave                               #módulo nave (herói)
import jogo_funcoes as jf                           #módulo funções do jogo com aliás jf


def run_game():
    pygame.init()                                                #Inicializa o jogo e cria um objeto para a tela
    ai_configuracoes = Configuracoes()                           #objeto ai_configuracoes da Classe Configuracoes
    tela = pygame.display.set_mode ((ai_configuracoes.tela_width, ai_configuracoes.tela_height))
    pygame.display.set_caption("Space War")
    nave_espacial = Nave(ai_configuracoes, tela)                 #objeto nave_espacial da classe Nave
    municoes = Group()                                           #Cria um grupo no qual serão armazenados as munições
    aliens = Group()                                             #Cria um grupo vazio para armazenar os aliens do jogo
    jf.cria_frota(ai_configuracoes, tela, nave_espacial, aliens) #Cria uma frota de aliens (usa configurações, tela e um grupo vazio de aliens)



    while True:   #Inicia o laço principal do jogo
        jf.check_eventos(ai_configuracoes, tela, nave_espacial, municoes)           #checa os eventos
        nave_espacial.update_nave()                                                 #posicionamento da nave
        jf.update_municoes(ai_configuracoes, tela, nave_espacial, aliens, municoes) #verifica as municoes na tela ,se houve disparo
        jf.update_aliens(ai_configuracoes, aliens)
        jf.update_tela(ai_configuracoes, tela, nave_espacial, aliens,  municoes)    #update da tela



run_game()

jogo_funcoes.py

"""Módulo que armazena as  funções do jogo"""
import sys
import pygame
from municao import Municao
from alien import Alien



def check_keydown_events(evento, ai_configuracoes, tela, nave_espacial, municoes):
    """Responde a pressionamento de teclas"""
    if evento.key == pygame.K_RIGHT:
        nave_espacial.move_direita = True
    elif evento.key == pygame.K_LEFT:
        nave_espacial.move_esquerda = True
    elif evento.key == pygame.K_SPACE:                         #Esta condição cria um novo projétil e adiciona ao grupo de projéteis
        tiro_municao(ai_configuracoes, tela, nave_espacial, municoes)
    elif evento.key == pygame.K_q:
        sys.exit()

def check_eventos(ai_configuracoes, tela, nave_espacial, municoes):
    """Responde a eventos de pressionamento de teclas e do mouse"""
    for evento in pygame.event.get():                          #pegar cada evento
        if evento.type == pygame.QUIT:                         #caso seja solicitado a saída
            sys.exit()
        elif evento.type == pygame.KEYDOWN:                    #pressionamento de tecla
            check_keydown_events(evento, ai_configuracoes, tela, nave_espacial, municoes)
        elif evento.type == pygame.KEYUP:                      #soltura de tecla
            check_keyup_events(evento, nave_espacial)


def check_keyup_events(evento, nave_espacial):
    """Responde a solturas de tecla"""
    if evento.key == pygame.K_RIGHT:
        nave_espacial.move_direita = False
    elif evento.key == pygame.K_LEFT:
        nave_espacial.move_esquerda = False
    elif evento.key == pygame.K_q:
        sys.exit()


def update_tela(ai_configuracoes, tela, nave_espacial, aliens, municoes):
    """Atualiza as imagens na tela e alterna para a nova tela"""
    tela.fill(ai_configuracoes.bg_color)
    for municao in municoes.sprites():
        municao.desenha_projetil()
    nave_espacial.blitme()
    aliens.draw(tela)         #desenha cada alienigena do grupo na tela
    pygame.display.flip()


def update_municoes(ai_configuracoes, tela, nave_espacial, aliens, municoes):
    """Atualiza as posicoes dos projéteis antigos, se o projétil chega ao fim da tela é removido"""
    municoes.update()
    for municao in municoes.copy():
        if municao.rect.bottom <= 0:                               #verifica se o projétil chegou ao fim da tela
            municoes.remove(municao)
        check_municao_alien_colisoes(ai_configuracoes, tela, nave_espacial, municoes, aliens)


def check_municao_alien_colisoes(ai_configuracoes, tela, nave_espacial, municoes, aliens):
    """Responde a colisões entre projéteis e alienígenas."""
    colisoes = pygame.sprite.groupcollide(municoes, aliens, True, True)  # verifica se algum projétil atingiu os alienígenas , em caso afirmativo se livra do projétil e do alien
    if len(aliens) == 0:          #Destrói os projéteis existentes e cria uma nova frota
        municoes.empty()          #remove todos os sprites de munições
        cria_frota(ai_configuracoes, tela, nave_espacial, aliens)


def tiro_municao(ai_configuracoes, tela, nave_espacial, municoes):
    """Dispara um projétil se o limite ainda não foi lançado"""
    if len(municoes) < ai_configuracoes.municoes_permitida:         #Caso não tenha número máximo de munições na tela(3) , add munição
        nova_municao = Municao(ai_configuracoes, tela, nave_espacial)
        municoes.add(nova_municao)                                  #adicionando munição ao grupo municoes (criado no arquivo principal)



def criar_alien(ai_configuracoes, tela, aliens, qtde_aliens, linha):
    alien = Alien(ai_configuracoes, tela)                           #Cria uma nave alien
    alien_width = alien.rect.width
    alien.x = alien_width + 2 * alien_width * qtde_aliens
    alien.rect.x = alien.x
    alien.rect.y = alien.rect.height + 2 * alien.rect.height * linha
    aliens.add(alien)


def get_numero_aliens_x(ai_configuracoes, alien_largura ):
    """Determina o número de alienígenas que cabem em uma linha"""
    espaco_livre_x = ai_configuracoes.tela_width - 2 * alien_largura
    numero_aliens_x = int(espaco_livre_x / (2 * alien_largura ))
    return numero_aliens_x



def get_numero_linhas(ai_configuracoes, nave_espacial, alien):
    """Determina o número de linhas com alinígenas que cabem na tela"""
    espaco_livre_y = (ai_configuracoes.tela_height - (3 * alien.rect.height) - nave_espacial.rect.height)
    numero_linhas = int(espaco_livre_y / (2 * alien.rect.height))
    return numero_linhas


def cria_frota(ai_configuracoes, tela, nave_espacial, aliens):
    """Cria uma frota completa de aliens"""
    alien = Alien(ai_configuracoes, tela)  #Cria um alienígena
    alien_largura = alien.rect.width
    numero_aliens_x = get_numero_aliens_x(ai_configuracoes, alien_largura)   #Calcula a qtde de alienígenas que cabem numa linha
    numero_linhas = get_numero_linhas(ai_configuracoes, nave_espacial, alien)
    for linha in range(numero_linhas):                                      #laço para preencher as linhas da tela(eixo y) com aliens
        for qtde_aliens in range(numero_aliens_x):                          #laço para preencher uma linha (eixo x) com aliens
            criar_alien(ai_configuracoes, tela, aliens, qtde_aliens, linha)
        aliens.add(alien)  #Adiciona o alienígena criado ao Group()


def check_frota_bordas(ai_configuracoes, aliens):
    """Responde se algum alien chegou na borda da tela"""
    for alien in aliens.sprites():
        if alien.check_bordas():
            trocar_direcao_frota(ai_configuracoes, aliens)
            break



def trocar_direcao_frota(ai_configuracoes, aliens):
    """Faz a frota inteira descer e mudar a direcao"""
    for alien in aliens.sprites():
        alien.rect.y += ai_configuracoes.frota_drop_speed                   #horda desce na tela
        ai_configuracoes.frota_direcao *= -1                             #muda a direção do alien


def update_aliens(ai_configuracoes, aliens):
    """Verifica se a frota está numa das bordas e então atualiza as posições dos aliens"""
    check_frota_bordas(ai_configuracoes, aliens)
    aliens.update()  # Usando o método update() no Grupo aliens , fará o método update() de cada alienígena ser chamado automaticamente

网吧.py

import pygame
from pygame.sprite import Sprite

class Municao(Sprite):
    """Uma classe que administra projéteis disparados  pela espaçonave"""

    def __init__(self, ai_configuracoes, tela, nave_espacial):
        """Cria um objeto para o projétil na posição atual da espaçonave"""
        super(Municao, self).__init__()                                        #herdando de Sprite
        self.tela = tela
        self.rect = pygame.Rect(0, 0, ai_configuracoes.municao_width, ai_configuracoes.municao_height) #Cria um projétil em (0,0) e define a posição correta
        self.rect.centerx = nave_espacial.rect.centerx                                                 #rect do projétil igual ao da nave
        self.rect.top = nave_espacial.rect.top                                                         #rect top do projétil igual ao topo da nave
        self.y = float(self.rect.y)             #Armazena a posição do projétil como um valor decimal na orientação y para ajustes de velocidade do mesmo
        self.color = ai_configuracoes.municao_color
        self.speed_factor = ai_configuracoes.municao_speed_factor


    def update(self):
        """Move o projétil para cima na tela"""
        self.y -= self.speed_factor             #Dá velocidade ao projétil alterando sua posição no eixo y (subindo na tela)
        self.rect.y = self.y                 #Atualiza a posição de rect


    def desenha_projetil(self):
        """Desenha o projétil na tela"""
        pygame.draw.rect(self.tela, self.color, self.rect)

外星人.py

import pygame
from pygame.sprite import Sprite


class Alien(Sprite):
    """Uma classe que representa um único alienígena da frota."""
    def __init__(self, ai_configuracoes, tela):
        """Inicializa o alienígena e define sua posição inicial."""
        super(Alien, self).__init__()
        self.tela = tela
        self.ai_configuracoes = ai_configuracoes
        self.image = pygame.image.load('/home/marco_user/Documentos/Projetos/Python_ProjetoLivro/imagens/aliens-1.bmp')
        self.rect = self.image.get_rect()
        self.rect.x = self.rect.width    #Inicia cada novo alienígena próximo à parte superior esquerda da tela
        self.rect.y = self.rect.height
        self.x = float(self.rect.x)                 #Armazena a posição exata do alienígena


    def check_bordas(self):
        """Verifica se o alienígena chegou na borda da tela e devolve True"""
        tela_rect = self.tela.get_rect()
        if self.rect.right >= tela_rect.right:        #SE frota alien na borda direita da tela
            return True
        elif self.rect.left <= 0:                             #SE frota alien na borda esquerda da tela
            return True


    def update(self):
        """Move o alienígena para a direita ou para a esquerda"""
        self.x += (self.ai_configuracoes.alien_speed_factor * self.ai_configuracoes.frota_direcao) #Soma o fator de velocidade ao eixo x da imagem do alien
        self.rect.x = self.x #Atualizo a posição do rect do alien

nave.py

class Nave():
    def __init__(self, ai_configuracoes, tela):
        """Inicializa a espaçonave e define sua posição inicial."""
        self.ai_configuracoes = ai_configuracoes
        self.tela = tela
        self.image = pygame.image.load('/home/marco_user/Documentos/Projetos/Python_ProjetoLivro/imagens/nave_nova1.bmp')   #Carrega a imagem da espaçonave
        self.rect = self.image.get_rect()                    #atributo da superfície - o Pygame trata elementos como retângulos , rects
        self.tela_rect = tela.get_rect()
        self.rect.centerx = self.tela_rect.centerx            #Inicia cada nova espaçonave na parte inferior central da tela
        self.center = float(self.rect.centerx)                #Transforma self.rect.centerx em ponto flutuante para aceitar valores decimais
        self.rect.bottom = self.tela_rect.bottom              #Inicia cada nova espaçonave na parte inferior
        self.move_direita = False                             #Flag de movimento da nave para a direita
        self.move_esquerda = False                            #Flag de movimento da nave para a esquerda



    def update_nave(self):
        """Atualiza a posição da espaçonave de acordo com a flag de movimento"""
        if self.move_direita and (self.rect.right < self.tela_rect.right):  #se flag True e se antes do FIM DIREITO da tela
            self.center += self.ai_configuracoes.nave_speed_factor          #utiliza o fator de 1.5 de movimento definido em Configurações

        if self.move_esquerda and self.rect.left > 0:                       #se a flag para a esquerda for True e não for o FIM ESQUERDO da tela
            self.center -= self.ai_configuracoes.nave_speed_factor          #utiliza o fator de 1.5 de movimento

        self.rect.centerx = self.center                                     #Atualiza o objeto rect(que controla a posição da nave) de acordo com self.center


    def blitme(self):
        """Desenha a espaçonave em sua posição atual"""
        self.tela.blit(self.image, self.rect)

配置文件.py

"""Módulo de Configurações"""

class Configuracoes():
    """Uma classe para  armazenar todas as configurações da Invasão Alienígena"""
    def __init__(self):
        """Inicializa as configurações do jogo"""
        self.tela_width = 1359            #Configuração da tela , largura
        self.tela_height = 700             #Configuracao da tela , altura
        self.bg_color = (0, 0, 0)          #Configuração da cor de fundo da tela
        self.nave_speed_factor = 1.5       #Configurações da espaçonave para ajuste da velocidade
        self.alien_speed_factor = 1        #Configuração da espaçonave alienígena para ajuste de velocidade
        self.frota_drop_speed = 10         #Configuração da velocidade com que a frota desce na tela após chegar nas bordas da tela
        self.frota_direcao = 1          #fleet_direction -1 representa direção para a esquerda da tela, 1 seria para a direita
        self.municao_width = 1           #largura do projétil
        self.municao_height = 15           #tamanho do projétil
        self.municao_color = 247, 20, 43   #cor do projétil
        self.municao_speed_factor = 1      #velocidade do projétil
        self.municoes_permitida = 3        #atributo que limita a 3 tiros ao mesmo tempo na tela

标签: pythonpygamespritecollision

解决方案


推荐阅读