Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I have a sprite group created with pygame.sprite.Group() (and add sprites to it with the add method)

How would I retrieve the nth sprite in this group?

Code like this does not work:

mygroup = pygame.sprite.Group(mysprite01)
print mygroup[n].rect

It returns the error: group object does not support indexing.

For the moment I'm using the following function:

def getSpriteByPosition(position,group):
    for index,spr in enumerate(group):
        if (index == position):
            return spr
    return False

Although working, it just doesn't seem right...

Is there a cleaner way to do this?

EDIT: I mention a "position" and index but it's not important actually, returning any single sprite from the group is enough

share|improve this question
    
The answer to your other question seems like it answers this one as well. –  Tetrad May 2 '11 at 6:19
    
Actually not anymore. I'm keeping the sprite group as I don't need to shuffle it anymore. –  user3956 May 2 '11 at 9:32
1  
If you continue down this path of madness, at least update getSpriteByPosition to return None instead of False - False is equal to integer 0, which is a valid index. –  user744 May 2 '11 at 13:47

3 Answers 3

up vote 1 down vote accepted

What do you need the index for? Since sprites are hashed, the index is not stable; since you can't use it to easily find the sprite again, I don't know why you'd want to store it; and since you can't easily get from a sprite to an index I don't know how you got it in the first place.

If you need a reference to a sprite, reference the sprite itself, not its index.

share|improve this answer
    
I'm not trying to index sprites inside a group. I just want to get the first or second sprite in the group, whatever it is and whenever it has been added to the group. (thanks for return None) –  user3956 May 2 '11 at 13:58
    
Groups are not ordered so "the first sprite in the group" is a useless designator. What you probably actually want is "the player sprite" or "the enemy ship" or something. Store those when you make them, don't rely on being able to pull them back out of a group by the weakest handle imaginable. –  user744 May 2 '11 at 14:03
    
hmm, it looks very well ordered to me. As a test I tried removing a sprite from its group (and printing the sprites names in the group before and after removing it) the sprites order is kept and I can get any sprite inside the group by "position" with the code above... but I understand a sprite group is here to keep all the "similar" sprites together for easier update and not to index them. –  user3956 May 2 '11 at 14:18
    
Removing a sprite is guaranteed, at the very least, to shift all the objects past it down by one. Removing many elements may make the dictionary shrink, rehashing. Adding elements is guaranteed to make the dictionary grow, rehashing. Indices into the key view/list - which are what you get when you make indices into the sprite group - are not reliable. –  user744 May 2 '11 at 14:25
    
Understood and agreed. Note that what I want to do is take any single sprite from the group. The code above does that and is not an aberration. If there's a better solution to achieve this, I will accept it. (in the question I mention a "position" or index but it's not important actually, getting any single sprite from the group is enough) I'm wondering if your answer to the linked question (shuffle group) would not work for this purpose as well... –  user3956 May 2 '11 at 15:53

You can save a reference to the sprite elsewhere. Game class might have a variable pointing to the player instance, as well as sprite list.

You can have a reference to one sprite, in multiple sprite groups. Ex: Starcraft unit selections, could use a unit_list of all unit sprites. And a sprite group for selected_units.

player = Unit()
units = pygame.sprite.Group()
units.add( Unit(), Unit() , player, Unit() )

# use player, by ref.
print player.rect
for unit in unit_group:
    print unit.rect
share|improve this answer

If you really, truly, absolutely want access a sprite by index, you can do this:

third_sprite = mygroup.sprites()[2]

So your function would be:

def getSpriteByPosition(position,group):
    return group.sprites()[position]

Which throws IndexError if the index is not found. If you want to return None in that case, simply enclose the line with a try block:

def getSpriteByPosition(position,group):
   try:
       return group.sprites()[position]
   except IndexError:
       pass

But... quoting user744, "What do you need the index for?". Afterall, the index of a sprite changes when you add or remove sprites to that group. And even if you don't, Pygame does not guarantee the list order will be the same in each call. So what do you mean by the "3rd sprite in the group"? It may be the 3rd now, but the 5th or 2nd later. How useful is that for you?

Simply put:

Being the nth sprite in a group means absolutely nothing !

(as a side note, position is a poor name for an index, as it might get confused as the sprite (x,y) position on screen)

Another sidenote: try to think OO. Instead of a function that receives a group as argument, subclass Group and create a custom method, so you can use it like mygroup.getSpriteByPosition(3)

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.