Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Colliderect firing even when 2 items aren't touching

I am making a system where the items fall from the sky and you collect them however the collision is being registered even when the character doesn’t touch the items. The collision happens when the character collides with the item on the x axis but it can collide at any point on the y axis.

Here is an example from the image below:

Example Image

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I have tried printing the positions of both the character and item to see if for some reason the position wasn’t up to date with where it was on screen but for both the character and item the positions were fine.

Here is my code:

import pygame
import sys
import os
import time
from pygame.locals import *

os.environ["SDL_VIDEO_CENTERED"] = "1"
pygame.init()

SCREENWIDTH = 580
SCREENHEIGHT = 375
SCREENSIZE = [SCREENWIDTH, SCREENHEIGHT]
SCREEN = pygame.display.set_mode(SCREENSIZE)

CLOCK = pygame.time.Clock()
FPS = 60


jumping = False
backgroundImage = pygame.image.load('Images/backgroundImage.jpg')
backgroundScaled = pygame.transform.scale(backgroundImage,(580,375))
pygame.display.set_caption("Christmas Game")

santaWidth, santaHeight = 93,64
santaImage = pygame.image.load("Images/santa.png")
santaScaled = pygame.transform.scale(santaImage,(santaWidth,santaHeight))
santa = pygame.Rect(100,100,santaWidth,santaHeight)
                                     
font = pygame.font.SysFont("myriadProFont",50)
timeText = font.render("", 1,(255,255,255))
startTime = time.time()

itemsGroup = pygame.sprite.Group()

#IDs 0 = coin, 
class Item(pygame.sprite.Sprite):
  def __init__(self,x,y,ID,imageName):
    super().__init__()
    self.ID = ID
    self.image = pygame.image.load(imageName)
    self.scaledImage = pygame.transform.scale(self.image,(50,50))
    self.x = x
    self.y = y
    self.rect = self.image.get_rect()
    self.rect.topleft = (self.x,self.y)
  def render(self, screen):
    screen.blit(self.scaledImage,(self.x,self.y))
  def collect(self, santa):
    hit = self.rect.colliderect(santa)
    if hit:
      if self.ID == 0:
        print("Coin")
      self.kill()
  def itemGravity(self):
    if self.y < 370:
      self.y += 1
      self.rect = self.image.get_rect()
      self.rect.topleft = (self.x,self.y)
    else:
      self.kill()
      print("killed")
  
    
coin = Item(200,0,0,"Images/coin.png")
itemsGroup.add(coin)
coin2 = Item(500,0,0,"Images/coin.png")
itemsGroup.add(coin2)


class Floor(pygame.sprite.Sprite):
  def __init__(self, width, height, x, y, name):
    super().__init__()
    self.image = pygame.image.load(name)
    self.image = pygame.transform.scale(self.image, (width, height))
    self.rect = self.image.get_rect()
    self.size = width, height
    self.pos = (x, y)
    self.rect.topleft = self.pos
    self.isTouching = False
  def render(self, display):
    display.blit(self.image, self.pos)
  def collision(self,santa):
    global jumping
    hit = self.rect.colliderect(santa)
    if hit and self.isTouching == False:
      self.isTouching = True
    elif not hit:
      self.isTouching = False
floorGroup = pygame.sprite.Group()
floor = Floor(291,70,-50,305,"Images/floor.webp")
floorGroup.add(floor)
floor2 = Floor(291,70,330,305,"Images/floor.webp")
floorGroup.add(floor2)


def adjustTime():
  global timeText
  global jumping
  newTime = time.time()
  difference = newTime - startTime
  if difference > 1:
    timeText = font.render(time.strftime('%M:%S', time.gmtime(difference)), 1,(255,255,255))



def playerMovement(keyPressed,santa):
  global jumping
  if (keyPressed[pygame.K_UP] or keyPressed[pygame.K_w] or keyPressed[pygame.K_SPACE]) and santa.y > 0 and jumping == False:
    jumping = True
    santa.y = santa.y - 50
  elif(keyPressed[pygame.K_LEFT] or keyPressed[pygame.K_a]) and santa.x > -20:
    santa.x = santa.x - 5
  elif(keyPressed[pygame.K_RIGHT] or keyPressed[pygame.K_d]) and santa.x < 525:
   santa.x = santa.x + 5
  

def updateScreen(santa):
  SCREEN.blit(backgroundScaled, (0, 0))
  for floor in floorGroup:
    floor.render(SCREEN)
  for item in itemsGroup:
    item.render(SCREEN)
  SCREEN.blit(santaScaled,(santa.x,santa.y))
  SCREEN.blit(timeText,(250,0))
  pygame.display.update()


def gravity(santa): 
  global jumping
  if santa.y < 320:
    santa.y += 3
  elif santa.y == 320:
    jumping = False
  else:
    santa.y = 320


while True:
  timeDelta = CLOCK.tick(FPS)/1000.0 
  adjustTime()

  for event in pygame.event.get():
    if event.type == pygame.QUIT:
      pygame.quit()
      sys.exit()
  user_input = pygame.key.get_pressed()  
  playerMovement(user_input,santa)
  gravity(santa)
  for item in itemsGroup:
    item.collect(santa)
    item.itemGravity()
  for floor in floorGroup:
    floor.collision(santa)
  updateScreen(santa)
  CLOCK.tick(FPS)
`

>Solution :

You have to get the bounding rectangle of the scaled image instead of the original image:

self.rect = self.image.get_rect()

self.rect = self.scaledImage.get_rect()

Note that the pygame.sprite.Sprite object does not need a render or draw method if you use pygame.sprite.Group. See How can I add objects to a "pygame.sprite.Group()"? and What does pygame.sprite.Group() do

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading