Python Snake教程,尾部/速度

时间:2018-05-18 01:40:07

标签: python performance variables

我正在尝试为我的蛇添加尾巴(最后使用三角形图像而不是方形填充)。虽然我认为我的代码大部分都在工作,但我看到如果我改变了方向,那么最后几秒尾巴会与身体“断开”。 (尾巴指向右侧和身体向下留下间隙)。我试图通过提高我的FPS来解决这个问题,这似乎有用;但是我希望蛇的速度与以前相同,因为我将FPS加倍,我的速度将提高1/2。然而,当我这样做时,我的碰撞检测不同步,如果我放慢速度,我的身体就会掠过我的脸,如果我加速,我会让我的身体断开(阻挡,空间,阻挡)。我尝试了几种不同的方式,所以任何帮助都会受到赞赏。

请注意block_speed = 10,如果我手动输入10就可以了,但如果我改为5或20,或者我改为值为5或20的变量(比如说速度),代码不起作用。

代码:

import pygame, sys
from pygame.locals import*
import time
import random
import os

pygame.init()

#GUI Settings
display_Width = 800
display_Height = 600
gameDisplay = pygame.display.set_mode((display_Width,display_Height))
pygame.display.set_caption("Gluttonous Snake")
gameicon = pygame.image.load('icon.png')
potatoimg = pygame.image.load('potato.png')
pygame.display.set_icon(gameicon)
FPS = 15

direction = "up"
#set path to where to .py/.exe is
abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
os.chdir(dname)
print(dname)
snakeheadimg = pygame.image.load('snakehead.png')
snaketailimg = pygame.image.load('snaketail.png')
appleimg = pygame.image.load('apple.png')

#define colors
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
yellow = (255,255,0)
eggwhite = (255,255,204)
lightgrey = (242,242,242)

#Game Variables
block_size = 10
clock = pygame.time.Clock()

def game_intro():
    intro = True

    x = 500
    y = 400
    x_dir = "left"
    while intro:
        gameDisplay.fill(eggwhite)
        gameDisplay.blit(potatoimg, (50, 25))
        message_to_screen("Potato Productions Presents...", black, -100, size=45)
        message_to_screen("Gluttonous Snake", green, -25, size=75)
        message_to_screen("A game made by a potato to run on a potato", black, 50, size=25)
        message_to_screen("Press C to Start!", red, 75, size=25)
        gameDisplay.blit(gameicon, (x, y))
        if x_dir == "left":
            if x > 0:
                x -= 10
            else:
                x_dir = "right"
        else:
            if x < 500:
                x += 10
            else:
                x_dir = "left"

        if x < 125 or x > 375:
            y -= 9.66
        else:
            y += 10


        pygame.display.update()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
                intro = False

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_c:
                    intro = False
                if event.key == pygame.K_q:
                    pygame.quit()
                    quit()


def  pickFont(name,size):
    font = pygame.font.SysFont(name, size, bold=False)
    return font
    #font size  = 25
    #font = pygame.font.SysFont("comicsansms",size=25)


def snake(snakelist):
    # faster GPU method is
    # gameDisplay.fill(red, rect=[200,200,50,50])

    if direction == "left":
        head = pygame.transform.rotate(snakeheadimg,90)
    if direction == "right":
        head = pygame.transform.rotate(snakeheadimg,270)
    if direction == "down":
        head = pygame.transform.rotate(snakeheadimg,180)
    if direction == "up":
        head = pygame.transform.rotate(snakeheadimg,0)

    gameDisplay.blit(head,(snakelist[-1][0],snakelist[-1][1]))

    #-1 because we are drawing that above
    # for XnY in snakelist[:-1]:
    #     #gameDisplay.fill(green, rect=[lead_x, lead_y, block_size, block_size])
    #     gameDisplay.fill(green, rect=[XnY[0], XnY[1], block_size, block_size])

    # -1 because we are drawing that above
    if len(snakelist) >= 2:
        for XnY in snakelist[1:-1]:
            gameDisplay.fill(green, rect=[XnY[0], XnY[1], block_size, block_size])
        if direction == "up":
            tail = pygame.transform.rotate(snaketailimg, 180)

        if snakelist[1][0] > snakelist[0][0]:
            tail = pygame.transform.rotate(snaketailimg, 90)
        elif snakelist[1][0] < snakelist[0][0]:
            tail = pygame.transform.rotate(snaketailimg, 270)
        elif snakelist[1][1] > snakelist[0][1]:
            tail = pygame.transform.rotate(snaketailimg, 0)
        elif snakelist[1][1] < snakelist[0][1]:
            tail = pygame.transform.rotate(snaketailimg, 180)
        gameDisplay.blit(tail, (snakelist[-len(snakelist)][0], snakelist[-len(snakelist)][1]))

def text_objects(text, color,size):
    font = pickFont("comicsansms", size)
    textSurface = font.render(text,True,color,size)
    return textSurface, textSurface.get_rect()

def message_to_screen(msg,color,y_displace=0, size=25):
    #True is anti-aliasing
    textSurf, textRect = text_objects(msg, color, size)
    textRect.center = (display_Width/2),(display_Height/2) + y_displace
    gameDisplay.blit(textSurf,textRect)

