Python Snake Tutorial, Хвост / Скорость - PullRequest
0 голосов
/ 18 мая 2018

Я пытаюсь добавить хвост моей змеи (в самом конце используйте изображение треугольника, а не квадратную заливку).Хотя я думаю, что код по большей части работал, я видел, что если я поменяю направление, последние несколько секунд хвост «отсоединится» от тела.(хвост указывает вправо, а тело, спускающееся вниз, оставляет зазор).Я попытался исправить это, подняв свой FPS, который, казалось, работал;однако я хотел, чтобы скорость змеи была такой же, как и раньше, и, поскольку я удвоил FPS, мне пришлось бы вдвое увеличить скорость.Однако, когда я сделал это, мое обнаружение столкновений было не синхронизировано, и если бы я замедлил его, мое тело притянулось бы к моему лицу, и если я ускорился бы, мое тело было бы отключено (блок, пространство, блок).Я пробовал несколько разных способов, поэтому любая помощь будет оценена.

Обратите внимание, что 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 голосов
/ 18 мая 2018

Вы, вероятно, можете немного сгладить вещи (и сделать ваш код более понятным), выполнив следующее:

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-, затем замените каскад if в snake(snakelist) на:

tail = tail_oriented_images[tail_direction]

4- Сделайте то же самое для направления головы

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...