lordmauve / pgzero

A zero-boilerplate games programming framework for Python 3, based on Pygame.
https://pygame-zero.readthedocs.io/
GNU Lesser General Public License v3.0
530 stars 190 forks source link

Schedule functions with arguments #246

Open jasongrout opened 3 years ago

jasongrout commented 3 years ago

First, I'm teaching kids how to program with pygame zero - it's awesome! They really picked it up quickly, and the quick wins they get encourage them to dive deeper into programming. Thanks very much for your work on this.

One thing that came up after doing the tutorial is wanting multiple aliens, which quickly led to storing the aliens in a list and iterating through them, and abstracting out how the alien pictures change to work across a list of aliens. This led to us wanting to schedule a function with arguments (in our case, we want to schedule setting an alien's picture back to normal, but we want to pass in the alien and a string to construct the alien's picture filename as arguments to the callback). We ended up with something like:

clock.schedule_unique(partial(set_alien_normal, alien, 'blue'))

where set_alien_normal is essentially:

def set_alien_normal(alien, color):
    alien.image = 'alien_' + color

Of course, this doesn't work, as is explained just under https://pygame-zero.readthedocs.io/en/stable/builtins.html#Clock.unschedule (and is clear from looking at the code, since scheduling is using weak refs). Scheduling with weakrefs prevents easy abstraction of a scheduled function call with arguments. Which brings us to:

Would you be amenable to adding a *args, **kwargs to the scheduling functions to supply arguments to call the callbacks with? Unscheduling could also take these arguments and only unschedule a function if it matched both the function and the args/kwargs. This would allow us to schedule a call without creating a temporary function that goes out of scope, i.e., we could do something like clock.schedule_unique(set_alien_normal, 1, alien, color).