I just made my first pygame program, ChickenDodger, and I would like to know how I could make my code better. I think I did pretty good for my first time, except the way I added the 2nd egg. I do not like the way I added it. Any advice?
(I made a lot of comments for my younger brother, so he understands it easier, I think some comments are unnecessary)
import pygame
import time
import random
#Initialize pygame
pygame.init()
#Initialize the screen
screenwidth = 960
screenheigth = 640
screen = pygame.display.set_mode((screenwidth,screenheigth))
#Get the color codes
white = (255,255,255)
black = (0,0,0)
#Get the chicken image and scale it
chickenwidth = 50
chickenheigth = 100
chicken = pygame.image.load("chicken.jpg")
chicken = pygame.transform.scale(chicken, (chickenwidth, chickenheigth))
#Get the egg image and scale it
eggwidth = 50
eggheigth = 50
egg = pygame.image.load("egg.jpg")
egg = pygame.transform.scale(egg, (eggwidth, eggheigth))
#Get the second egg image and scale it
egg2width = 50
egg2heigth = 50
egg2 = pygame.image.load("egg.jpg")
egg2 = pygame.transform.scale(egg2, (egg2width, egg2heigth))
#Change the title
pygame.display.set_caption("Chicken Dodger")
#Set the clock
clock = pygame.time.Clock()
#Define the chicken's starting location
def chickenplace(chickenx, chickeny):
screen.blit(chicken, (chickenx, chickeny))
#Define the egg's starting location
def eggplace(eggx, eggy):
screen.blit(egg, (eggx, eggy))
#Define the second egg's starting location
def egg2place(egg2x, egg2y):
screen.blit(egg2, (egg2x, egg2y))
#Define the gameloop
def gameloop():
#Wait 2 seconds before starting the function
time.sleep(2)
dead = False
#Set the counter for the dodged eggs
eggcounter = 0
#Place the chicken and define its xchange
chickenx = (screenwidth * 0.5)
chickeny = (screenheigth * 0.8)
chickenxchange = 0
#Place the egg and define its speed
eggx = random.randint(0,910)
eggy = -200
eggspeed = 7
#Place the second egg and define its speed
egg2x = random.randint(0,910)
egg2y = -200
egg2speed = 14
while not dead:
for event in pygame.event.get():
#Make a quit option
if event.type == pygame.QUIT:
dead = True
#Move chicken
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
chickenxchange = -10
elif event.key == pygame.K_RIGHT:
chickenxchange = 10
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
chickenxchange = 0
#Change the chickenx and the eggy
chickenx += chickenxchange
eggy += eggspeed
#Fill the screen
screen.fill(white)
#Place the chicken and the egg
chickenplace(chickenx, chickeny)
eggplace(eggx, eggy)
egg2place(egg2x, egg2y)
#Set the boundaries for the chicken
if chickenx > screenwidth - chickenwidth:
chickenx = screenwidth - chickenwidth
chickenplace(chickenx, chickeny)
if chickenx < 0:
chickenx = 0
chickenplace(chickenx, chickeny)
#Make the egg come back
if eggy > screenheigth:
eggy = -200
eggx = random.randint(0,910)
#Make the second egg come back
if egg2y > screenheigth:
egg2y = -200
egg2x = random.randint(0,910)
#Add 1 point for every egg avoided, if the egg hits the chicken, reset the counter to 0
if eggy == chickeny + 2:
if eggx > chickenx + 50 or eggx < chickenx - 50:
eggcounter += 1
else:
eggcounter = 0
time.sleep(2)
gameloop()
#Do not add a point if the second egg gets avoided, if the second egg hits the chicken, reset the counter to 0
if egg2y == chickeny + 2:
if egg2x > chickenx + 50 or egg2x < chickenx - 50:
eggcounter = eggcounter
else:
eggcounter = 0
time.sleep(2)
gameloop()
#Display the counter
countertext = pygame.font.SysFont(None, 20)
counterlabel = countertext.render("Counter:" + str(eggcounter), True, black)
screen.blit(counterlabel, (20, 20))
#Double the egg's speed when you have dodged 5 eggs
if eggcounter > 5:
eggspeed = 14
#Make a second egg fall when you have dodged 15 eggs
if eggcounter > 15:
egg2y += egg2speed
egg2place(egg2x, egg2y)
#Display a "You won!" when you dodged the first egg 30 times
if eggcounter == 30:
wintext = pygame.font.SysFont(None, 60)
winlabel = wintext.render("You won!", True, black)
screen.blit(winlabel, (200, 200))
time.sleep(1)
dead = True
pygame.display.update()
clock.tick(60)
gameloop()
pygame.quit()
quit()
1 Answer 1
First of all, the name "Chicken Dodger" made me laugh, that's a good one!
Quitting
Quitting is handled like this:
while not dead: for event in pygame.event.get(): #Make a quit option if event.type == pygame.QUIT: dead = True # ... more code # ... a lot more code
After you set dead
to True
, still a lot more code will get executed in the outer while not dead
loop.
I'm not sure if that's intentional.
If it isn't, then it looks like that you can simply return
from the function.
Use more elif
In these conditions:
#Make a quit option if event.type == pygame.QUIT: dead = True #Move chicken if event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: chickenxchange = -10 elif event.key == pygame.K_RIGHT: chickenxchange = 10 if event.type == pygame.KEYUP: if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT: chickenxchange = 0
event.type
can only have one of these values.
For example if event.type == pygame.QUIT
, then there's no need to evaluate the other conditions.
This is what elif
is designed for:
if event.type == pygame.QUIT:
# ...
elif event.type == pygame.KEYDOWN:
# ...
elif event.type == pygame.KEYUP:
# ...
The same goes here:
if chickenx > screenwidth - chickenwidth: chickenx = screenwidth - chickenwidth chickenplace(chickenx, chickeny) if chickenx < 0: chickenx = 0 chickenplace(chickenx, chickeny)
The second if
should be an elif
, because if the first condition was true, the second cannot be true, so there's no need to evaluate it.
Review the entire program, and look for conditions that are mutually exclusive as in these examples.
Variable span
It's good to move references to a variable close together as much as possible. Consider this:
dead = False # ... a lot of code while not dead:
You initialized dead
early on, wrote a lot of code before actually using that variable in the while
loop.
By the time I read the while
loop,
I don't remember where dead
was initialized.
I also have to quickly scan the code between the initialization and the loop, to see that its value was never changed before the loop begins.
If you move the initialization line down to right before the loop start,
the code becomes a little bit easier to read.