Source Code Makeover: Square Shooter, Part 2

i.age += delta_t

# check if all the bubbles have been destroyed

if len(self.bubbles) == 0:

if self.afterfinish_timer > 0:

# the afterfinish timer is still counting down

self.afterfinish_timer -= delta_t;

else:

# the afterfinish timer is done, add a life and set up the next level

self.level += 1

self.lives += 1

self.init_level(self.level)

return

elif not self.ship.has_freeze():

# update all the bubbles

for i in self.bubbles:

i.update(delta_t)

# update the bullet

if self.bullet != None:

bullet_wrapped = self.bullet.update(delta_t)

if bullet_wrapped:

# delete the bullet if it has hit the edge of the map

self.bullet = None

# update the ship

if self.ship == None:

if self.afterdeath_timer > 0:

# player is dead and afterdeath timer is still counting down

self.afterdeath_timer -= delta_t

elif self.lives > 0:

# create a new Ship for the next level

self.ship = Ship()

self.ship.add_shield() # add shields at the start of a life

else:

# player has run out of lives, level 0 will make the start screen display

self.level = 0 # Game over

return

self.ship.update(delta_t)

Checking this in with log message, “Added comments to GameWorld.update().”

Refactoring the GameWorld class

(These changes can be seen in the github history.)

Now that it has some documentation, let’s see how we can improve the GameWorld class. One thing that is odd is that the powerups and explosions are removed if they are too old, and then they are aged. This means that old explosions and powerups won’t be removed until the next call to update(). Let’s swap the order of that and age them first before doing the age check:

# expand the explosions and delete them once they get too big

for i in self.explosions:

i.radius += delta_t

if len(self.explosions) > 0:

if self.explosions[0].radius > 0.5:

self.explosions.pop(0)

# "age" the powerups on the map, and delete them if they get too old

for i in self.powerups:

i.age += delta_t

if len(self.powerups) > 0:

if self.powerups[0].age > 9:

self.powerups.pop(0)

Also, there seems to be a slight bug with this code. It only checks if the first explosion or power up in the explosions and powerups lists is too old. (You can tell by the self.explosions[0] and self.powerups[0] part.) We should add a loop to these if statements so that every explosion and powerup is checked. (The reason we don’t see this bug in the game is because update() is called so frequently that the powerups and explosions are quickly removed in future update() calls.) Notice that we iterate from the end of the self.explosions and self.powerups list to the beginning, because we are modifying the items in the list as we iterate.

# expand the explosions and delete them once they get too big

for i in self.explosions:

i.radius += delta_t

for i in range(len(self.explosions - 1, -1, -1)):

if self.explosions[i].radius > 0.5:

self.explosions.pop(i)

# "age" the powerups on the map, and delete them if they get too old

for i in self.powerups:

i.age += delta_t

for i in range(len(self.powerups - 1, -1, -1)):

if self.powerups[i].age > 9:

self.powerups.pop(i)

Let’s also replace the 0.5 and 9 magic numbers with global constants MAX_EXPLOSION_SIZE and MAX_POWERUP_AGE:

MAX_EXPLOSION_SIZE = 0.5 # set between 0.0 and 1.0

MAX_POWERUP_AGE = 9 # in seconds

...

# expand the explosions and delete them once they get too big

for i in self.explosions:

i.radius += delta_t

for i in range(len(self.explosions) - 1, -1, -1):

if self.explosions[i].radius > MAX_EXPLOSION_SIZE:

self.explosions.pop(i)

# "age" the powerups on the map, and delete them if they get too old

for i in self.powerups:

i.age += delta_t

for i in range(len(self.powerups) - 1, -1, -1):

if self.powerups[i].age > MAX_POWERUP_AGE:

self.powerups.pop(i)

It is more Pythonic to just use not len(self.bubbles) instead of len(self.bubbles) == 0 for conditions, since the integer value 0 evaluates to False anyway:

# check if all the bubbles have been destroyed

if not len(self.bubbles):

And the variable name i is usually used to mean “index”. Since the for loop for updating the bubbles is iterating over Bubble objects instead of an integer index, let’s rename i to bubble:

# update all the bubbles

for bubble in self.bubbles:

bubble.update(delta_t)

Page 2 of 8 | Previous page | Next page