5
\$\begingroup\$

I am making a snake game and I'm almost done but I want to make my code more organized so people can understand so how to do it.

# -*- coding: utf-8 -*-
import pygame
import random
import time
import thread
##########################Functions#####################################################################################
def startBackground():
 gameDisplay.blit(introBackground, [0, 0])
def snake(block_size, snakeBody):
 if direction == "right":
 head = pygame.transform.rotate(img, 270)
 if direction == "left":
 head = pygame.transform.rotate(img, 90)
 if direction == "up":
 head = img
 if direction == "down":
 head = pygame.transform.rotate(img, 180)
 gameDisplay.blit(head, (snakeBody[-1][0], snakeBody[-1][1]))
 for XnY in snakeBody[:-1]:
 pygame.draw.rect(gameDisplay, green, [XnY[0], XnY[1], block_size, block_size])
def background():
 for x in range(display_width / Background.get_width() + 1):
 for y in range(display_height / Background.get_height() + 1):
 gameDisplay.blit(Background, (x * 100, y * 100))
def Apple(random_x_coordinates, random_y_coordinates):
 gameDisplay.blit(apple, (random_x_coordinates, random_y_coordinates))
def gameLoop():
 music("Sleep Away.mp3", -1)
 direction = "right"
 global FPS
 FPS = 30
 score = 0
 snakeBody = []
 snakeLength = 5
 random_Apple_x_coordinates = round(random.randrange(0, display_width - block_size) / 10.0) * 10.0
 random_Apple_y_coordinates = round(random.randrange(0, display_height - block_size) / 10.0) * 10.0
 lead_x = display_width / 2
 lead_x_change = 10
 lead_y = display_height / 2
 lead_y_change = 0
 gameExit = True
 gameOver = False
 speed = 10
 flag = 1
 flag2 = 0
 fail_music_play = True
 global direction
 while gameExit:
 while gameOver:
 gameDisplay.fill(white)
 if fail_music_play is True:
 music("fail.mp3")
 fail_music_play = False
 message_to_screen("Game Over !!!", red, -50)
 message_to_screen("your score is " + str(score), red, 0)
 message_to_screen("Press 'R' To Play again or 'Q' to Quit", red, 50)
 pygame.display.update()
 for event in pygame.event.get():
 if event.type == pygame.KEYDOWN:
 if event.key == pygame.K_q:
 gameExit = False
 gameOver = False
 if event.key == pygame.K_r:
 gameLoop()
 if event.type == pygame.QUIT:
 pygame.quit()
 quit()
 ####################################################################################################################################################################################
 # Screen Boundries
 if lead_x < 0 or lead_x >= display_width or lead_y >= display_height or lead_y < 0:
 gameOver = True
 ####################################################################################################################################################################################
 # Snake Movement
 lead_x += lead_x_change
 lead_y += lead_y_change
 ####################################################################################################################################################################################
 # Apple location and Creation
 Apple(random_Apple_x_coordinates, random_Apple_y_coordinates)
 ####################################################################################################################################################################################
 # Collision Detection
 for eachSegment in snakeBody[:-1]:
 if eachSegment == snakeHead:
 gameOver = True
 # Snake Body & Length
 # snakeBody = []
 # snakeLength = 1
 snakeHead = [lead_x, lead_y]
 snakeBody.append(snakeHead)
 if len(snakeBody) > snakeLength:
 del snakeBody[0]
 snake(block_size, snakeBody)
 clock.tick(FPS)
 ####################################################################################################################################################################################
 if ((random_Apple_x_coordinates <= lead_x < random_Apple_x_coordinates + apple_thickness) or (
 random_Apple_x_coordinates < lead_x + block_size <= random_Apple_x_coordinates + apple_thickness)) and (
 (random_Apple_y_coordinates <= lead_y < random_Apple_y_coordinates + apple_thickness) or (
 random_Apple_y_coordinates < lead_y + block_size <= random_Apple_y_coordinates + apple_thickness)):
 random_Apple_x_coordinates = round(random.randrange(0, display_width - block_size)) # / 10.0) * 10.0
 random_Apple_y_coordinates = round(random.randrange(0, display_height - block_size)) # / 10.0) * 10.0
 gameDisplay.fill(purple, rect=[random_Apple_x_coordinates, random_Apple_y_coordinates, apple_thickness,
 apple_thickness])
 snakeLength += 1
 score += 1
 if score % 11 == 0:
 speed += 2
 ####################################################################################################################################################################################
 pygame.display.update()
 background()
 for event in pygame.event.get():
 if event.type == pygame.QUIT:
 gameExit = False
 gameOver = False
 if event.type == pygame.KEYDOWN:
 global flag, flag2, direction
 if event.key == pygame.K_LEFT:
 if not flag == 1:
 direction = "left"
 lead_x_change = -speed
 lead_y_change = 0
 flag2 = 0
 flag = 1
 elif event.key == pygame.K_RIGHT:
 if not flag == 1:
 direction = "right"
 lead_x_change = speed
 lead_y_change = 0
 flag2 = 0
 flag = 1
 elif event.key == pygame.K_UP:
 if not flag2 == 1:
 direction = "up"
 lead_y_change = -speed
 lead_x_change = 0
 flag2 = 1
 flag = 0
 elif event.key == pygame.K_DOWN:
 if not flag2 == 1:
 direction = "down"
 lead_y_change = speed
 lead_x_change = 0
 flag2 = 1
 flag = 0
 pygame.quit()
 quit()
