区分组中的对象

问题描述

在名为 powerUpGroup 的组中,有两个对象:speedUpjumpuP。以下代码检查 player 对象是否与组中的任何对象发生碰撞:

for eachPowerUp in powerUpGroup:        
    if pygame.sprite.spritecollide(eachPowerUp,playerGroup,False) :
        eachPowerUp.kill()

假设我希望程序在玩家与 speedUp 对象碰撞时打印“速度增加”。根据上面的代码,如果它是 speedUpjumpuP,它将打印消息,因为它们在同一组中。在不创建新组的情况下,python 有没有办法识别它们是不同对象运行某些代码

解决方法

如果 speedUpjumpUp 是不同的类,你应该在它们的类中实现它们的行为(多态性):

speepUp 类应该包含用于加速(或它所做的任何事情)和触发次要效果(例如向玩家显示内容并将其从游戏中移除)的代码,以及 jumpUp 类应该做同样的事情。当然,您可以深入抽象的兔子洞,但让我们保持简单。

这是一个小例子:

import pygame
from random import choice

class Actor(pygame.sprite.Sprite):
    def __init__(self,color,pos,*grps):
        super().__init__(*grps)
        self.image = pygame.Surface((64,64))
        self.image.fill(color)
        self.rect = self.image.get_rect(topleft=pos)
        
    def update(self,events,dt):
        pass

class Player(Actor):
    def __init__(self,*grps):
        super().__init__('dodgerblue',(400,300),*grps)
        self.pos = pygame.Vector2(self.rect.topleft)
        self.dir = pygame.Vector2((0,0))
        self.speed = 300
        
    def update(self,dt):
        pressed = pygame.key.get_pressed()
        self.dir.x,self.dir.y = (0,0)
        if pressed[pygame.K_d]: self.dir += ( 1,0)
        if pressed[pygame.K_a]: self.dir += (-1,0)
        if pressed[pygame.K_s]: self.dir += ( 0,1)
        if pressed[pygame.K_w]: self.dir += ( 0,-1)
        
        if self.dir.length() > 0:
            self.dir.normalize()
        
        self.pos += self.dir * self.speed * dt
        self.rect.topleft = self.pos
        

class PowerUp(Actor):
    def __init__(self,player,*grps):
        super().__init__(color,*grps)
        self.player = player

    def apply(self):
        pass

    def update(self,dt):
        if pygame.sprite.collide_rect(self,self.player):
            self.apply()
            self.kill()

class SpeedUp(PowerUp):
    def __init__(self,*grps):
        super().__init__('yellow',(100,100),*grps)
     
    def apply(self):
        print('Speed Up')
        self.player.speed += 200

class ColorChange(PowerUp):
    def __init__(self,*grps):
        super().__init__('purple',(600,*grps)
     
    def apply(self):
        print('ColorChange!')
        self.player.image.fill(choice(['green','blue','yellow','grey']))

def main():
    pygame.init()
    screen = pygame.display.set_mode((800,600))
    clock,dt = pygame.time.Clock(),0
    sprites = pygame.sprite.Group()
    player = Player(sprites)
    SpeedUp(player,sprites)
    ColorChange(player,sprites)
    while True:
        events = pygame.event.get()
        for e in events: 
            if e.type == pygame.QUIT:
                return
        screen.fill('black')
        sprites.draw(screen)
        sprites.update(events,dt)
        pygame.display.flip()
        dt = clock.tick(120)/1000
        
if __name__ == '__main__':
    main()

enter image description here

,

使用 if 语句检查加电是否为 speedUp

for eachPowerUp in powerUpGroup:        
    if pygame.sprite.spritecollide(eachPowerUp,playerGroup,False):
        if eachPowerUp == speedUp:
            print("Speed increased")
        eachPowerUp.kill()

编辑问题的第二部分: 您可以检查它是否是某个类,而不是检查电源是否是某个对象。 假设您有一个名为 SpeedUp 的类。您可以检查 eachPowerUp 是否为 SpeedUp 对象,然后打印您想要的消息。

for eachPowerUp in powerUpGroup:        
    if pygame.sprite.spritecollide(eachPowerUp,False):
        if type(eachPowerUp) == SpeedUp:
            print("Speed increased")
        eachPowerUp.kill()
,

前面的代码是两个精灵之间的相等性测试,而不是一种精灵。变量 speedUp 是您的 powerUpGroup 精灵之一。仅当玩家碰撞的特定 speedUp 是该变量中的特定 speedUp 时,if 语句才会为真。

所以我添加了一个属性。
在构造函数中(未在 OP 中添加),我有 self.type = "multiShot"self.type = "speed",具体取决于它是哪种类型。然后,一个 if 语句现在应该是这样的:

for eachPowerUp in powerUpGroup:
    if pygame.sprite.spritecollide(eachPowerUp,False) :
        if eachPowerUp.type == "multiShot" :
            ...
        elif eachPowerUp.type == "speed" :
            ...