Remaking snake, cant make more segments

2019-07-26 10:19发布

问题:

I am re-making snake in pygame and I need to make it longer. I have made a piece of code that moves a 2nd segment of the snake when I have eaten an apple:

if sa == 2:
    pygame.draw.rect(screen, GREEN, pygame.Rect(sx,sy,tilesize,tilesize))

and at the top of the 'game loop' i have:

sx = x
sy = y

I want to add more segments but have no idea how I would do this without having to make a function for every possible segment. I want a code that either tells every new segment where to go or if someone has a better idea (which I'm sure they do) pls post that instead


here is my code so far:

import pygame, sys, random
from pygame.locals import *
pygame.init()
movement_x = movement_y = 0
RED = (240, 0, 0)
GREEN = (0, 255, 0)
ran = [0,25,50,75,100,125,150,175,200,225,250,275,300,325,350,375,400,425,450,475,500]
ax = 0
ay = 0
x = 0
y = 0
sa = 0
sizex = 500
sizey = 500
tilesize = 25
screen = pygame.display.set_mode((sizex,sizey))
pygame.display.set_caption('Snake')
pygame.display.set_icon(pygame.image.load('images/tile.png'))
tile = pygame.image.load('images/tile.png')
tile = pygame.transform.scale(tile, (tilesize, tilesize))
x2 = 0
pag = 0
clock = pygame.time.Clock()
sx = 0
sy = 0
vel_x = 0
vel_y = 0
ap = True
while True:
    sx = x
    sy = y
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
    for row in range(sizex):
        for column in range(sizey):
            screen.blit(tile,(column*tilesize, row*tilesize,tilesize,tilesize))
    for event in pygame.event.get():
        if event.type == KEYDOWN:
            if event.key == K_UP:
                vel_y = -25
                vel_x = 0
            elif event.key == K_DOWN:
                vel_y = 25
                vel_x = 0
            elif event.key == K_LEFT:
                vel_x = - 25
                vel_y = 0
            elif event.key == K_RIGHT:
                vel_x= 25
                vel_y = 0
            elif event.key == K_y:
                pag = 1
            elif event.key == K_n:
                pag = 2


    inBounds = pygame.Rect(0, 0, sizex, sizey).collidepoint(x+vel_x, y+vel_y)
    if inBounds:
        y += vel_y
        x += vel_x
    else:
        basicFont = pygame.font.SysFont(None, 48)
        text = basicFont.render('Game Over! Play again? y/n', True, GREEN, RED)
        textRect = text.get_rect()
        textRect.centerx = screen.get_rect().centerx
        textRect.centery = screen.get_rect().centery
        pygame.draw.rect(screen, RED, (textRect.left - 20, textRect.top - 20, textRect.width + 40, textRect.height + 40))
        screen.blit(text, textRect)
        ay = -25
        ax = -25
        x = -25
        y = -25
        if pag == 1:
            pag = 0
            inBounds = True
            x = 0
            y = 0
            vel_x = 0
            vel_y = 0
            ax = random.choice(ran)
            ay = random.choice(ran)
            pygame.draw.rect(screen, RED, pygame.Rect(ax,ay,tilesize,tilesize))
        if pag == 2:
            pygame.quit()
            sys.exit()

    if ap:
        pygame.draw.rect(screen, RED, pygame.Rect(ax,ay,tilesize,tilesize))
    if x == ax and y == ay:
        pygame.draw.rect(screen, RED, pygame.Rect(ax,ay,tilesize,tilesize))
        ax = random.choice(ran)
        ay = random.choice(ran)
        sa += 1
    if sa == 2:
        pygame.draw.rect(screen, GREEN, pygame.Rect(sx,sy,tilesize,tilesize))
    pygame.draw.rect(screen, GREEN, pygame.Rect(x,y,tilesize,tilesize))
    pygame.display.update()
    clock.tick(100)

回答1:

Think of how a worm moves, it picks up it's head, then ripples a change in movement down throughout the entire body. Each body segment moves to the position of the previous segment.

Your "snake" is basically a list of rectangles + position. When the snake head moves, the 2nd body rectangle moves into the space the head occupied before the move. The 3nd part moves into the space from the 2nd, 4th into 3rd, etc. etc.

One way to handle this, is to keep all the "snake parts" in a list, and loop through the entries, changing the positions in-turn. Decide which way the head has moved, then starting from the tail, move each segment to the location of the previous segment.

This leads us to a simple function:

snake_parts = []   # /N/ Pygame rects 

def slither( new_head_coord ):
    # Move each body part to the location of the previous part
    # So we iterate over the tail-parts in reverse
    for i in range( len( snake_parts )-1, 0, -1 ):
        x, y = snake_parts[i-1].centerx, snake_parts[i-1].centery
        snake_parts[i].center = ( x, y )
    # Move the head
    snake_parts[0].centre = new_head_coord


回答2:

As a comment said, making a snake class is a good idea to group your functionality for the snake.

To represent the snake, you need to think of a data structure to hold it. You could represent it as an array of points. For each tick of your game loop, you could append a new point at the end of the array, and you remove the first point. This represents your snake's movement. The new point would be the "head" (which is the last point in the array), and would be placed at the current head's location + 1 in whatever direction you're going.

To draw your snake, just loop over your points array and draw a square at every point.



标签: python pygame