Search code examples
pythonspritepyglet

Moving many sprites the same distance at the same time with pyglet


I know how to draw them at the same time using batches but I was wondering if there was a way to move a whole batch at once. Do I need to move all sprites individually?

So far I have been doing it like this:

tile2 =pyglet.sprite.Sprite(tile1,0,0,batch = terrain)
tile3 =pyglet.sprite.Sprite(tile1,10,0,batch = terrain)
tile4 =pyglet.sprite.Sprite(tile1,20,0,batch = terrain)
tile5 =pyglet.sprite.Sprite(tile1,30,0,batch = terrain)
tile6 =pyglet.sprite.Sprite(tile1,40,0,batch = terrain)
tile7 =pyglet.sprite.Sprite(tile1,50,0,batch = terrain)

tile2.x += 10
tile3.x += 10
tile4.x += 10

etc...

But there will be more sprites than this in the finished product (50+ I hope) and moving them all will be pretty tiresome.

Any help will be appreciated :)


Solution

  • You would want to store your objects in an appropriate data structure, such as a list:

    tiles = []
    tiles.append(pyglet.sprite.Sprite(tile1,0,0,batch = terrain))
    tiles.append(pyglet.sprite.Sprite(tile1,10,0,batch = terrain))
    ...
    

    A list contains a series of items, which can be accessed individually (tiles[0], tiles[1]) or looped through (for tile in tiles:). The list can change length and allows you to make the number of tiles you have changeable, without having to hard code lots of variables.

    However, this is a very verbose way of doing it, and the much better method is to use a loop:

    tiles = []
    for x in range(0, 51, 10):
        tiles.append(pyglet.sprite.Sprite(tile1, x, 0, batch = terrain))
    

    Here we loop over a range of numbers (from 0 to 51 in steps of 10 - note the use of 51, not 50 - python stops on the last value, not after it, so range(0, 50, 10) would yield 0 to 40 in steps of 10.), creating a tile and adding it to our list. Note that if you are using a pre-3.x version of Python, xrange() will be faster than range() as it is returns a generator, not a list. In Python 3.x, this is the behaviour of range.

    But Python can be even more elegant, using a list comprehension to create the list easily:

    tiles = [pyglet.sprite.Sprite(tile1, x, 0, batch = terrain) for x in range(0, 51, 10)] 
    

    Then to move them, we loop through the list, moving each one as we go:

    for tile in tiles:
        tile.x += 10
    

    In general, doing x1, x2, x3, ... is a sign that something is wrong - using an appropriate data structure will help you do less typing, and make your code more flexible. A good way to think about this is if you are copying and pasting something, then could probably re-factor that code into a reusable function or use a loop to perform the same thing on multiple items.