import pygame
import time
from pygame.locals import * # importing global variables
import random
SIZE = 40 # Constant variable - size of block(snake)
bg_color = (102, 167, 67) # Greenish
class Food:
def __init__(self, parent_screen):
self.image = pygame.image.load("Resources\\apple.jpg").convert() # loading
block image from resources
self.parent_screen = parent_screen
self.x = SIZE * 5
self.y = SIZE * 5
def draw(self):
self.parent_screen.blit(self.image, (self.x, self.y)) # blit is used to
draw on surface blit(object, dimension)
pygame.display.flip() # displaying the surface color
def move(self):
self.x = random.randint(10, 24) * SIZE
self.y = random.randint(10, 19) * SIZE
class Snake: # making our snake
def __init__(self, parent_screen, length):
self.length = length
self.parent_screen = parent_screen
self.block = pygame.image.load("Resources\\block.jpg").convert() # loading
block image from resources
self.x = [SIZE] * length # x dimension of block
self.y = [SIZE] * length # y dimension of block
self.direction = None
def increase_length(self): # increasing length of snake
self.length += 1
self.x.append(-1)
self.y.append(-1)
def draw(self): # drawing blocks (snake)
# self.parent_screen.fill(bg_color) # main screen
for i in range(self.length): # iterating over x and y position
self.parent_screen.blit(self.block, (self.x[i], self.y[i])) # blit is
used to draw on surface blit(object, dimension)
pygame.display.flip() # displaying the surface color
def move_up(self):
self.direction = 'up'
def move_down(self):
self.direction = 'down'
def move_left(self):
self.direction = 'left'
def move_right(self):
self.direction = 'right'
def slither(self):
# Update body
for i in range(self.length - 1, 0, -1):
self.x[i] = self.x[i - 1]
self.y[i] = self.y[i - 1]
# Update head
if self.direction == 'up':
self.y[0] -= SIZE
if self.direction == 'down':
self.y[0] += SIZE
if self.direction == 'right':
self.x[0] += SIZE
if self.direction == 'left':
self.x[0] -= SIZE
self.draw()
class Game:
def __init__(self):
pygame.init() # initializing whole pygame module so we can use its
functions
pygame.display.set_caption("Snake")
pygame.mixer.init() # pygame sound module initialization
self.play_bg_music()
self.surface = pygame.display.set_mode((1000, 800)) # initializing game
window
self.surface.fill((0, 154, 23))
self.snake = Snake(self.surface, 1)
self.snake.draw()
self.food = Food(self.surface)
self.food.draw()
def is_collision(self, x1, y1, x2, y2):
if x2 <= x1 < x2 + SIZE:
if y2 <= y1 < y2 + SIZE:
return True # if collision the return True
return False # else false
def play_bg_music(self):
pygame.mixer.music.load("Resources\\bg_music_1.mp3") # loading music file
pygame.mixer.music.play() # playing loaded file
def play_sound(self, sound):
sound = pygame.mixer.Sound(f"Resources\\{sound}.mp3") # storing ding.mp3
in sound
pygame.mixer.Sound.play(sound) # playing sound
def render_bg(self):
bg = pygame.image.load("Resources\\background.jpg")
self.surface.blit(bg, (0, 0))
def play(self):
self.render_bg()
self.snake.slither()
self.food.draw()
self.display_score()
pygame.display.flip() # displaying the surface color
# snake colliding with apple
if self.is_collision(self.snake.x[0], self.snake.y[0], self.food.x,
self.food.y): # checking collision b/w food and snake
self.play_sound("ding")
self.food.move() # moving food after eaten
self.snake.increase_length() # increasing snake's length
# snake colliding with itself
for i in range(1, self.snake.length):
if self.is_collision(self.snake.x[0], self.snake.y[0], self.snake.x[i],
self.snake.y[i]): # snake head colliding with remaining blocks
self.play_sound("crash")
raise "Game Over" # throwing an exception
# snake colliding with boundaries
if not (0 <= self.snake.x[0] <= 1000 and 0 <= self.snake.y[0] <= 800):
self.play_sound('crash')
raise "Hit the boundary error"
def show_game_over(self):
self.render_bg()
font = pygame.font.SysFont('arial', 30)
line1 = font.render(f"Game Over! Your Score is {self.snake.length}", True,
(255, 255, 255))
self.surface.blit(line1, (200, 300))
line2 = font.render("To play again press Enter. To exit press Escape",
True, (255, 255, 255))
self.surface.blit(line2, (200, 350))
pygame.display.flip()
pygame.mixer.music.pause() # pausing music on game over
def display_score(self): # showing score
font = pygame.font.SysFont('arial', 30)
score = font.render(f"Score: {self.snake.length}", True, (255, 255, 255))
self.surface.blit(score, (800, 10))
def reset(self):
self.snake = Snake(self.surface, 1)
self.food = Food(self.surface)
def run(self): # running the game
# Making Event Loop - Waiting for user's input to do something
running = True
pause = False
while running:
for event in pygame.event.get(): # getting user's input
if event.type == KEYDOWN: # checking key presses
if event.key == K_ESCAPE: # if user presses escape key
running = False
if event.key == K_RETURN:
pygame.mixer.music.unpause() # un-pausing music on game
over
pause = False
# moving the snake
if not pause:
if event.key == K_UP: # pressing UP Arrow Key
self.snake.move_up()
if event.key == K_DOWN: # pressing DOWN Arrow Key
self.snake.move_down()
if event.key == K_LEFT: # pressing LEFT Arrow Key
self.snake.move_left()
if event.key == K_RIGHT: # pressing RIGHT Arrow Key
self.snake.move_right()
elif event.type == QUIT: # If user clicks x (top right)
running = False
try:
if not pause:
self.play()
except Exception:
self.show_game_over()
pause = True
self.reset()
time.sleep(0.1) # will move on its own evey 0.1 sec
if __name__ == '__main__': # __name__ is a built-in variable which prevents the
module to run in other files if imported.
game = Game()
game.run()
# Generating an exe, file.
# 1. pip install auto-py-to-exe
# 2. Run auto-py-to-exe.exe