10
\$\begingroup\$

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()
\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.