Pygame snake and food collision detection

Question:

I just decided to learn pygame so I picked up this tutorial.

When I’m in adding the food section, my snake is eating the food but there is no output message. So if statement is not checking for the right values. I tried to change them like foodX – snake_block or foodX + snake_block but there is still no output. Can someone help?

import pygame
import random

pygame.init()

#setting up window
screen_width = 1920
screen_height = 1080
screen = pygame.display.set_mode((screen_width,screen_height))
pygame.display.set_caption("Snake Game")
pygame.display.update()

#colors
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213)

#FPS 
clock = pygame.time.Clock()

#message function
font_style = pygame.font.SysFont(None, 50)
def message(msg, color):
    mesg = font_style.render(msg, True, color)
    screen.blit(mesg, [screen_width/2, screen_height/2])

#gameloop
def gameLoop():
    game_over = False
    game_close = False
    
    #coordinates for snakes starting point
    x1 = screen_width/2
    y1 = screen_height/2

    #for snake movement
    snake_block = 16
    snake_speed = 120
    x1_change = 0       
    y1_change = 0
    
    #food!
    foodX = round(random.randrange(0, screen_width - snake_block) / 10) * 10
    foodY = round(random.randrange(0, screen_height - snake_block) / 10) * 10  
       
    while not game_over:
        
        while game_close == True:
            screen.fill(black)
            message("You Lost! Press ALT + F4 to quit or C to play again", red)
            pygame.display.update()
            for event in pygame.event.get():
                if event.key == pygame.K_c:
                    gameLoop()
                    
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game_over = True
        
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_a:
                    x1_change = -snake_block
                    y1_change = 0
                elif event.key == pygame.K_d:
                    x1_change = snake_block
                    y1_change = 0
                elif event.key == pygame.K_w:
                    x1_change = 0
                    y1_change = -snake_block
                elif event.key == pygame.K_s:
                    x1_change = 0
                    y1_change = +snake_block
                    
        if x1 >= screen_width:       
            x1 = 25
        elif x1 <= 0:
            x1 = screen_width-25
        elif y1 >= screen_height:
            y1 = 25
        elif y1 <= 0:
            y1 = screen_height-25
        x1 += x1_change
        y1 += y1_change
        
        screen.fill(black)
        pygame.draw.rect(screen, blue, [foodX, foodY, snake_block, snake_block])
        pygame.draw.rect(screen,white, [x1,y1,snake_block,snake_block])
        pygame.display.update()
        
        if x1 == foodX and y1 == foodY:
            message("Yummy!", red)
        
        clock.tick(snake_speed)
            
    pygame.quit
    quit()
gameLoop()
Asked By: ubersmurf

||

Answers:

  1. See How do I detect collision in pygame?. You have to test if the player rectangle collides with the food rectangle. Use pygame.Rect.colliderect to detect collision between rectangles:

  2. The message is drawn in only a single frame and is therefore barely noticeable. Assign the message text to a variable and draw the message for some time when the variable is set.

  3. You have to draw the message text before the display is updated with pygame.display.update()

def gameLoop():
    # [...]

    while not game_over:
        # [...]

        player_rect = pygame.Rect(x1,y1,snake_block,snake_block)
        food_rect = pygame.Rect(foodX, foodY, snake_block, snake_block)

        current_time = pygame.time.get_ticks()
        if player_rect.colliderect(food_rect):
            message_text = "Yummy!"
            text_end_time = current_time + 1500 # 1.5 seconds
            foodX = round(random.randrange(0, screen_width - snake_block) / 10) * 10
            foodY = round(random.randrange(0, screen_height - snake_block) / 10) * 10  
        
        screen.fill(black)
        pygame.draw.rect(screen, blue, food_rect)
        pygame.draw.rect(screen, white, player_rect)
        if message_text and current_time < text_end_time:
             message(message_text, red)
        pygame.display.update()
        
        clock.tick(snake_speed)

Answered By: Rabbid76
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.