Daeshaun Morrison
Daeshaun Morrison

Reputation: 33

Difficiating objects in a group

In a group called powerUpGroup, there are two objects: speedUp and jumpUP. The following code checks if the player object has collided with any objects in the group:

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

Let's say I only want the program to print "Speed increased" when the player collides with speedUp object. Based on the code above, it will print the message if it either speedUp or jumpUP since they are in the same group. Without creating a new group, is there a way for python to identify that they are different objects run certain code?

Upvotes: 3

Views: 47

Answers (3)

Daeshaun Morrison
Daeshaun Morrison

Reputation: 33

The previous code was an equality test between two sprites, not a type of sprite. The variable speedUp is one of your powerUpGroup sprites. The if statement will only be true if the particular speedUp that the player is colliding with is the particular speedUp in that variable.

So I added a property.
In the constructor(That was not added in the OP), I have self.type = "multiShot" or self.type = "speed", depending on which type it is. Then, an if statement would now be something like:

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

        

Upvotes: 0

AlarmClockMan
AlarmClockMan

Reputation: 458

Use an if statement to check if the power-up is speedUp

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

Edit for second part of question: Instead of checking if the power up is a certain object, you can check if it is a certain class. Say you have a class called SpeedUp. You can check to see if eachPowerUp is a SpeedUp object and then print the message you wanted.

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

Upvotes: 0

sloth
sloth

Reputation: 101122

If speedUp and jumpUp are different classes, you should implement their behaviour in their very classes (something something polymorphism):

The speepUp class should contain the code for speeding up (or whatever it does) and trigger secondary effects (like displaying stuff to the player and removing itself from the game), and the jumpUp class should do the same. Of course you could go down the abstraction rabbit hole but let's keep it simple.

Here's a litte example:

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, events, 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, color, pos, player, *grps):
        super().__init__(color, pos, *grps)
        self.player = player

    def apply(self):
        pass

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

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

class ColorChange(PowerUp):
    def __init__(self, player, *grps):
        super().__init__('purple', (600, 300), player, *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

Upvotes: 2

Related Questions