Python Forum
Snake Game in Python with Pygame
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Snake Game in Python with Pygame
#1
So with some help I wrote this simple Snake game in Python using Pygame. It works in it's current state with no errors that I could find. I was wondering if anyone had some ideas to refine the code or any ideas to make the game better, I'd love to hear them.
import pygame
import sys
import random
import time

pygame.init()

class Snake():
    def __init__(self):
        self.position = [100,50]
        self.body = [[100,50],[90,50],[80,50]]
        self.direction = "RIGHT"
       

    def changeDirTo(self,dir):
        if dir=="RIGHT" and not self.direction=="LEFT":
            self.direction = "RIGHT"
        elif dir=="LEFT" and not self.direction=="RIGHT":
            self.direction = "LEFT"
        elif dir=="UP" and not self.direction=="DOWN":
            self.direction = "UP"
        elif dir=="DOWN" and not self.direction=="UP":
            self.direction = "DOWN"
        
    def move(self,foodPos):
        if self.direction == "RIGHT":
            self.position[0] = self.position[0] + 10
        elif self.direction == "LEFT":
            self.position[0] = self.position[0] - 10
        elif self.direction == "UP":
            self.position[1] = self.position[1] - 10
        elif self.direction == "DOWN":
            self.position[1] = self.position[1] + 10
        self.body.insert(0,list(self.position))
        
        if self.position == foodPos:
            return 1
        else:
            self.body.pop()
            return 0

    def move_Right(self):
        self.position[0] = self.position[0] + 10
    def move_Left(self):
        self.position[0] = self.position[0] - 10
    def move_Up(self):
        self.position[0] = self.position[1] - 10
    def move_Down(self):
        self.position[0] = self.position[1] + 10
    
    def checkCollision(self):
        if self.position[0] > 490 or self.position[0] < 10:
            return 1 
        elif self.position[1] > 500 or self.position[1] < 10:
            return 1
        for bodyPart in self.body[1:]:
            if self.position == bodyPart:
                return 1
        return 0

    def getHeadPosition(self):
        return self.position
    
    def getBody(self):
        return self.body


class FoodSpawn():
    def __init__(self):
        self.position = [random.randint(4,46)*10,random.randint(4,46)*10]
        self.isFoodOnScreen = True

    def spawnFood(self):
        if self.isFoodOnScreen == False:
            self.position = [random.randrange(4,46)*10,random.randrange(4,46)*10]
            self.isFoodOnScreen = True
        return self.position
    
    def setFoodOnScreen(self,b):
        self.isFoodOnScreen = b


window = pygame.display.set_mode((500 + 20,500 + 20))
pygame.display.set_caption("Snake Game")
fps = pygame.time.Clock()

score = 0

snake = Snake()
foodSpawner = FoodSpawn()

def gameOver():
    font = pygame.font.SysFont('Candara', 30)
    score_text = font.render("Congrats you got " + str(score) + " points!",4,(255,0,0))
    window.blit(score_text,(100,250))
    pygame.display.flip()
    time.sleep(3)
    pygame.quit()
    sys.exit()

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            gameOver()
        
        pressed = pygame.key.get_pressed()

        if pressed[pygame.K_RIGHT]:
            snake.changeDirTo('RIGHT')
        elif pressed[pygame.K_LEFT]:
            snake.changeDirTo('LEFT')
        elif pressed[pygame.K_UP]:
            snake.changeDirTo('UP')
        elif pressed[pygame.K_DOWN]:
            snake.changeDirTo('DOWN')
        elif pressed[pygame.K_ESCAPE]:
            gameOver()

    foodPos = foodSpawner.spawnFood()
    if(snake.move(foodPos)==1):
        score+=1
        foodSpawner.setFoodOnScreen(False)

    window.fill(pygame.Color(225,225,225))
    for x in range(0, 510, 10):
        pygame.draw.rect(window, (0,0,225), [x, 0, 10, 10])
        pygame.draw.rect(window, (0,0,225), [x, 510, 10, 10])

    for x in range(0, 510, 10):
        pygame.draw.rect(window, (0,0,225), [0, x, 10, 10])
        pygame.draw.rect(window, (0,0,225), [510, x, 10, 10])

    for pos in snake.getBody():
        pygame.draw.rect(window,pygame.Color(0,225,0),pygame.Rect(pos[0],pos[1],10,10))
    pygame.draw.rect(window,pygame.Color(225,0,0),pygame.Rect(foodPos[0],foodPos[1],10,10))
    
    if(snake.checkCollision()==1):
        gameOver()
    
    pygame.display.set_caption("Snake | Score: " + str(score))
    pygame.display.flip()
    fps.tick(20)