def music(song_name, repeat=0):
 pygame.init()
 pygame.mixer.init()
 pygame.mixer.music.load(song_name)
 pygame.mixer.music.play(repeat)
#################### Images #####################################################################################################################################################
img = pygame.image.load('SnakeHead.png')
Background = pygame.image.load("grass.png")
snakeIcon = pygame.image.load('snake.png')
apple = pygame.image.load('apple.png')
introBackground = pygame.image.load("startBackground.jpg")
#################### COLORS #######################################################################################################################################################
white = (255, 255, 255)
black = (0, 0, 0)
bright_red = (255, 0, 0)
red = (155, 0, 0)
brown = (33, 20, 18)
purple = (150, 50, 150)
bright_purple = (255, 50, 255)
green = (20, 150, 20)
bright_green = (20, 255, 20)
blue = (30, 0, 150)
bright_blue = (0, 0, 255)
#####################################################################################################################################################################################
display_width = 800
display_height = 600
FPS = 30
score = 0
block_size = 20
apple_thickness = 20
direction = "right"
speed = 10
pause = False
#####################################################################################################################################################################################
rect_width = display_width / 4.0
rect_height = display_height / 12.0
####################################################################################################################################################################################
rect_x_corner = (display_width / 2) - rect_width / 2 # x-ccoordinate of head of the head of the rectangle
rect1_y_corner = (display_height * 1 / 5.0) - (rect_height / 2) # y-ccoordinate of head of the head of rectangle 1
rect2_y_corner = (display_height * 2 / 5.0) - (rect_height / 2) # y-ccoordinate of head of the head of rectangle 2
rect3_y_corner = (display_height * 3 / 5.0) - (rect_height / 2) # y-ccoordinate of head of the head of rectangle 3
rect4_y_corner = (display_height * 4 / 5.0) - (rect_height / 2) # y-ccoordinate of head of the head of rectangle 4
#####################################################################################################################################################################################
rect1_y_displace = -(display_height / 2) + rect1_y_corner + (rect_height / 2)
rect2_y_displace = -(display_height / 2) + rect2_y_corner + (rect_height / 2)
rect3_y_displace = -(display_height / 2) + rect3_y_corner + (rect_height / 2)
rect4_y_displace = -(display_height / 2) + rect4_y_corner + (rect_height / 2)
#####################################################################################################################################################################################
inactive_color1 = purple
inactive_color2 = green
inactive_color3 = red
inactive_color4 = blue
#####################################################################################################################################################################################
active_color1 = bright_purple
active_color2 = bright_green
active_color3 = bright_red
active_color4 = bright_blue
#####################################################################################################################################################################################
rect1_x_displace = - (display_width / 2) + rect_x_corner + (rect_width / 2)
rect2_x_displace = - (display_width / 2) + rect_x_corner + (rect_width / 2)
rect3_x_displace = - (display_width / 2) + rect_x_corner + (rect_width / 2)
rect4_x_displace = - (display_width / 2) + rect_x_corner + (rect_width / 2)
def Credits():
 game_credits = True
 gameDisplay.fill(white)
 while game_credits is True:
 for event in pygame.event.get():
 clock.tick(100)
 # def button(rect_x_corner, rect_y_corner, rect_width, rect_height, inactive_color, active_color, text_color, text="Random_Text", action=None):
 message_to_screen("The Game is made by :", green, -150, "freesasbold.ttf", 50)
 message_to_screen("Ahmed Tarek", red, -40)
 message_to_screen("omar Wael", black, 40)
 button((rect_x_corner + 200), (rect3_y_corner + 100), rect_width, rect_height, inactive_color3,
 active_color3, black, "Back", "Back")
 if event.type == pygame.QUIT:
 pygame.quit()
 quit()
 pygame.display.update()
