💻Project 5 : Snake Game In Python

Project 5 : Snake Game In Python

This is a Python project that uses the Pygame library to create a simple game where a player controls a snake on a grid. The snake can move in different directions and must eat randomly generated green "snacks" to grow longer. The game continues until the snake hits the boundaries of the grid or runs into itself.

Here's a breakdown of the different components and functionalities in simple English:

  1. Importing Libraries: The program starts by importing necessary libraries like math, random, pygame, and tkinter.

  2. Setting Up Constants: The game screen is set up with a width of 500 pixels and a height of 500 pixels. The grid is divided into 25 columns and 20 rows.

  3. Defining Cube Class: The cube class represents a single unit on the grid. It has properties like position, direction, and color. It can move in different directions and draw itself on the game screen.

  4. Defining Snake Class: The snake class represents the player-controlled snake. It consists of a series of connected cubes. The snake can move, grow longer when it eats a snack, and restart when it hits the boundaries or itself.

  5. Game Logic: The main game loop is in the main() function. It initializes the game window and sets up the snake and a green snack. The loop continues as long as the flag is true.

  6. Moving the Snake: The snake's movement is controlled using the arrow keys. The move() method of the snake class updates the position of each cube in the snake's body.

  7. Handling Collisions: The game checks for collisions with the boundaries and the snake's own body. If the snake collides with a boundary or itself, the game ends and the player's score is displayed. The snake can also collide with the green snack, causing it to grow longer.

  8. Drawing the Game: The redrawWindow() function clears the screen, draws the grid, the snake, and the snack. It updates the game display.

  9. Running the Game: The main() function initializes the game window, sets up the snake and the snack, and enters the main game loop. The loop keeps the game running, processing player input and updating the game state.

In summary, this project implements a basic snake game where players control a snake to collect green snacks and avoid collisions. It demonstrates fundamental concepts of game programming, user input handling, collision detection, and graphical rendering using the Pygame library.


Code:

  1import math
  2import random
  3import pygame
  4import random
  5import tkinter as tk
  6from tkinter import messagebox
  7
  8width = 500
  9height = 500
 10
 11cols = 25
 12rows = 20
 13
 14
 15class cube():
 16    rows = 20
 17    w = 500
 18    def __init__(self, start, dirnx=1, dirny=0, color=(255,0,0)):
 19        self.pos = start
 20        self.dirnx = dirnx
 21        self.dirny = dirny # "L", "R", "U", "D"
 22        self.color = color
 23
 24    def move(self, dirnx, dirny):
 25        self.dirnx = dirnx
 26        self.dirny = dirny
 27        self.pos  = (self.pos[0] + self.dirnx, self.pos[1] + self.dirny)
 28            
 29
 30    def draw(self, surface, eyes=False):
 31        dis = self.w // self.rows
 32        i = self.pos[0]
 33        j = self.pos[1]
 34        
 35        pygame.draw.rect(surface, self.color, (i*dis+1,j*dis+1,dis-2,dis-2))
 36        if eyes:
 37            centre = dis//2
 38            radius = 3
 39            circleMiddle = (i*dis+centre-radius,j*dis+8)
 40            circleMiddle2 = (i*dis + dis -radius*2, j*dis+8)
 41            pygame.draw.circle(surface, (0,0,0), circleMiddle, radius)
 42            pygame.draw.circle(surface, (0,0,0), circleMiddle2, radius)
 43        
 44
 45
 46class snake():
 47    body = []
 48    turns = {}
 49    
 50    def __init__(self, color, pos):
 51        #pos is given as coordinates on the grid ex (1,5)
 52        self.color = color
 53        self.head = cube(pos)
 54        self.body.append(self.head)
 55        self.dirnx = 0
 56        self.dirny = 1
 57    
 58    def move(self):
 59        for event in pygame.event.get():
 60            if event.type == pygame.QUIT:
 61                pygame.quit()
 62            keys = pygame.key.get_pressed()
 63
 64            for key in keys:
 65                if keys[pygame.K_LEFT]:
 66                    self.dirnx = -1
 67                    self.dirny = 0
 68                    self.turns[self.head.pos[:]] = [self.dirnx,self.dirny]
 69                elif keys[pygame.K_RIGHT]:
 70                    self.dirnx = 1
 71                    self.dirny = 0
 72                    self.turns[self.head.pos[:]] = [self.dirnx,self.dirny]
 73                elif keys[pygame.K_UP]:
 74                    self.dirny = -1
 75                    self.dirnx = 0
 76                    self.turns[self.head.pos[:]] = [self.dirnx,self.dirny]
 77                elif keys[pygame.K_DOWN]:
 78                    self.dirny = 1
 79                    self.dirnx = 0
 80                    self.turns[self.head.pos[:]] = [self.dirnx,self.dirny]
 81        
 82        for i, c in enumerate(self.body):
 83            p = c.pos[:]
 84            if p in self.turns:
 85                turn = self.turns[p]
 86                c.move(turn[0], turn[1])
 87                if i == len(self.body)-1:
 88                    self.turns.pop(p)
 89            else:
 90                c.move(c.dirnx,c.dirny)
 91        
 92        
 93    def reset(self,pos):
 94        self.head = cube(pos)
 95        self.body = []
 96        self.body.append(self.head)
 97        self.turns = {}
 98        self.dirnx = 0
 99        self.dirny = 1