pygame.quit()
Reply
#2
Don't get discouraged by the following list (PEP8 violations), as they clean up fast and almost all of there are white-space warnings
This was created by pycodestyle which can be installed using:
pip install pycodestyle
and run using:
pycodestyle Snake.py
I named your code Snake.py for a run on my system
Here's the results:
Output:
Snake.py:5:1: W293 blank line contains whitespace Snake.py:7:1: W293 blank line contains whitespace Snake.py:8:1: E302 expected 2 blank lines, found 1 Snake.py:10:29: E231 missing whitespace after ',' Snake.py:11:26: E231 missing whitespace after ',' Snake.py:11:30: E231 missing whitespace after ',' Snake.py:11:34: E231 missing whitespace after ',' Snake.py:11:38: E231 missing whitespace after ',' Snake.py:11:42: E231 missing whitespace after ',' Snake.py:13:1: W293 blank line contains whitespace Snake.py:14:1: W293 blank line contains whitespace Snake.py:15:5: E303 too many blank lines (2) Snake.py:15:25: E231 missing whitespace after ',' Snake.py:16:15: E225 missing whitespace around operator Snake.py:16:47: E225 missing whitespace around operator Snake.py:18:17: E225 missing whitespace around operator Snake.py:18:48: E225 missing whitespace around operator Snake.py:20:17: E225 missing whitespace around operator Snake.py:20:46: E225 missing whitespace around operator Snake.py:22:17: E225 missing whitespace around operator Snake.py:22:48: E225 missing whitespace around operator Snake.py:24:1: W293 blank line contains whitespace Snake.py:25:18: E231 missing whitespace after ',' Snake.py:34:27: E231 missing whitespace after ',' Snake.py:35:1: W293 blank line contains whitespace Snake.py:41:1: W293 blank line contains whitespace Snake.py:44:5: E301 expected 1 blank line, found 0 Snake.py:46:5: E301 expected 1 blank line, found 0 Snake.py:48:5: E301 expected 1 blank line, found 0 Snake.py:50:1: W293 blank line contains whitespace Snake.py:53:21: W291 trailing whitespace Snake.py:60:1: W293 blank line contains whitespace Snake.py:63:1: W293 blank line contains whitespace Snake.py:66:1: W293 blank line contains whitespace Snake.py:67:1: W293 blank line contains whitespace Snake.py:70:42: E231 missing whitespace after ',' Snake.py:70:49: E231 missing whitespace after ',' Snake.py:70:66: E231 missing whitespace after ',' Snake.py:72:1: W293 blank line contains whitespace Snake.py:74:32: E712 comparison to False should be 'if cond is False:' or 'if not cond:' Snake.py:75:48: E231 missing whitespace after ',' Snake.py:75:55: E231 missing whitespace after ',' Snake.py:75:74: E231 missing whitespace after ',' Snake.py:75:80: E501 line too long (81 > 79 characters) Snake.py:78:1: W293 blank line contains whitespace Snake.py:79:29: E231 missing whitespace after ',' Snake.py:81:1: W293 blank line contains whitespace Snake.py:82:1: W293 blank line contains whitespace Snake.py:83:43: E231 missing whitespace after ',' Snake.py:86:1: W293 blank line contains whitespace Snake.py:88:1: W293 blank line contains whitespace Snake.py:91:1: W293 blank line contains whitespace Snake.py:92:1: E302 expected 2 blank lines, found 1 Snake.py:94:75: E231 missing whitespace after ',' Snake.py:94:77: E231 missing whitespace after ',' Snake.py:94:80: E501 line too long (87 > 79 characters) Snake.py:94:82: E231 missing whitespace after ',' Snake.py:94:84: E231 missing whitespace after ',' Snake.py:95:27: E231 missing whitespace after ',' Snake.py:95:32: E231 missing whitespace after ',' Snake.py:100:1: W293 blank line contains whitespace Snake.py:101:1: E305 expected 2 blank lines after class or function definition, found 1 Snake.py:105:1: W293 blank line contains whitespace Snake.py:107:1: W293 blank line contains whitespace Snake.py:118:1: W293 blank line contains whitespace Snake.py:120:27: E225 missing whitespace around operator Snake.py:121:14: E225 missing whitespace around operator Snake.py:123:1: W293 blank line contains whitespace Snake.py:124:33: E231 missing whitespace after ',' Snake.py:124:37: E231 missing whitespace after ',' Snake.py:126:36: E231 missing whitespace after ',' Snake.py:126:38: E231 missing whitespace after ',' Snake.py:127:36: E231 missing whitespace after ',' Snake.py:127:38: E231 missing whitespace after ',' Snake.py:128:1: W293 blank line contains whitespace Snake.py:130:36: E231 missing whitespace after ',' Snake.py:130:38: E231 missing whitespace after ',' Snake.py:131:36: E231 missing whitespace after ',' Snake.py:131:38: E231 missing whitespace after ',' Snake.py:132:1: W293 blank line contains whitespace Snake.py:134:32: E231 missing whitespace after ',' Snake.py:134:47: E231 missing whitespace after ',' Snake.py:134:51: E231 missing whitespace after ',' Snake.py:134:54: E231 missing whitespace after ',' Snake.py:134:73: E231 missing whitespace after ',' Snake.py:134:80: E231 missing whitespace after ',' Snake.py:134:80: E501 line too long (87 > 79 characters) Snake.py:134:83: E231 missing whitespace after ',' Snake.py:135:28: E231 missing whitespace after ',' Snake.py:135:45: E231 missing whitespace after ',' Snake.py:135:47: E231 missing whitespace after ',' Snake.py:135:50: E231 missing whitespace after ',' Snake.py:135:73: E231 missing whitespace after ',' Snake.py:135:80: E501 line too long (91 > 79 characters) Snake.py:135:84: E231 missing whitespace after ',' Snake.py:135:87: E231 missing whitespace after ',' Snake.py:136:1: W293 blank line contains whitespace Snake.py:137:30: E225 missing whitespace around operator Snake.py:139:1: W293 blank line contains whitespace Snake.py:143:1: W293 blank line contains whitespace
Reply
#3
Quote:
score_text = font.render("Congrats you got " + str(score) + " points!",4,(255,0,0))
use format or f strings, dont use old school +
It also seems not appropriate to say congrats when the user loses.

