3
\$\begingroup\$

I am a total beginner at Python, so I wrote a very simple snake game using pygame to get some practice with it. I also don't have too much experience with object-oriented design. Does the code layout look okay? Is it easy to read and understand? I'm sure it can be simplified some. The update_segments section in particular seems too long and overly complicated. I know there's a way to shorten it, maybe by going through it in reverse order, but it's just not coming to me at the moment.

import pygame
import random

BOARD_SIZE_WIDTH = 25
BOARD_SIZE_HEIGHT = 25

# This will determine the size of the objects drawn on the board.
# Must be equal to resolution
BOARD_SPACE_SIZE = 20

DISPLAY_RESOLUTION_WIDTH = BOARD_SIZE_WIDTH * BOARD_SPACE_SIZE
DISPLAY_RESOLUTION_HEIGHT = BOARD_SIZE_HEIGHT * BOARD_SPACE_SIZE

PLAYER1_START_X = 12
PLAYER1_START_Y = 12

COBRA_START_DIRECTION = "Up"
# Number of milliseconds between player movements.
MOVEMENT_DELAY = 100

SEGMENT_SIZE = 20

# Define the objects that can occupy board spaces.
EMPTY = 0
COBRA = 1
FOOD = 2

EMPTY_RECT = pygame.Rect(0, 0, BOARD_SPACE_SIZE, BOARD_SPACE_SIZE)
COBRA_RECT = pygame.Rect(0, 0, BOARD_SPACE_SIZE, BOARD_SPACE_SIZE)
FOOD_RECT = pygame.Rect(0, 0, BOARD_SPACE_SIZE, BOARD_SPACE_SIZE)

RED = (0xFF, 0x00, 0x00)
YELLOW = (0xFF, 0xFF, 0x00)
BLACK = (0x00, 0x00, 0x00)

class board(object):
    foodOnBoard = False

    def __init__(self, width, height, spaceSize):
        self.width = width
        self.height = height
        self.spaceSize = spaceSize
        self.spaces = [[0 for y in range(0, BOARD_SIZE_HEIGHT)] for x in range(0, BOARD_SIZE_WIDTH)]

    def create_food(self):
        while self.foodOnBoard == False:
            x = random.randint(0, BOARD_SIZE_WIDTH - 1)
            y = random.randint(0, BOARD_SIZE_HEIGHT - 1)
            if self.spaces[x][y] == EMPTY:
                self.spaces[x][y] = FOOD
                self.foodOnBoard = True

    def draw_board(self, screen):
        for y in range(0, BOARD_SIZE_HEIGHT):
            for x in range(0, BOARD_SIZE_WIDTH):
                drawX = x * BOARD_SPACE_SIZE
                drawY = y * BOARD_SPACE_SIZE
                if self.spaces[x][y] == COBRA:
                    pygame.draw.rect(screen, RED, pygame.Rect(drawX, drawY, BOARD_SPACE_SIZE, BOARD_SPACE_SIZE))
                elif self.spaces[x][y] == FOOD:
                    pygame.draw.rect(screen, YELLOW, pygame.Rect(drawX, drawY, BOARD_SPACE_SIZE, BOARD_SPACE_SIZE))
                elif self.spaces[x][y] == EMPTY:
                    pygame.draw.rect(screen, BLACK, pygame.Rect(drawX, drawY, BOARD_SPACE_SIZE, BOARD_SPACE_SIZE))

class cobra(object):
    numberOfSegments = 1
    sizeOfSegments = SEGMENT_SIZE
    segments = []

    def __init__(self, posX, posY, direction):
        self.posX = posX
        self.posY = posY
        self.direction = direction

    class segment(object):
        def __init__(self, posX, posY):
            self.posX = posX
            self.posY = posY

    def add_segment(self, segment):
        self.segments.append(segment)

    def move(self):
        if self.direction == "Up":
            self.posY -= 1
        if self.direction == "Down":
            self.posY += 1
        if self.direction == "Left":
            self.posX -= 1
        if self.direction == "Right":
            self.posX += 1    

def check_collision(board, cobra):
    if (cobra.posX < 0) or (cobra.posY < 0) or (cobra.posX > BOARD_SIZE_WIDTH - 1)\
    or (cobra.posY > BOARD_SIZE_HEIGHT - 1) or (board.spaces[cobra.posX][cobra.posY] == COBRA):
        collision = True
    else:
        collision = False

    return collision

def update_segments(board, cobra):
    posX = cobra.posX
    posY = cobra.posY

    if board.spaces[posX][posY] == FOOD:
        cobra.add_segment(cobra.segment(posX, posY))
        board.foodOnBoard = False

    for seg in cobra.segments:
        prevPosX = seg.posX
        prevPosY = seg.posY
        board.spaces[prevPosX][prevPosY] = EMPTY
        seg.posX = posX
        seg.posY = posY
        board.spaces[seg.posX][seg.posY] = COBRA
        posX = prevPosX
        posY = prevPosY

def main():
    # Set board size, cobra starting position, create first cobra segment, and initialize display
    board1 = board(BOARD_SIZE_WIDTH, BOARD_SIZE_HEIGHT, BOARD_SPACE_SIZE)
    cobra1 = cobra(PLAYER1_START_X, PLAYER1_START_Y, COBRA_START_DIRECTION)
    cobra1.add_segment(cobra.segment(cobra1.posX, cobra1.posY))

    pygame.init()

    screen = pygame.display.set_mode((DISPLAY_RESOLUTION_WIDTH, DISPLAY_RESOLUTION_HEIGHT))

    gameRunning = True
    paused = False

    while gameRunning == True:

        update_segments(board1, cobra1)
        board1.draw_board(screen)
        pygame.display.update()

        events = pygame.event.get()
        for event in events:
            if event.type == pygame.QUIT:
                pygame.quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    cobra1.direction = "Up"
                if event.key == pygame.K_DOWN:
                    cobra1.direction = "Down"
                if event.key == pygame.K_LEFT:
                    cobra1.direction = "Left"
                if event.key == pygame.K_RIGHT:
                    cobra1.direction = "Right"
                if event.key == pygame.K_SPACE:
                    if not paused:
                        paused = True
                    else:
                        paused = False

        if not paused:
            cobra1.move()
            collision = check_collision(board1, cobra1)

            if not board1.foodOnBoard:
                board1.create_food()

            if collision == True:
                gameRunning = False

            pygame.time.wait(MOVEMENT_DELAY)

main()
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.