Search code examples
pythonpygamegame-physics

How do i check if the snake is collidiing with the border?


I'm making a snake game in pygame and can't figure out how to do collision chek on the border of the game. I would like to implement a collision check with the border so i can end the game when the snake hits the border. I'm wondering what the best way to do this is. Here is my code if it helps.

import pygame
import sys
import random

pygame.init()

win_width, win_height = 900, 1000

game_width, game_height = 800, 800
GRID_SIZE = 40


UP = (0, -1)
DOWN = (0, 1)
LEFT = (-1, 0)
RIGHT = (1, 0)

win = pygame.display.set_mode((win_width, win_height), pygame.RESIZABLE)


class Snake:
    def __init__(self):
        self.length = 1
        self.positions = [(game_width // 2 + 50, game_height // 2 + 50)]
        self.direction = random.choice([UP, DOWN, LEFT, RIGHT])
        self.color = (0, 255, 0)

    def get_head_position(self):
        return self.positions[0]

    def update(self):
        head = self.get_head_position()
        x, y = self.direction
        new = (((head[0] + (x * GRID_SIZE)) % game_width), (head[1] + (y * GRID_SIZE)) % game_height)
        if len(self.positions) > 2 and new in self.positions[2:]:
            self.reset()
        else:
            self.positions.insert(0, new)
            if len(self.positions) > self.length:
                self.positions.pop()

    def reset(self):
        self.length = 1
        self.positions = [(game_width, game_height)]
        self.direction = random.choice([UP, DOWN, LEFT, RIGHT])
        game_over_sound = pygame.mixer.Sound("Assets/Sounds/game_over.ogg")
        game_over_sound.play()

    def render(self, surface):
        for p in self.positions:
            snake_rect = pygame.draw.rect(surface, self.color, (p[0], p[1], GRID_SIZE, GRID_SIZE))
            snake_up = pygame.image.load("Assets/Images/snake_up.png")
            snake_down = pygame.image.load("Assets/Images/snake_down.png")
            snake_left = pygame.image.load("Assets/Images/snake_left.png")
            snake_right = pygame.image.load("Assets/Images/snake_right.png")
            if self.direction == UP:
                surface.blit(snake_up, snake_rect)
            if self.direction == DOWN:
                surface.blit(snake_down, snake_rect)
            if self.direction == LEFT:
                surface.blit(snake_left, snake_rect)
            if self.direction == RIGHT:
                surface.blit(snake_right, snake_rect)


class Food:
    pass


def main():

    clock = pygame.time.Clock()
    fps = 10

    bg = pygame.image.load("Assets/Images/background.png")

    snake = Snake()

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP and not snake.direction == DOWN:
                    snake.direction = UP
                elif event.key == pygame.K_DOWN and not snake.direction == UP:
                    snake.direction = DOWN
                elif event.key == pygame.K_LEFT and not snake.direction == RIGHT:
                    snake.direction = LEFT
                elif event.key == pygame.K_RIGHT and not snake.direction == LEFT:
                    snake.direction = RIGHT
                elif event.key == pygame.K_ESCAPE:
                    pygame.quit()

        win.fill((255, 210, 190))
        win.blit(bg, (50, 50))
        pygame.draw.rect(win, (100, 100, 100), (30, 30, 840, 840), width=20)
        snake.update()
        snake.render(win)
        pygame.display.update()
        clock.tick(fps)


if __name__ == "__main__":
    main()

I have alredy tried "pygame.Rect.colliderect(Rect)" but can't get it to work


Solution

  • you can modify the update method in your Snake class. After calculating the new head position (new), check if it goes beyond the game borders. I

    def update(self):
        head = self.get_head_position()
        x, y = self.direction
        new = (((head[0] + (x * GRID_SIZE)) % game_width), (head[1] + (y * GRID_SIZE)) % game_height)
    
        # Check if the new head position is outside the game borders
        if new[0] < 30 or new[0] >= game_width + 30 or new[1] < 30 or new[1] >= game_height + 30:
            self.reset()
        else:
            if len(self.positions) > 2 and new in self.positions[2:]:
                self.reset()
            else:
                self.positions.insert(0, new)
                if len(self.positions) > self.length:
                    self.positions.pop()