7 Replies - 1356 Views - Last Post: 12 February 2013 - 09:09 AM Rate Topic: -----

#1 slidon  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 29
  • Joined: 09-February 13

pygame collision detection problem

Posted 09 February 2013 - 04:02 AM

Hi, I am creating a simple game. For a bit now I have been trying to add collision detection. I am trying to use the colliderect() function to detect the collision but I get the error
AttributeError: 'rectangle' object has no attribute 'colliderect'
Script terminated


when using these lines to detect the collision

if player.colliderect(white_rect):
    screen.fill(BLACK)


both white_rect and player have rect methods.

if you want it here is my full (though a bit simplified) code
import pygame, sys
pygame.init()
def main():
    class rectangle(pygame.sprite.Sprite):
        def __init__(self, image_file, location):
            self.image = pygame.image.load(image_file)
            self.rect = self.image.get_rect()
            self.location = location
            self.currentX = location[0]
            self.currentY = location[1]
            
            
    class player(pygame.sprite.Sprite):
        def __init__(self, location, speed, image_file):
            self.image = pygame.image.load(image_file)
            self.speed = speed
            self.start_location = location
            self.currentX = location[0]
            self.currentY = location[1]
            self.keydownA = False
            self.keydownD = False
            self.keydownSPACE = False
            self.jumping = False
            self.jumpY = location[1]
            self.jump_direction = 1 # 1 = going up, 0 = going down
            self.jumpspeed = 20
            self.rect = self.image.get_rect()
        def detectMoving(self):
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    sys.exit()
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_a:
                        self.keydownA = True
                    if event.key == pygame.K_d:
                        self.keydownD = True
                    if event.key == pygame.K_SPACE:
                        self.keydownSPACE = True
                    
                        
                            
                
                if event.type == pygame.KEYUP:
                    if event.key == pygame.K_a:
                        self.keydownA = False
                    if event.key == pygame.K_d:
                        self.keydownD = False
                    if event.key == pygame.K_SPACE:
                        self.keydownSPACE = False
            
        def move(self):
            if self.keydownA == True:
                self.currentX -= self.speed
            if self.keydownD == True:
                self.currentX += self.speed
        def jump(self):
                 if self.jumping == False:
                    self.jumpY = self.currentY
                 if self.keydownSPACE == True:
                    self.jumping = True
                 if self.jumping == True:
                        self.currentY -= self.jumpspeed
                        self.jumpspeed -= 1
                 if self.currentY == self.jumpY:
                    self.jumping = False
                    self.jumpspeed = 20
    running = True
    WHITE = (255, 255, 255)
    BLACK = (0, 0, 0)
    white_rect_sprite = ("white_rect.png")
    player_sprite = ("player_sprite.png")
    white_rect = rectangle(white_rect_sprite, (400, 480 - 130))
    player = player([250, 480 - 145], 3, player_sprite)
    screen = pygame.display.set_mode((640, 480), 0, 32)
    pygame.display.set_caption("My Platformer")
    
    
    
    while running:
        player.detectMoving()
        player.move()
        player.jump()
        screen.fill(BLACK)
        screen.blit(white_rect.image, (white_rect.currentX, white_rect.currentY))
        screen.blit(player.image, (player.currentX, player.currentY))
#---------collision detection-----
        if player.colliderect(white_rect):
            screen.fill(BLACK)
        pygame.display.flip()
main()


thanks in advance!

Is This A Good Question/Topic? 0
  • +

Replies To: pygame collision detection problem

#2 Nallo  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 163
  • View blog
  • Posts: 255
  • Joined: 19-July 09

Re: pygame collision detection problem

Posted 09 February 2013 - 06:44 AM

Your player and rectangle classes are subclasses of pygame.sprite.Sprite. For sprites the method is called collide_rect, not colliderect as for rects. Take a look at the pygame documentation
Was This Post Helpful? 1
  • +
  • -

#3 slidon  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 29
  • Joined: 09-February 13

Re: pygame collision detection problem

Posted 09 February 2013 - 07:21 AM

Hi, thanks for pointing that out and the pygame docs link. I tried out this
if pygame.sprite.collide_rect(player, white_rect):
    screen.fill(BLACK)

and it filled the screen as soon as I ran it instead of when the player collided. I tried out this
if pygame.sprite.collide_rect(player, white_rect) == True:

but it did not change. If I did this:
pygame.sprite.collide_rect(player, white_rect) == False

on the end it plays the game like normal and does not seem to detect.

Thanks for the reply
Was This Post Helpful? 0
  • +
  • -

#4 Mekire  Icon User is offline

  • D.I.C Head