def text_objects(text, color, text_style="freesansbold.ttf", text_size=40):
 font = pygame.font.Font(text_style, text_size) # change None to Font Style and change 25 to change font size
 textSurface = font.render(text, True, color)
 return textSurface, textSurface.get_rect()
def message_to_screen(msg, color, y_displace, text_style="freesansbold.ttf", text_size=30):
 textSurface, textRectangle = text_objects(msg, color)
 textRectangle.center = (display_width / 2), (display_height / 2) + y_displace
 gameDisplay.blit(textSurface, textRectangle)
def message_to_rect(msg, color, rect_x_center, rect_y_center, text_style=None, text_size=25):
 textSurface, textRectangle = text_objects(msg, color, text_style, text_size)
 textRectangle.center = rect_x_center, rect_y_center
 gameDisplay.blit(textSurface, textRectangle)
####################################################################################################################################################################################
def button(rect_x_corner, rect_y_corner, rect_width, rect_height, inactive_color, active_color, text_color,
 text="Random_Text", action=None):
 mouse = pygame.mouse.get_pos()
 click = pygame.mouse.get_pressed()
 rect_x_center = rect_x_corner + (rect_width / 2)
 rect_y_center = rect_y_corner + (rect_height / 2)
 gameDisplay.fill(inactive_color, rect=[rect_x_corner, rect_y_corner, rect_width, rect_height])
 if rect_x_corner + rect_width > mouse[0] > rect_x_corner and rect_y_corner + rect_height > mouse[1] > rect_y_corner:
 gameDisplay.fill(active_color, rect=[rect_x_corner, rect_y_corner, rect_width, rect_height])
 message_to_rect(text, text_color, rect_x_center, rect_y_center)
 pygame.display.update()
 if click[0] == 1 and action is not None:
 if action == "Play":
 gameLoop()
 if action == "Credits":
 Credits()
 if action == "Quit":
 pygame.quit()
 quit()
 if action == "Back":
 startBackground()
 pygame.display.update()
 game_intro()
 else:
 gameDisplay.fill(inactive_color, rect=[rect_x_corner, rect_y_corner, rect_width, rect_height])
 message_to_rect(text, text_color, rect_x_center, rect_y_center)
####################################################################################################################################################################################
def game_intro():
 game = True
 while game:
 # User Can Only Quit the game OR Use the button Function to Escape the menu, using the buttons!
 for event in pygame.event.get():
 button(rect_x_corner, rect1_y_corner, rect_width, rect_height, inactive_color1, active_color1, black,
 "Play", "Play")
 button(rect_x_corner, rect2_y_corner, rect_width, rect_height, inactive_color2, active_color2, black,
 "Options", "Options")
 button(rect_x_corner, rect3_y_corner, rect_width, rect_height, inactive_color3, active_color3, black,
 "Credits", "Credits")
 button(rect_x_corner, rect4_y_corner, rect_width, rect_height, inactive_color4, active_color4, black,
 "Quit", "Quit")
 if event.type == pygame.QUIT:
 game = False
 pygame.quit()
 quit()
 pygame.display.update()
####################################################################################################################################################################################
pygame.init()
####################################################################################################################################################################################
pygame.display.set_caption("Snake 🐍")
gameDisplay = pygame.display.set_mode((display_width, display_height))
clock = pygame.time.Clock()
pygame.display.set_icon(snakeIcon)
####################################################################################################################################################################################
startBackground()
pygame.display.update()
game = True
clock.tick(30)
game_intro()

I would appreciate it if you could help me because this is my project and I have to give it to the instructor tomorrow.

200_success
145k22 gold badges190 silver badges478 bronze badges
asked Sep 2, 2016 at 17:11
\$\endgroup\$
1
  • \$\begingroup\$ any one can help please \$\endgroup\$ Commented Sep 2, 2016 at 18:34

1 Answer 1

1
\$\begingroup\$

Your code overall is pretty structured, but here are some improvement suggestions. The acronym for them is called PBS:

1. 'P'ut DocStrings in all of your functions

I cannot stress enough how important it is to document large projects, such as yours. Six to seven months from now, you'll be looking at your code thinking: 'what the heck is this?'.

To give an exmaple of what I mean, take your function startBackground().It creates the intro screen to your game, So this is the DocString I would add:

def startBackground():
 '''
 Blits the intro screen of the game.
 '''
 gameDisplay.blit(introBackground, [0, 0])

While the DocString above may seem trivial, it will certainly matter for some of your large functions, such as gameLoop() or snake().

When creating your DocStrings, just remember that your trying to summarize exactly what your function does. you could even add a description of the arguments your function takes.

2. 'B'e consistent

I've noticed a few places where you switch between naming conventions.

Take here for example