You already have a snake and food class. You might as well clean up the code by putting events in them. Such as move this into snake
Quote:
        if pressed[pygame.K_RIGHT]:
            snake.changeDirTo('RIGHT')
        elif pressed[pygame.K_LEFT]:
            snake.changeDirTo('LEFT')
        elif pressed[pygame.K_UP]:
            snake.changeDirTo('UP')
        elif pressed[pygame.K_DOWN]:
            snake.changeDirTo('DOWN')
        elif pressed[pygame.K_ESCAPE]:
            gameOver()
 
as well as its draw method and the food draw into the foods class draw method

Quote:
def gameOver():
    font = pygame.font.SysFont('Candara', 30)
    score_text = font.render("Congrats you got " + str(score) + " points!",4,(255,0,0))
    window.blit(score_text,(100,250))
    pygame.display.flip()
    time.sleep(3)
    pygame.quit()
    sys.exit()
A couple things here. When you write bigger games. You are going to want to handle states differently. The gameplay is one, and the end of the game is another.
Example: https://python-forum.io/Thread-PyGame-Cr...te-machine
You should only have flip()/update() in your code once, not every state. In a small game like this its quicker and easier to do it this way, but as a game grows, it becomes spaghetti code by maintaining this structure. Here is an example of why as well as an example of two code snippets (wrong and right way). https://python-forum.io/Thread-PyGame-wa...-tutorials

Also you should gracefully exit the program at the end of the script, not use sys.exit to kill the program.
Recommended Tutorials:
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Pygame clicker game CrazyMakes 2 13,092 May-26-2020, 07:41 PM
Last Post: CrazyMakes
  [PyGame] Block Game Zman350x 3 6,066 May-30-2018, 01:55 AM
Last Post: fierygaming
  Flappy Bird Game [Pygame] georgecoopers 2 4,546 Apr-30-2017, 07:59 PM
Last Post: Mekire

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020