kBeezee
kBeezee

Reputation: 48

Using Pygame, draw a copy of an image in a different location

This is kind of a follow up to this question:

Note: This in python, using the pygame library.

I'm wanting to get some clarification on this statement which is a comment from the above question:

Another important thing, don't use the same Sprite() nor the same Rectangle in different locations. If you want to draw another copy of the same image in a new location make a copy of the rectangle, then create a new Sprite() object.

I have a group of game assets and I want to pick one at random to add my sprite group. I am currently doing this as such:

class TestSprite(pygame.sprite.Sprite):
    def __init__(self, strFolder):
        super(TestSprite, self).__init__()
        self.image = load_image(strFolder + 'x.png'))
        #....

def GetRandomAsset():
    rnd = random.randrange(1, 4)
    if rnd == 1:
        return TestSprite('assets/A/')
    elif rnd == 2:
        return TestSprite('assets/B/')
    elif rnd == 3:
        return TestSprite('assets/C/')
    else:
        return TestSprite('assets/D/')
    #....

my_group = pygame.sprite.Group()
my_group.add(GetRandomAsset())
#.....
#Control FPS
#Check Events
#Update State
#Clear Screen
#Draw Current State
#Update Display

Everything works as expected; Every time I run the above code, a new sprite is displayed to the screen. My problem is every time i add a sprite, im having to load it from the disk, even tho im using the same 4 images over and over again.

I imagine it would be smarter for me to store all my assets in a global list called PRELOADEDASSETS. Then whenever I need one just do: my_group.add(PRELOADEDASSETS[x]) But when I try to do that, i can only have one copy of each of my assets.

How can I preload all my assets, and then grab the stored data when needed?

Thanks!

Upvotes: 3

Views: 3071

Answers (1)

sloth
sloth

Reputation: 101142

Another important thing, don't use the same Sprite() nor the same Rectangle in different locations. If you want to draw another copy of the same image in a new location make a copy of the rectangle, then create a new Sprite() object.

This is a valid advice in this context. It's of course no problem to blit a surface multiple times to different locations (using different Rects for example), but if you use a Group to handle/simplify your drawing, you need one object for each location you want to draw your image.


To answer your actual question:

You don't need to cache the Sprite instances. Just cache the Surface instances.

This way, you can have different Sprite objects that draw the same image to different locations.

A simple cache implementation could look like this:

images = {'a': load_image('assets/A/x.png'),
          'b': load_image('assets/B/x.png'),
          'c': load_image('assets/C/x.png'),
          'd': load_image('assets/D/x.png')}
...
class TestSprite(pygame.sprite.Sprite):
    def __init__(self, image_key):
        super(TestSprite, self).__init__()
        self.image = images[image_key]
...
def GetRandomAsset():
    image_key = random.choice(images.keys())
    return TestSprite(image_key)

This will load all images upfront (may or maynot what you want); adding laziness is easy, but you probably don't want possible lags (what is best depends how many images you actually load and when).

You could even just go through all folders in your game's directory and detect and load all images automatically, but such sprees are out of scope of this answer.

Upvotes: 2

Related Questions