def gameLoop():
    # set up variables
    global direction
    gameExit = False
    gameOver = False
    lead_x = display_Width / 2
    lead_y = display_Height / 2

    coinflip = random.randint(0, 1)
    if coinflip == 0:
        coinflip = random.randint(0, 1)
        if coinflip == 0:
            lead_x_change = **10**
            lead_y_change = 0
            direction = "right"
        else:
            lead_x_change = -**10**
            lead_y_change = 0
            direction = "left"
    else:
        coinflip = random.randint(0, 1)
        if coinflip == 0:
            lead_x_change = 0
            lead_y_change = **10**
            direction = "down"
        else:
            lead_x_change = 0
            lead_y_change = -**10**
            direction = "up"

    #lead_x_change = 0
    #lead_y_change = 0
    #the 10 is round to 10
    randAppleX = random.randrange(0, display_Width - block_size, 10)
    randAppleY = random.randrange(0, display_Height - block_size, 10)
    snakelist = []
    snakelength = 1

    while not gameExit:

        while gameOver == True:
            gameDisplay.fill(white)
            #message_to_screen("Game over \n Press C to play again or Q to quit", red)
            message_to_screen("Game Over", red, y_displace=-50, size=75)
            message_to_screen("Press C to play again or Q to quit",black,y_displace=50,size=25)
            pygame.display.update()
            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_q:
                        gameExit = True
                        gameOver = False

                    if event.key == pygame.K_c:
                        gameLoop()
                        #gameOver = False



        for event in pygame.event.get():
            #shows every mouse move and key pressed
            #print(event)
            if event.type == pygame.QUIT:
                gameExit = True
                gameOver = False

            #check for single depress of keys
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    #lead_x -= 10
                    #this is so they can't back over themselves
                    if lead_x_change != **block_size**:
                        lead_x_change = - **block_size**
                        lead_y_change = 0
                        direction = "left"
                #elif is only tested if the ifs and elifs above it are not true
                elif event.key == pygame.K_RIGHT:
                    #lead_x += 10
                    if lead_x_change != -**block_size**:
                        lead_x_change = **block_size**
                        lead_y_change = 0
                        direction = "right"
                elif event.key == pygame.K_UP:
                    if lead_y_change != **block_size**:
                        lead_x_change = 0
                        lead_y_change = -**block_size**
                        direction = "up"
                elif event.key == pygame.K_DOWN:
                    if lead_y_change != -**block_size**:
                        lead_x_change = 0
                        lead_y_change = **block_size**
                        direction = "down"

            # user releases key
            # if event.type == pygame.KEYUP:
                # if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                   # lead_x_change = 0

        #Ends the game once the square has left the window
        if lead_x >= (display_Width - block_size) or lead_x <= 0 or lead_y >= (display_Height - block_size)  or lead_y <= 0:
            print("snake left at " + str(lead_x)+","+str(lead_y))
            lead_x_change = 0
            lead_y_change = 0
            gameOver = True



        lead_x += lead_x_change
        lead_y += lead_y_change

        gameDisplay.fill(lightgrey)



        snakehead = []
        snakehead.append(lead_x)
        snakehead.append(lead_y)
        snakelist.append(snakehead)

        if len(snakelist) > snakelength:
            del snakelist[0]

        #-1 because last element is the head
        for eachSegement in snakelist[:-1]:
            if eachSegement == snakehead:
                print("snake eats itself")
                gameOver = True

        #draw snake first so if apple spawns on it I can still see it
        snake(snakelist)

        #gameDisplay.fill(red, rect=[randAppleX, randAppleY, block_size, block_size])
        gameDisplay.blit(appleimg,(randAppleX, randAppleY))

        pygame.display.update()

        #better collison detection as part of the snake can go over part of the apple
        # if lead_x >= randAppleX and lead_x + block_size < randAppleX + block_size or lead_x + block_size  >= randAppleX and lead_x + block_size < randAppleX + block_size:
        #     if lead_y >= randAppleY and lead_y < randAppleY + block_size or lead_y + block_size >= randAppleY and lead_y + block_size < randAppleY + block_size:
        if lead_x >= randAppleX:
            if lead_x + block_size <= randAppleX + block_size:
                if lead_y >= randAppleY:
                    if lead_y + block_size <= randAppleY + block_size:
                        print("nom nom nom")
                        randAppleX = random.randrange(0, display_Width - block_size, 10)
                        randAppleY = random.randrange(0, display_Height - block_size, 10)
                        snakelength += 1

        #used to make FPS
        clock.tick(FPS)

    pygame.quit()
    quit()

game_intro()
gameLoop()

回复提供的答案:

非常感谢我会调查此事。你能弄清楚为什么我不能调整速度吗?如果我减慢速度,它会将身体吸过头部似乎很奇怪,或者如果我加快它会留下空隙。部分是我正在调整速度是粗体

1 个答案:

答案 0 :(得分:0)

您可以通过执行以下操作来平滑一些事情(并使代码更清晰):

1 - 存储尾部(头部)旋转图像:

tail_left = pygame.transform.rotate(snaketailimg, 180)   # choose appropriate rotation
tail_right = ...
tail_up = ...
tail_down = ...

2 - 确定蛇走向哪个方向,并从字典中查找图像(例如)

tail_oriented_images = {'left': tail_left, 'right': tail_right, ...}
...
tail_direction = get_tail_direction()   # to be extracted

3-然后将snake(snakelist)中的if cascade替换为:

tail = tail_oriented_images[tail_direction]

4-为头部方向做同样的事情