pythonpygamereplit

I'm starting to make a little puzzle game with Pygame on Replit and i'm struggling with multiple objects


So I have the player and two boxes that I am trying to independently move around, if a box is behind another box, then when one is pushed, they will both be pushed, and I know why, I just don't know how to fix it. Any help would be appreciated.

I have the two boxes in a sprite group with the movement lines of code having self since they are in a class, and I assumed that this would move them one at a time but they are both moved, and I am unsure how to have them move independently while not repeating too much code.

Here is the code


import pygame, sys
from pygame.locals import QUIT
from pygame import *

# Predefined some colors
BLUE  = (0, 0, 255)
RED   = (255, 0, 0)
GREEN = (0, 255, 0)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)

pygame.init()
DISPLAYSURF = pygame.display.set_mode((750, 500))
DISPLAYSURF.fill(WHITE)
SCREEN_WIDTH=750
SCREEN_HEIGHT=500
pygame.display.set_caption('Puzzle Game')
FPS=20
FramesPerSecond=pygame.time.Clock()

class Player(pygame.sprite.Sprite):
  def __init__(self):
    super().__init__()
    self.image = pygame.image.load("Player1.png")
    self.rect = self.image.get_rect()
    self.rect.center=(75,425)
    
  def update(self):
    pressed_keys=pygame.key.get_pressed()
    if self.rect.top > 0:
      if pressed_keys[K_UP]:
          self.rect.move_ip(0, -5)
    if self.rect.bottom < SCREEN_HEIGHT:
      if pressed_keys[K_DOWN]:
          self.rect.move_ip(0,5)
        
    if self.rect.left > 0:
      if pressed_keys[K_LEFT]:
          self.rect.move_ip(-5, 0)
    if self.rect.right < SCREEN_WIDTH:        
        if pressed_keys[K_RIGHT]:
            self.rect.move_ip(5, 0)
          
  def draw(self, surface):
    surface.blit(self.image, self.rect)

class Box(pygame.sprite.Sprite):
  def __init__(self, x, y):
    super().__init__()
    self.image = pygame.image.load("Box.jpg")
    self.rect = self.image.get_rect()
    self.rect.center = (x, y)

  def update(self):
    pressed_keys=pygame.key.get_pressed()
    if pygame.sprite.spritecollideany(P1, boxes):
      if P1.rect.x < self.rect.x and pressed_keys[K_RIGHT]:
        self.rect.move_ip(5,0)
      if P1.rect.x > self.rect.x and pressed_keys[K_LEFT]:
        self.rect.move_ip(-5,0)
      if P1.rect.y > self.rect.y and pressed_keys[K_UP]:
        self.rect.move_ip(0,-5)
      if P1.rect.y < self.rect.y and pressed_keys[K_DOWN]:
        self.rect.move_ip(0,5)
    
  def draw(self, surface):
    surface.blit(self.image, self.rect)
    
P1 = Player()
B1 = Box(100, 100)
B2 = Box(200, 200)
boxes = pygame.sprite.Group()
boxes.add(B1, B2)
while True:     
    for event in pygame.event.get():              
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        
            
          
          
    P1.update()
    B1.update()
    B2.update()
    
    
    DISPLAYSURF.fill(WHITE)
    P1.draw(DISPLAYSURF)
    B1.draw(DISPLAYSURF)
    B2.draw(DISPLAYSURF)
        
    pygame.display.update()
    FramesPerSecond.tick(FPS)


Solution

  • pygame.sprite.spritecollideany detects if the player collides with any box in the group of boxes. This condition applies to all box objects in the group as soon as the player collides with a single box object and thus all objects are moved. You have to use pygame.sprite.collide_rect() to detect if the player collides with a single box object itself:

    if pygame.sprite.spritecollideany(P1, boxes):

    if pygame.sprite.collide_rect(self, P1):