#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2008
    Posts
    47
    Rep Power
    7

    Spritecollision using class attribute?


    Hey, a newbie with a question about the use of sprites in pygame here:

    I am using a class to create little tux sprites in a game I'm doing for fun and practice. For each instance of tux, the init funtction takes an argument (a string) to create a unique greeting, looking something like this:

    Code:
    class Tux(pygame.sprite.Sprite,greeting):
        def __init__(self,x,y):
            pygame.sprite.Sprite.__init__(self)
    
            self.image = pygame.image.load('tux1.png')
    
            self.rect = self.image.get_rect()
            self.rect.topleft = (x,y)
           
            self.greeting = greeting
    Within the main function, but before the game loop starts, I create all the tuxes like so:
    Code:
    tuxlist = []
    a = Tux(200,200)
    tuxlist.append(a)
    
    tuxes = pygame.sprite.RenderPlain(tuxlist)
    Finally, within the Player class, I have an update function that among other things checks for collisions with the tuxes like this:

    Code:
    collidetux = pygame.sprite.spritecollide(self,tux,True)
    if collideconversation:
            self.rect.topleft = (old_x,old_y)
            self.change_x+=-self.change_x
            self.change_y+=-self.change_y

    ... so essentially all it does is vanish when bumped into. I have a more complicated version where it calls another module with a separate loop for a short conversation as well, upon collision. Now, here's what I've been wondering about:
    Is it somehow possible to have the program call the class attribute self.greeting of the particular tux sprite you collide with? So if the player bumps into the sprite of a tux I created with greeting = 'Hi there!', can I have the program print that out on the screen? I know how to have stuff printed out on the pygame-screen, so my question boils down entirely to how to actually reach a particular class attribute when sprite colliding. Any thoughts or hints much appreciated!
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2012
    Posts
    194
    Rep Power
    2
    If you use
    Code:
    pygame.sprite.spritecollideany()
    the return value will be the first sprite it detects a collision with (or None if no collisions are detected). Use this to access the attribute of your tux class.

    python Code:
    import os
    import sys
    import pygame as pg
     
     
    DIRECT_DICT = {pg.K_LEFT  : (-1, 0),
                   pg.K_RIGHT : ( 1, 0),
                   pg.K_UP    : ( 0,-1),
                   pg.K_DOWN  : ( 0, 1)}
     
     
    class Player(pg.sprite.Sprite):
        def __init__(self,rect,speed):
            pg.sprite.Sprite.__init__(self)
            self.rect = pg.Rect(rect)
            self.speed = speed
            self.image = self.make_image()
     
        def make_image(self):
            image = pg.Surface((self.rect.size)).convert()
            image.fill((0,0,0))
            interior = pg.Rect((0,0),self.rect.size)
            image.fill((255,0,0),interior.inflate(-12,-12))
            return image
     
        def update(self,keys,limit_rect=None):
            for key in DIRECT_DICT:
                if keys[key]:
                    self.rect.x += DIRECT_DICT[key][0]*self.speed
                    self.rect.y += DIRECT_DICT[key][1]*self.speed
            if limit_rect:
                self.rect.clamp_ip(limit_rect)
     
        def draw(self,surface):
            surface.blit(self.image,self.rect)
     
     
    class Block(pg.sprite.Sprite):
        def __init__(self,rect,message):
            pg.sprite.Sprite.__init__(self)
            self.rect = pg.Rect(rect)
            self.image = self.make_image()
            self.message = message
     
        def make_image(self):
            image = pg.Surface((self.rect.size)).convert()
            image.fill((0,0,255))
            interior = pg.Rect((0,0),self.rect.size)
            image.fill((0,255,0),interior.inflate(-12,-12))
            return image
     
     
    class Control(object):
        def __init__(self):
            os.environ['SDL_VIDEO_CENTERED'] = '1'
            pg.init()
            pg.display.set_caption("Move me with the Arrow Keys.")
            self.screen = pg.display.set_mode((500,500))
            self.screen_rect = self.screen.get_rect()
            self.clock = pg.time.Clock()
            self.fps = 60.0
            self.font = pg.font.SysFont('timesnewroman', 60)
            self.done = False
            self.keys = pg.key.get_pressed()
            self.player = Player((0,0,25,25),5)
            self.player.rect.center = self.screen_rect.center
            self.blocks = self.make_blocks()
            self.message = None
            self.timer = 0.0
     
        def make_blocks(self):
            blocks = pg.sprite.Group()
            blocks.add(Block((50,50,50,50),"Hey."))
            blocks.add(Block((400,50,50,50),"Hello."))
            blocks.add(Block((50,400,50,50),"Hi!!"))
            blocks.add(Block((400,400,50,50),"What's up?"))
            return blocks
     
        def collision(self):
            collide = pg.sprite.spritecollideany(self.player,self.blocks)
            if collide:
                self.message = collide.message
                self.timer = pg.time.get_ticks()
                collide.kill()
     
        def display_message(self):
            if self.message:
                msg = self.font.render(self.message,True,(0,0,255))
                msg_rect = msg.get_rect(center=(self.screen_rect.centerx,50))
                self.screen.blit(msg,msg_rect)
                if pg.time.get_ticks() - self.timer > 500:
                    self.message = None
     
        def event_loop(self):
            for event in pg.event.get():
                self.keys = pg.key.get_pressed()
                if event.type == pg.QUIT or self.keys[pg.K_ESCAPE]:
                    self.done = True
     
        def update(self):
            self.player.update(self.keys,self.screen_rect)
            self.collision()
            self.screen.fill(-1)
            self.blocks.draw(self.screen)
            self.player.draw(self.screen)
            self.display_message()
     
        def main_loop(self):
            while not self.done:
                self.event_loop()
                self.update()
                pg.display.update()
                self.clock.tick(self.fps)
     
     
    if __name__ == "__main__":
        run_it = Control()
        run_it.main_loop()
        pg.quit()
        sys.exit()

    -Mek
    Last edited by Mekire; August 17th, 2013 at 10:44 AM.
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2008
    Posts
    47
    Rep Power
    7
    Wow, damn, you really went above and beyond there - thanks a bunch!

IMN logo majestic logo threadwatch logo seochat tools logo