Reputation: 116
  • View blog
  • Posts: 212
  • Joined: 11-January 13

Re: pygame collision detection problem

Posted 09 February 2013 - 10:53 AM

Well there are a lot of issues with your code that I am not going to try to get into right now, but basically it boils down to this; you don't seem to understand what rects are for or how to use them.

Hopefully this will help you get on the right track. I changed all your coordinates to make use of the rectangle locations as they should. Also created a clock to limit your frame rate. The collision is detecting now... all it does is turn the whole screen blue when they collide, but I will leave the details to you. (note I replaced your graphics with simple filled blocks because I don't have your graphics.)
import pygame, sys
pygame.init()

myclock = pygame.time.Clock()
def main():
    class rectangle(pygame.sprite.Sprite):
        def __init__(self, image_file, location):
            self.image = pygame.Surface((30,30))
            self.image.fill((255,255,255))
            self.rect = self.image.get_rect()
            self.rect.topleft = location

    class player(pygame.sprite.Sprite):
        def __init__(self, location, speed, image_file):
            self.image = pygame.Surface((40,40))
            self.image.fill((255,0,0))
            self.speed = speed
            self.rect = self.image.get_rect()
            self.rect.topleft = location
            self.keydownA = False
            self.keydownD = False
            self.keydownSPACE = False
            self.jumping = False
            self.jumpY = location[1]
            self.jump_direction = 1 # 1 = going up, 0 = going down
            self.jumpspeed = 20
            
        def detectMoving(self):
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit();sys.exit()
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_a:
                        self.keydownA = True
                    if event.key == pygame.K_d:
                        self.keydownD = True
                    if event.key == pygame.K_SPACE:
                        self.keydownSPACE = True

                if event.type == pygame.KEYUP:
                    if event.key == pygame.K_a:
                        self.keydownA = False
                    if event.key == pygame.K_d:
                        self.keydownD = False
                    if event.key == pygame.K_SPACE:
                        self.keydownSPACE = False

        def move(self):
            if self.keydownA == True:
                self.rect.x -= self.speed
            if self.keydownD == True:
                self.rect.x += self.speed
        def jump(self):
                 if self.jumping == False:
                    self.jumpY = self.rect.y
                 if self.keydownSPACE == True:
                    self.jumping = True
                 if self.jumping == True:
                        self.rect.y -= self.jumpspeed
                        self.jumpspeed -= 1
                 if self.rect.y == self.jumpY:
                    self.jumping = False
                    self.jumpspeed = 20
    running = True
    WHITE = (255, 255, 255)
    BLACK = (0, 0, 0)
    white_rect_sprite = ("white_rect.png")
    player_sprite = ("player_sprite.png")
    white_rect = rectangle(white_rect_sprite, (400, 480 - 130))
    player = player([250, 480 - 145], 3, player_sprite)
    screen = pygame.display.set_mode((640, 480), 0, 32)
    pygame.display.set_caption("My Platformer")

    while running:
        player.detectMoving()
        player.move()
        player.jump()
        screen.fill(BLACK)
        screen.blit(white_rect.image, (white_rect.rect.topleft))
        screen.blit(player.image, (player.rect.topleft))
#---------collision detection-----
        if player.rect.colliderect(white_rect.rect):
            screen.fill((0,0,255))
        pygame.display.flip()
        myclock.tick(64)
main()


Good luck to you,
-Mek
Was This Post Helpful? 1
  • +
  • -

#5 slidon  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 29
  • Joined: 09-February 13

Re: pygame collision detection problem

Posted 09 February 2013 - 11:31 AM

Hi, thanks for your changes! youre right I am very new to pygame and python so I kind of jumped into it. I messed around with the images and found if I go back to the old way
pygame.image.load()

then I get my old problem.
What should be put in there if you want to have a sprite instead of a shape?

oh and could you give a very brief summary of what you changed?
it would help me quite a bit
Was This Post Helpful? 0
  • +
  • -

#6 slidon  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 29
  • Joined: 09-February 13

Re: pygame collision detection problem

Posted 09 February 2013 - 11:45 AM

View Postslidon, on 09 February 2013 - 11:31 AM, said:

Hi, thanks for your changes! youre right I am very new to pygame and python so I kind of jumped into it. I messed around with the images and found if I go back to the old way
pygame.image.load()

and change the collision detection to
player.sprite.collide_rect()

then I get the error
'player' object has no attribute 'sprite'

I suppose this means the player is not a sprite but it looks like it is.
What should I do if I want to have a sprite instead of a shape?

oh and could you give a very brief summary of what you changed?
it would help me quite a bit


sorry just getting the hang of the dream in code forums
Was This Post Helpful? 0
  • +
  • -

#7 Mekire  Icon User is offline

  • D.I.C Head

Reputation: 116
  • View blog
  • Posts: 212
  • Joined: 11-January 13

Re: pygame collision detection problem

Posted 11 February 2013 - 09:39 AM

I assure you that using an image or not doesn't change how that code works.
I have looked through your code a little more and made a few basic changes.
Below I also use images rather than filled shapes.
(Images are grabbed from the internet so this won't work if your computer is not online)

For my changes, I have taken your class definitions outside your function. They do not belong within the function. Also, as I said all sprite locations are now handled by their rects. This is what rects are for. Using rectangle collision functions isn't going to work if your rectangle is not located at the same place your sprite is supposed to be.

import os,sys
import pygame

#The following lines are just getting a couple images we can agree upon from the net.
#Don't worry about how this works.
try:
    from urllib import urlopen
    from cStringIO import StringIO as inout
except ImportError:
    from urllib.request import urlopen
    from io import BytesIO as inout
face_url  = urlopen("http://i1192.photobucket.com/albums/aa340/Mekire/smallface.png")
block_url = urlopen("http://i1192.photobucket.com/albums/aa340/Mekire/block.png")
#The following our the temporary image file names
FACE  = inout(face_url.read())
BLOCK = inout(block_url.read())

#Global constants here
WHITE = (255,255,255)
BLACK = (0,0,0)
GREY  = (50,50,50)
RED  = (255,50,50)

class Rectangle(pygame.sprite.Sprite):
    def __init__(self,image_file,location):
        self.image = pygame.image.load(image_file).convert()
        self.rect = self.image.get_rect()
        self.rect.topleft = location

class Player(pygame.sprite.Sprite):
    def __init__(self, location, speed, image_file):
        self.image = pygame.image.load(image_file).convert_alpha()
        self.speed = speed
        self.rect = self.image.get_rect()
        self.rect.topleft = location
        self.keydownA = False
        self.keydownD = False
        self.keydownSPACE = False
        self.jumping = False
        self.jumpY = location[1]
        self.jump_direction = 1 # 1 = going up, 0 = going down
        self.jumpspeed = 20

    def detectMoving(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit();sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_a:
                    self.keydownA = True
                if event.key == pygame.K_d:
                    self.keydownD = True
                if event.key == pygame.K_SPACE:
                    self.keydownSPACE = True

            elif event.type == pygame.KEYUP:
                if event.key == pygame.K_a:
                    self.keydownA = False
                if event.key == pygame.K_d:
                    self.keydownD = False
                if event.key == pygame.K_SPACE:
                    self.keydownSPACE = False

    def move(self):
        if self.keydownA == True:
            self.rect.x -= self.speed
        if self.keydownD == True:
            self.rect.x += self.speed
    def jump(self):
             if self.jumping == False:
                self.jumpY = self.rect.y
             if self.keydownSPACE == True:
                self.jumping = True
             if self.jumping == True:
                    self.rect.y -= self.jumpspeed
                    self.jumpspeed -= 1
             if self.rect.y == self.jumpY:
                self.jumping = False
                self.jumpspeed = 20

class Control:
    def __init__(self):
        self.white_rect = Rectangle(BLOCK,(400,350))
        self.player = Player([250,350], 3, FACE)
    def main(self):
        self.player.detectMoving()
        self.player.move()
        self.player.jump()
        SCREEN.fill(GREY)
        SCREEN.blit(self.white_rect.image, self.white_rect.rect)
        SCREEN.blit(self.player.image, self.player.rect)
        #Collission detection
        if self.player.rect.colliderect(self.white_rect.rect):
            SCREEN.fill(RED)
        pygame.display.flip()

#############################################################
if __name__ == "__main__":
    os.environ['SDL_VIDEO_CENTERED'] = '1' #center screen
    pygame.init()
    pygame.display.set_caption("My Platformer")
    SCREEN = pygame.display.set_mode((640, 480))
    
    Runit = Control()
    Myclock = pygame.time.Clock()
    while 1:
        Runit.main()
        Myclock.tick(64)





In the future, rather than updating each sprite in the main function, you will need to write update functions for the sprites. Also, as you are inheriting from pygame.sprite.Sprite, you might as well make use of that. As is this code would run regardless of inheriting from Sprite or not.

Hope this helps. Let me know if you have further questions or would like clarification on anything,
-Mek
Was This Post Helpful? 1
  • +
  • -

#8 slidon  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 29
  • Joined: 09-February 13

Re: pygame collision detection problem

Posted 12 February 2013 - 09:09 AM

Thanks!!!!!!!! solved. all the formating helped a lot too!
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1