Snake version 2

A different user evet type of management in this snake game version.

import pygame
from pygame import gfxdraw
import random


# Define Constants

BOARD_SIZE = 20  # Size of the board, in block
BLOCK_SIZE = 20  # Size of 1 block, in pixel
GAME_SPEED = 8  # Game speed (Normal = 10), The bigger, the faster
SIZE = (BOARD_SIZE * BLOCK_SIZE, BOARD_SIZE * BLOCK_SIZE)
window = pygame.display.set_mode(SIZE)
pygame.display.set_caption("window")
score = 0


# ============================ THE SNAKE POSITION AND BEHAVIOUR ======

class Snake():
    def __init__(self):
        self.starting_position()

    def starting_position(self):
        "The coordinates of the start and direction are here"

        self.head = [
            # self.head[0] = x = 5
            int(BOARD_SIZE / 4),
            # self.head[1] = x = 5
            int(BOARD_SIZE / 4)]
        self.body = [[self.head[0], self.head[1]],
                     [self.head[0] - 1, self.head[1]],
                     [self.head[0] - 2, self.head[1]]
                     ]
        #   [ ][ ][ ] => right
        self.direction = "RIGHT"

    def change_direction_to(self, dir):
        "When you hit a key in the while loop; avoid going backwards"
        if dir == "RIGHT" and not self.direction == "LEFT":
            self.direction = "RIGHT"
        if dir == "LEFT" and not self.direction == "RIGHT":
            self.direction = "LEFT"
        if dir == "UP" and not self.direction == "DOWN":
            self.direction = "UP"
        if dir == "DOWN" and not self.direction == "UP":
            self.direction = "DOWN"

    def move(self, food_pos):
        "Continue to move in the dir, place one square forward, delete last"
        # if do not eat, return 1 if you eat
        # so that in the while loop... score += 1 GAME_SPEED +=1 food_spawn
        if self.direction == "RIGHT":
            self.head[0] += 1
        if self.direction == "LEFT":
            self.head[0] -= 1
        if self.direction == "UP":
            self.head[1] -= 1
        if self.direction == "DOWN":
            self.head[1] += 1
        # [][][]
        self.body.insert(0, list(self.head))
        # [][][][]
        if self.head == food_pos:
            # [][][][]  it grows after he ate
            return 1
        else:
            "If do not eat... same size"
            self.body.pop()
            # pop([])   [][][]  it stays of the same size, but moves
            return 0

    def check_collision(self):
        # Checks collision with border or himself

        conditions = (
            # x axis limits  <0 ..... >20
            self.head[0] >= 20 or self.head[0] < 0,
            # y axis
            self.head[1] > 19 or self.head[1] < 0,
            # checks if you hit yourself
            # comprehension list - a for loop with a python syntax
            [x for x in self.body[1:] if self.head == x]
        )
        if any(conditions):
            return 1
        else:
            return 0

# ============================= SPAWN FOOD =======================

class FoodSpawner():
    def __init__(self):
        self.food_pos = [random.randrange(1, BOARD_SIZE), random.randrange(1, BOARD_SIZE)]
        self.is_food_on_screen = True

    def spawn_food(self):
        if self.is_food_on_screen == False:
            self.food_pos = [random.randrange(1, BOARD_SIZE), random.randrange(1, BOARD_SIZE)]
            self.is_food_on_screen = True
        return self.food_pos

    def set_food_on_screen(self, bool_value):
        self.is_food_on_screen = bool_value


# ===================== DRAW HEAD, BODY and FOOD ================


def draw_head(pos):
    pygame.draw.rect(
        window,
        (0, 255, 0),
        pygame.Rect(
            pos[0] * BLOCK_SIZE,
            pos[1] * BLOCK_SIZE,
            BLOCK_SIZE,
            BLOCK_SIZE))

def draw_body(pos):
    pygame.draw.rect(window, (0, 128, 0), pygame.Rect(pos[0] * BLOCK_SIZE, pos[1] * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE))

def delete_tail(pos):
    pygame.draw.rect(window, (0, 0, 0), pygame.Rect(snake.body[-1][0] * BLOCK_SIZE, snake.body[-1][1] * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE))

def delete_fruit(pos, food_pos):
    x = food_pos[0] * BLOCK_SIZE + 10
    y = food_pos[1] * BLOCK_SIZE + 10
    r = 9
    gfxdraw.filled_circle(window, x, y, r, (0, 0, 0))

def draw_fruit(food_pos):
    gfxdraw.filled_circle(window, food_pos[0] * BLOCK_SIZE + 10, food_pos[1] * BLOCK_SIZE + 10, 9, (255, 0, 0))


# =========== To write on the window surface on the screen ========

def write(text_to_show, x=0, y=0, middle="both"):
    "It write in the middle by default, if not middle='both' middle='x'"
    text = font.render(text_to_show, 1, pygame.Color("Coral"))
    if middle == "x":
        text_rect = text.get_rect(center=((size // 2, y)))
        window.blit(text, text_rect)      
    elif middle == "both":
        text_rect = text.get_rect(center=((size // 2, size // 2)))
        window.blit(text, text_rect)
    else:
        window.blit(text, (x, y))
    pygame.display.update()


# ================================= MANAGE GAME PART =================

def restart():
    global GAME_SPEED

    GAME_SPEED = 8
    window.fill((0, 0, 0))
    snake.starting_position()
    start()


def press_to_start():
    "Initial menu"
    global loop, snake, food_spawner
    global font, size

    pygame.init()
    font = pygame.font.SysFont("Arial", 24)
    size = BOARD_SIZE * BLOCK_SIZE # 400 20x20
    snake = Snake()
    food_spawner = FoodSpawner()
    write("Python vs Snake", y=30, middle="x")
    write("Press s to start")
    while True:
        event = pygame.event.wait()
        if event.type == pygame.QUIT:
            loop = 0
            break
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                loop = 0
                break
            if event.key == pygame.K_s:
                restart()
                break
    pygame.quit()


def start():
    "Starts the game"
    global GAME_SPEED, score, loop

    clock = pygame.time.Clock()
    food_pos = food_spawner.spawn_food()
    loop = 1
    while loop:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                loop = 0
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    loop = 0
                elif event.key == pygame.K_RIGHT:
                    snake.change_direction_to("RIGHT")
                elif event.key == pygame.K_UP:
                    snake.change_direction_to("UP")
                elif event.key == pygame.K_DOWN:
                    snake.change_direction_to("DOWN")
                elif event.key == pygame.K_LEFT:
                    snake.change_direction_to("LEFT")
        if snake.move(food_pos) == 1:
            # delete_fruit(pos, food_pos)
            score += 1
            food_spawner.set_food_on_screen(False)
            GAME_SPEED += 1
            food_pos = food_spawner.spawn_food()

        head = 1
        for pos in snake.body:
            if head == 1:
                draw_head(pos)
                head = 0
            else:
                draw_body(pos)
        delete_tail(pos)
        draw_fruit(food_pos)

        if snake.check_collision() == 1:
            loop = 0
            press_to_start()
        pygame.display.update()
        clock.tick(GAME_SPEED)

    pygame.quit()

press_to_start()

 


Subscribe to the newsletter for updates
Tkinter templates
Avatar My youtube channel

Twitter: @pythonprogrammi - python_pygame

Videos

Speech recognition game

Pygame's Platform Game

Other Pygame's posts

Published by pythonprogramming

Started with basic on the spectrum, loved javascript in the 90ies and python in the 2000, now I am back with python, still making some javascript stuff when needed.