Search code examples
pythondictionarypygamecollision

Python, pygame, collisions and dictionaries


I am using the below code to try and code basic collisions using pygame. Almost all of the built in collision method return python dictionaries which are new to me. Using many internet sources I have discovered how to search a dictionary, however the dictionary returned by the method does not appear to follow the same rules and therefore i am unable to search it for which sprites collide. Either a new collision method or a way to search my dictionary would be very much appreciated.

RED=(255,0,0)
BLACK=(0,0,0)
WHITE =(255,255,255)
GREEN = (0,255,0)
player_health = 10
enemy_health = 10
collision_counter = 0
attack_counter = 0
attack = False

import pygame

#Creating screen and sprites
all_sprites_list = pygame.sprite.Group()
all_enemies_list = pygame.sprite.Group()

pygame.init()

screen = pygame.display.set_mode((1,1))

class Sprites(pygame.sprite.Sprite):

    def __init__(self,x,y,img):
        super().__init__()

        #Colour and position
        #Set the background colour and set the image to be transparent
        self.image = pygame.Surface([x, y])
        self.image.fill(WHITE)
    self.image.set_colorkey(WHITE)

    #Or using an image
    self.image = pygame.image.load(img).convert_alpha()

    #Fetch a rectangle that is the same size
    self.rect = self.image.get_rect()

    self.mask = pygame.mask.from_surface(self.image)


def AI(self,charX):

    #If the player is on the left
    if self.rect.x < charX:
        self.rect.x +=  1

    #On right
    if self.rect.x > charX:
        self.rect.x -= 1

def update(self,charX):
    self.AI(charX)


img = "BadCrab.png"
#Creating the first AI sprite with width,height,colour and x,y position
AI1 = Sprites(30,20,img)
AI1.rect.x = 0
AI1.rect.y = 150
#Adding to to the necessary groups
all_enemies_list.add(AI1)

#Creating the character sprite with width,height,colour and x,y position
char = Sprites(30,20,"Crab.fw.png")
char.rect.x = 150
char.rect.y = 150
#Adding to to the necessary group
all_sprites_list.add(char)

screen = pygame.display.set_mode((800,400))
clock = pygame.time.Clock()
counter = 0

while True:
    pygame.event.pump()
    screen.fill(BLACK)
    clock.tick(60)
    pygame.event.pump()
    keys = []

    #Getting the keys which are pressed down
    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN:
            keys.append(event)

    #Converting the array to a string so it can be searched
    keys=str(keys)

    #Using the keys numbern value to determine if it has been pressed
    #Left arrow = 276
    if "276" in keys:
        char.rect.x -= 40

    #Right arrow = 275
    elif "275" in keys:
        char.rect.x += 40

    counter += 1
    #Space = 32
    if "32" in keys:
        counter = 0
        #Removing orignal sprite and then changing it to the attack sprite
        all_sprites_list.remove(char)
        char = Sprites(30,20,"Crab_attack.fw.png")
        char.rect.y = 150
        char.rect.x = charX
        all_sprites_list.add(char)
        attack = True
    #Allwoing the attack sprite to be drawn before replaced by original sprite
    if counter == 12:
        all_sprites_list.remove(char)
        char = Sprites(30,20,"Crab.fw.png")
        char.rect.y = 150
        char.rect.x = charX
        all_sprites_list.add(char)
        counter = 0
        attack = False

    charX = char.rect.x
    all_enemies_list.update(char.rect.x)
    all_enemies_list.draw(screen)
    all_sprites_list.draw(screen)
    pygame.display.flip()

    #Checking for collisions
    collisions = pygame.sprite.groupcollide(all_sprites_list, all_enemies_list,False,False)
    print(str(collisions))

Solution

  • keys = []
    
    #Getting the keys which are pressed down
    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN:
            keys.append(event)
    
    #Converting the array to a string so it can be searched
    keys=str(keys)
    
    #Using the keys numbern value to determine if it has been pressed
    #Left arrow = 276
    if "276" in keys:
        char.rect.x -= 40
    
    #Right arrow = 275
    elif "275" in keys:
        char.rect.x += 40
    
    counter += 1
    #Space = 32
    if "32" in keys:
        counter = 0
        #Removing orignal sprite and then changing it to the attack sprite
        all_sprites_list.remove(char)
        char = Sprites(30,20,"Crab_attack.fw.png")
        char.rect.y = 150
        char.rect.x = charX
        all_sprites_list.add(char)
        attack = True
    

    I don't know why you're trying to do it the most complicated way, just use

    #Getting the keys which are pressed down
    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                char.rect.x -= 40
            if event.key == pygame.K_RIGHT:
                char.rect.x += 40
            if event.key == pygame.K_SPACE:
                counter = 0
                #Removing orignal sprite and then changing it to the attack sprite
                all_sprites_list.remove(char)
                char = Sprites(30,20,"Crab_attack.fw.png")
                char.rect.y = 150
                char.rect.x = charX
                all_sprites_list.add(char)
                attack = True
    
    counter += 1
    

    however the dictionary returned by the method does not appear to follow the same rules

    The dictionary returned by groupcollide works the same way as every other dictionay. I don't know what rules you're talking about. If you have trouble figuring out what exactly is returns, just take a look at the documentation:

    Every Sprite inside group1 is added to the return dictionary. The value for each item is the list of Sprites in group2 that intersect.

    and the return value is a simple dict, so you could do e.g.:

    for sprite, others in collisions.items():
       for other in others:
          print(str(sprite) + ' collides with ' + str(other))