100
101    def addCube(self):
102        tail = self.body[-1]
103        dx, dy = tail.dirnx, tail.dirny
104
105        if dx == 1 and dy == 0:
106            self.body.append(cube((tail.pos[0]-1,tail.pos[1])))
107        elif dx == -1 and dy == 0:
108            self.body.append(cube((tail.pos[0]+1,tail.pos[1])))
109        elif dx == 0 and dy == 1:
110            self.body.append(cube((tail.pos[0],tail.pos[1]-1)))
111        elif dx == 0 and dy == -1:
112            self.body.append(cube((tail.pos[0],tail.pos[1]+1)))
113
114        self.body[-1].dirnx = dx
115        self.body[-1].dirny = dy
116    
117    def draw(self, surface):
118        for i,c in enumerate(self.body):
119            if i == 0:
120                c.draw(surface, True)
121            else:
122                c.draw(surface)
123
124
125
126def redrawWindow():
127    global win
128    win.fill((0,0,0))
129    drawGrid(width, rows, win)
130    s.draw(win)
131    snack.draw(win)
132    pygame.display.update()
133    pass
134
135
136
137def drawGrid(w, rows, surface):
138    sizeBtwn = w // rows
139
140    x = 0
141    y = 0
142    for l in range(rows):
143        x = x + sizeBtwn
144        y = y +sizeBtwn
145
146        pygame.draw.line(surface, (255,255,255), (x, 0),(x,w))
147        pygame.draw.line(surface, (255,255,255), (0, y),(w,y))
148    
149
150
151def randomSnack(rows, item):
152    positions = item.body
153
154    while True:
155        x = random.randrange(1,rows-1)
156        y = random.randrange(1,rows-1)
157        if len(list(filter(lambda z:z.pos == (x,y), positions))) > 0:
158               continue
159        else:
160               break
161
162    return (x,y)
163
164
165def main():
166    global s, snack, win
167    win = pygame.display.set_mode((width,height))
168    s = snake((255,0,0), (10,10))
169    s.addCube()
170    snack = cube(randomSnack(rows,s), color=(0,255,0))
171    flag = True
172    clock = pygame.time.Clock()
173    
174    while flag:
175        pygame.time.delay(50)
176        clock.tick(10)
177        s.move()
178        headPos = s.head.pos
179        if headPos[0] >= 20 or headPos[0] < 0 or headPos[1] >= 20 or headPos[1] < 0:
180            print("Score:", len(s.body))
181            s.reset((10, 10))
182
183        if s.body[0].pos == snack.pos:
184            s.addCube()
185            snack = cube(randomSnack(rows,s), color=(0,255,0))
186            
187        for x in range(len(s.body)):
188            if s.body[x].pos in list(map(lambda z:z.pos,s.body[x+1:])):
189                print("Score:", len(s.body))
190                s.reset((10,10))
191                break
192                    
193        redrawWindow()
194
195main()