Brandon Liu
Brandon Liu

Reputation: 35

Pygame: Click event is affecting every sprite to the left of them

I have an array with all the sprites inside of them, and in the loop, if the sprite is clicked then the sprite is killed.

If I click the sprites from left to right, everything is fine. They are cleared one by one independent of each other. But, if I click the sprite most right of the screen, it kills everything to the left of it.

Full code because I've no idea where the important region might be.

import pygame
from pygame.locals import *
import random
pygame.init()
level = 1
cooldown = 1000
class test(pygame.sprite.Sprite):
    def __init__(self, w):
        super().__init__()
        self.image = pygame.Surface([600,600])
        self.rect = self.image.get_rect()
        self.image = pygame.image.load("index.png")
        self.image = pygame.transform.scale(self.image, (w,w))
        self.last = pygame.time.get_ticks()
screen = pygame.display.set_mode([600,600])
clock = pygame.time.Clock()
background = pygame.Surface(screen.get_size())
background.fill([0,0,0])
rX = random.randint(0, 500)
rX2 = random.randint(0, 500) 
screen.blit(background, (0,0))
sp = []
all_sprites_list = pygame.sprite.Group()
a_1 = test(random.randint(40,60))
a_1.rect.x = rX
a_1.rect.y = -400
sp.append(a_1)
all_sprites_list.add(a_1)

#The steps for a_1 is repeated to make variables a_2, a_3, a_4...  

Running = True
while Running:
    now = pygame.time.get_ticks()
    for x in sp:
        x.rect.y+=level
    m_pos = pygame.mouse.get_pos()
    for event in pygame.event.get():
        if event.type == QUIT:
            Running = False
        if event.type == MOUSEBUTTONDOWN:
            for s in sp:
                if s.rect.collidepoint(m_pos):
                    s.kill()
    pygame.display.flip()
    all_sprites_list.clear(screen, background)
    all_sprites_list.draw(screen)
    all_sprites_list.update()
    clock.tick(60)

Upvotes: 1

Views: 290

Answers (1)

furas
furas

Reputation: 142641

Problem is because in class you create Surface with size (600, 600) and you assign this size to self.rect. After that you load image but you forgot to assign its size to self.rect so program always check mouse click with size (600, 600) and when you click most right item then all rect (600, 600) are in area of click.

But you don't have to create Surface if you load image.


My version with many changes.

I removed list sp because I can use all_sprites_list

When it sends MOUSEBUTTONDOWN event then mouse position is in event.pos so I don't need pygame.mouse.get_pos()

import pygame
import random

# --- classes --- (UpperCaseNames)

class Test(pygame.sprite.Sprite):

    def __init__(self, w):
        super().__init__()

        self.image = pygame.image.load("index.png")
        self.image = pygame.transform.scale(self.image, (w, w))
        self.rect = self.image.get_rect()

        self.last = pygame.time.get_ticks()

# --- main ----

level = 1
cooldown = 1000

# - init -

pygame.init()
screen = pygame.display.set_mode((600, 600))

# - items -

background = pygame.Surface(screen.get_size())
background.fill((0, 0, 0))

screen.blit(background, (0,0))

all_sprites_list = pygame.sprite.Group()

for x in range(10):
    item = Test(random.randint(40, 60))
    item.rect.x = 40 * random.randint(0, 10)
    item.rect.y = 0
    all_sprites_list.add(item)

# - mainloop -

clock = pygame.time.Clock()

running = True

while running:

    now = pygame.time.get_ticks()

    for item in all_sprites_list:
        item.rect.y += level

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.MOUSEBUTTONDOWN:
            for item in all_sprites_list:
                if item.rect.collidepoint(event.pos):
                    item.kill()

    pygame.display.flip()
    all_sprites_list.clear(screen, background)
    all_sprites_list.draw(screen)
    all_sprites_list.update()
    clock.tick(30)

pygame.quit()    

Upvotes: 1

Related Questions