def Apple(random_x_coordinates, random_y_coordinates):
 gameDisplay.blit(apple, (random_x_coordinates, random_y_coordinates))

All your other function start with lower case, so change this function to

def apple(random_x_coordinates, random_y_coordinates):
 gameDisplay.blit(apple, (random_x_coordinates, random_y_coordinates))

Also, there are certain common naming conventions for python. Mr.Lott, already has a nice answer on Stack Overflow that cites documentation from the PEP 8 styling guide for python. The documentation that he cites is concerning naming conventions. It reads:

Function names should be lowercase, with words separated by underscores as necessary to improve readability. mixedCase is allowed only in contexts where that's already the prevailing style. [For Variables] Use the function naming rules: lowercase with words separated by underscores as necessary to improve readability.

The most important thing to remember about naming convention for any programming language is pick one style, and stick to it. Nothing makes code more un-readable than mixed naming conventions.

3. 'S'tructure you code

Your code structure is a bit sloppy. There are lines down at the bottem that should be near the top. In fact I would move all of this:

#################### Images #####################################################################################################################################################
img = pygame.image.load('SnakeHead.png')
Background = pygame.image.load("grass.png")
snakeIcon = pygame.image.load('snake.png')
apple = pygame.image.load('apple.png')
introBackground = pygame.image.load("startBackground.jpg")
#################### COLORS #######################################################################################################################################################
white = (255, 255, 255)
black = (0, 0, 0)
bright_red = (255, 0, 0)
red = (155, 0, 0)
brown = (33, 20, 18)
purple = (150, 50, 150)
bright_purple = (255, 50, 255)
green = (20, 150, 20)
bright_green = (20, 255, 20)
blue = (30, 0, 150)
bright_blue = (0, 0, 255)
#####################################################################################################################################################################################
display_width = 800
display_height = 600
FPS = 30
score = 0
block_size = 20
apple_thickness = 20
direction = "right"
speed = 10
pause = False
#####################################################################################################################################################################################
rect_width = display_width / 4.0
rect_height = display_height / 12.0
####################################################################################################################################################################################
rect_x_corner = (display_width / 2) - rect_width / 2 # x-ccoordinate of head of the head of the rectangle
rect1_y_corner = (display_height * 1 / 5.0) - (rect_height / 2) # y-ccoordinate of head of the head of rectangle 1
rect2_y_corner = (display_height * 2 / 5.0) - (rect_height / 2) # y-ccoordinate of head of the head of rectangle 2
rect3_y_corner = (display_height * 3 / 5.0) - (rect_height / 2) # y-ccoordinate of head of the head of rectangle 3
rect4_y_corner = (display_height * 4 / 5.0) - (rect_height / 2) # y-ccoordinate of head of the head of rectangle 4
#####################################################################################################################################################################################
rect1_y_displace = -(display_height / 2) + rect1_y_corner + (rect_height / 2)
rect2_y_displace = -(display_height / 2) + rect2_y_corner + (rect_height / 2)
rect3_y_displace = -(display_height / 2) + rect3_y_corner + (rect_height / 2)
rect4_y_displace = -(display_height / 2) + rect4_y_corner + (rect_height / 2)
#####################################################################################################################################################################################
inactive_color1 = purple
inactive_color2 = green
inactive_color3 = red
inactive_color4 = blue
#####################################################################################################################################################################################
active_color1 = bright_purple
active_color2 = bright_green
active_color3 = bright_red
active_color4 = bright_blue
#####################################################################################################################################################################################
rect1_x_displace = - (display_width / 2) + rect_x_corner + (rect_width / 2)
rect2_x_displace = - (display_width / 2) + rect_x_corner + (rect_width / 2)
rect3_x_displace = - (display_width / 2) + rect_x_corner + (rect_width / 2)
rect4_x_displace = - (display_width / 2) + rect_x_corner + (rect_width / 2)

To the top of your code, right after your imports. The goal is to get your program to flow seamlessly down until the last line. Take this code snippet for example:

def print_number(sumation):
 print(sumation)
num1 = int(input("Enter number 1: "))
num2 = int(input("Enter number 2: "))
def add_number(a, b):
 return a + b
sumation = add_number(num1, num2)
print_number(sumation)

While the code above works, it does not flow. This is a better way to write the above:

num1 = int(input("Enter number 1: "))
num2 = int(input("Enter number 2: "))
def add_number():
 return num1 + num2
def print_number():
 print(add_number())
print_number()

Just think of your code as if it were a book. You wouldn't show how the story ends before introducing he characters would you?

That is what PBS stands for. While PBS does not get into very specfic details, it provides a basic checklist for your program, and a good starting point to more specific optimization.

answered Sep 3, 2016 at 5:02
\$\endgroup\$

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.