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.
-
\$\begingroup\$ any one can help please \$\endgroup\$omar wael– omar wael2016εΉ΄09ζ02ζ₯ 18:34:59 +00:00Commented Sep 2, 2016 at 18:34
1 Answer 1
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.
Explore related questions
See similar questions with these tags.