4
\$\begingroup\$

I made the following code. It's a simple animation of 'raindrops' falling and splattering once they reach the ground. The images I use can be found here: https://i.sstatic.net/oKOVA.jpg

import pygame, sys
from pygame import locals 
import random
import itertools
def listenToQuit():
 for event in pygame.event.get():
 if event.type == locals.QUIT:
 pygame.quit()
 sys.exit()
def makeNewDrop(display, drops):
 # there isa 15% chance we'll make a new drop, each frame
 x = display.get_width() * random.random() # a random xpostion
 return RainDrop(x, display, drops) 
class RainDrop(pygame.sprite.Sprite):
 img = pygame.image.load('assests/rain_drop.png')
 def __init__(self, x, display, group):
 # call the super constructor, and pass in the 
 # group you've created and it is automatically added to the group every 
 # time you create an instance of this class
 pygame.sprite.Sprite.__init__(self, group) 
 self.y = 0
 self.x = x
 self.fall_step = 5
 self.display = display
 self.die = False
 self. animation = iter([
 pygame.image.load('assests/splatter_1.png'),
 pygame.image.load('assests/splatter_2.png'),
 pygame.image.load('assests/splatter_3.png'),
 pygame.image.load('assests/splatter_4.png')
 ])
 def update(self):
 self.checkIfShouldDie()
 self.fall()
 if self.die:
 try:
 self.img = next(self.animation)
 except StopIteration:
 self.kill()
 self.display.blit(self.img, (self.x,self.y))
 def fall(self):
 self.y = self.y + self.fall_step
 def checkIfShouldDie(self):
 if self.img.get_rect().bottom + self.y >= self.display.get_height():
 self.die = True
 self.y = self.display.get_height() - self.img.get_rect().bottom - 5
if __name__ == '__main__':
 pygame.init()
 drops = pygame.sprite.Group()
 cooldown = 0
 fps = 30
 clock = pygame.time.Clock()
 main_display = pygame.display.set_mode((400,400),0,32)
 pygame.display.set_caption("rain!") 
 while True:
 main_display.fill((255,255,255))
 if random.random() >= 0.85 and cooldown == 0:
 # a 15% change we'll make a new drop, each frame
 # assuming we didn't make a drop in the last few frames
 drop = makeNewDrop(main_display, drops) # automatically added to the drops group
 cooldown = cooldown + 5
 drops.update()
 # reduce cooldown
 cooldown = 0 if cooldown <= 0 else cooldown - 1
 listenToQuit()
 pygame.display.update()
 clock.tick(30)

How can this code be improved? Specifically the part where I iterator over animations and catch the StopIteration error seems very hacky to me.

asked Apr 5, 2020 at 11:01
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

PEP8

The official Python style guide will suggest that:

  • there be two newlines between functions at the global scope, and only one newline between functions in the class scope (i.e. check_if_should_die)
  • functions be named in lower_snake_case, i.e. listen_to_quit

Hard exit

Currently, you have a forever-loop that only exits on sys.exit. Instead, simply return a boolean from listenToQuit (which can be called should_quit), and if the return value is true, break out of the loop.

Abbreviated imports

pygame.sprite.Sprite can just be Sprite if you from pygame.sprite import Sprite.

Typo

assests -> assets

Generator

 self. animation = iter([
 pygame.image.load('assests/splatter_1.png'),
 pygame.image.load('assests/splatter_2.png'),
 pygame.image.load('assests/splatter_3.png'),
 pygame.image.load('assests/splatter_4.png')
 ])

can be

self.animation = iter(
 pygame.image.load(f'assets/splatter_{i}.png')
 for i in range(1, 5)
)

Generally I don't think your iter/StopIteration approach is that bad. That said, you can rework it by changing your outer while True into a for drop in drops, where drops is an iterable through four instances of a drop object tied to a specific asset.

answered Apr 5, 2020 at 15:53
\$\endgroup\$
1
  • \$\begingroup\$ Quick question just to be sure I understand: The last suggestion of for drop in drops would work for an animation functionality, but this would not work if I would want this animation to only be the backdrop, and later add more functionality such as listening to keyboard input etc? Thanks for the detailed answer! It's very useful \$\endgroup\$ Commented Apr 6, 2020 at 11:02

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.