简体   繁体   中英

Snake Length in a Pygame Snake Game

I have been trying to increase the length of the snake every time it moves over the apple which is working fine but as soon as snake stops moving, the length of the snake shrinks back to a single unit and I am unable to fix that.

ABOUT THE GAME

  • Snake moves only when the user presses any of the arrow keys.

Problem 2 - I have also been trying to get the snake moving on its own. That is the snake should move even when the user is not pressing any key, and the user will press keys to change the direction of the snake.

import pygame
pygame.init()
import time
import random

def gameloop():
    x_width, y_width = 500, 500
    win = pygame.display.set_mode((x_width, y_width))
    pygame.display.set_caption("Snake")

    bgcolor = white = (255, 255, 255)
    red = (255, 0, 0)
    green = (0, 255, 0)
    blue = (0, 0, 255)
    black = (0, 0, 0)

    x_cord, y_cord = x_width/2, y_width/2
    width, height = 10, 10
    x_snake_change, y_snake_change = 10,10

    apple_width = 15
    apple_height = 15

    font = pygame.font.SysFont(None, 20)
    def gameover_message(msg, color):
        text_on_screen = font.render(msg, True, color)
        win.blit(text_on_screen, [x_width/4, y_width/3])
        pygame.display.update()

    rand_apple_x = round(random.randrange(0, x_width-width)/10)*10
    rand_apple_y = round(random.randrange(0, y_width-height)/10)*10
    def apple():
        win.fill(red, rect=[rand_apple_x,rand_apple_y, apple_width, apple_height])

    snake_list=[]
    snake_length = 1

    def snake():
        if len(snake_list) > snake_length:
            del snake_list[0]
            for XnY in snake_list[:-1]:
                win.fill(black, rect=[XnY[0], XnY[1], width, height])

    run = True
    gameover = False
    while run:
        while gameover:
            gameover_message("You Have LOSE, press c to continue and Q to quit", red)
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    run = False
                    gameover = False
                key_press = pygame.key.get_pressed()
                if key_press[pygame.K_c]:
                    gameloop()
                if key_press[pygame.K_q]:
                    win.fill(white)
                    gameover_message("QUITTING", black)
                    time.sleep(1)
                    run = False
                    pygame.quit()
                    quit()

        for event in pygame.event.get():
            print(event)
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
        # Bg-Color
        win.fill(bgcolor)

        # key_press

        key_press = pygame.key.get_pressed()
        if key_press[pygame.K_DOWN]:# and y_cord < y_width - height:
            y_cord += y_snake_change
        if key_press[pygame.K_RIGHT]:# and x_cord < x_width - width:
            x_cord += x_snake_change
        if key_press[pygame.K_UP]:# and y_cord >0 :
            y_cord -= y_snake_change
        if key_press[pygame.K_LEFT]:# and x_cord > 0:
            x_cord -= x_snake_change

        if x_cord > x_width - width or x_cord < 0 or y_cord < 0 or y_cord > y_width - height:
            gameover = True


        # apple
        apple()


        #  cords apple //   Apple Funciton
        if x_cord >= rand_apple_x and x_cord<=rand_apple_x + apple_width and y_cord >= rand_apple_y  and y_cord <= rand_apple_y + apple_height  :
            rand_apple_x = round(random.randrange(0, x_width - width) / 10) * 10
            rand_apple_y = round(random.randrange(0, y_width - height) / 10) * 10
            snake_length += 1
        snake_XnY_cord = []
        snake_XnY_cord.append(x_cord)
        snake_XnY_cord.append(y_cord)
        snake_list.append(snake_XnY_cord)


        snake()

        # snake
        win.fill(black, rect=[x_cord, y_cord, width, height])

        pygame.display.update()

        time.sleep(0.05)
    pygame.quit()
    quit()
gameloop()

Both problems can be solved with the same solution.

Basically, in the game loop you would have a variable like this:

snake_direction = 'Put Direction Here'

Later in the game code, while registering key-presses, you can change this variable, for example:

if event.type == pygame.K_LEFT:
    snake_direction = 'Left'

if event.type == pygame.K_RIGHT:
    snake_direction = 'Right'

# And so on with the other directions...

Finally, near the end of the event loop, near the point where everything is drawn. You do this:

if snake_direction == 'Left':
    x_cord -= x_snake_change

elif snake_direction == 'Right':
    x_cord -= x_snake_change

# And so on with down and up...

This should allow the snake to change direction with a simple keypress, and also allow it to move indefinitely. Now that the snake doesn't stop either, the tail will not shrink back to 1 unit again either.

Skip changing the snake_list in every frame:

snake_XnY_cord = []
snake_XnY_cord.append(x_cord)
snake_XnY_cord.append(y_cord)
snake_list.append(snake_XnY_cord)

Only change the snake_list if the head of the snake has moved. Instead it has to be:

if not snake_list or snake_list[-1] != (x_cord, y_cord):
    snake_list.append((x_cord, y_cord))
snake()

But draw the entire snake in ever frame. The entire window is filled in every frame ( win.fill(bgcolor) ), so the snake has to be redrawn. Change the function snake :

def snake():
    if len(snake_list) > snake_length:
        del snake_list[0]
    for XnY in snake_list:
        win.fill(black, rect=[XnY[0], XnY[1], width, height])

If you want to move the snake on its own, then you've to store the current movement. Store the direction vector to ( move_x , move_y ) and change it when a button was pressed. Add the direction vector to the current position in every frame:

while run:
move_x, move_y = (0, 0)
while run:

    // [...]

    key_press = pygame.key.get_pressed()
    if key_press[pygame.K_DOWN]:# and y_cord < y_width - height:
        move_x, move_y = (0, y_snake_change)
    elif key_press[pygame.K_RIGHT]:# and x_cord < x_width - width:
        move_x, move_y = (x_snake_change, 0)
    elif key_press[pygame.K_UP]:# and y_cord >0 :
        move_x, move_y = (0, -y_snake_change)
    elif key_press[pygame.K_LEFT]:# and x_cord > 0:
        move_x, move_y = (-x_snake_change, 0)

    x_cord += move_x
    y_cord += move_y

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM