Pygame Snake - Яблоко, порождающееся внутри змеи - PullRequest
0 голосов
/ 29 января 2019

Я учусь делать игру про змейку в pygame из обучающих программ по youtube на thenewboston и сделать ее своей.В игре есть проблема, когда за позицией змеи появляется «яблоко», чего я не хочу.

Я уверен, что должен заявить, что позиция яблока не может совпадать с позицией яблока.змея, но не может понять, как:

# Snake eating the apple
if snake_x_pos == apple_x and snake_y_pos == apple_y:
      pygame.mixer.Sound.play(eat_apple_sound)
      snakelength += 1
      apple_x = random.randrange(box_size, field_x, box_size)
      apple_y = random.randrange(box_size, field_y, box_size)

Полный код:

import pygame
import random

pygame.init()

# Game Title
pygame.display.set_caption("Original Snake")

# Game display 4:3
screen_w = 640
screen_h = 480
surface = pygame.display.set_mode((screen_w, screen_h))
bg_color = (170, 204, 102)
box_color = (43, 51, 26)
box_size = screen_h / 24

# PLAYING FIELD
field_x = screen_w - (box_size*2)
field_y = screen_h - (box_size*2)

# Frames per Second
clock = pygame.time.Clock()
FPS = 8

# Font settings
kongtext = "C:\Windows\Fonts\kongtext.ttf"
verysmall = pygame.font.Font(kongtext, 12)
small = pygame.font.Font(kongtext, 15)
medium = pygame.font.Font(kongtext, 30)
large = pygame.font.Font(kongtext, 60)
verylarge = pygame.font.Font(kongtext, 80)

# sound settings
game_over_sound = pygame.mixer.Sound("sounds/game_over.wav")
eat_apple_sound = pygame.mixer.Sound("sounds/eat_apple.wav")


def snake(box_size, snakelist):
    for XnY in snakelist:
        pygame.draw.rect(surface, box_color, [XnY[0], XnY[1], box_size, box_size])


# Text Object
def text_objects(text, color, size):
    if size == "small":
        text_surface = small.render(text, True, color)
    elif size == "verysmall":
        text_surface = verysmall.render(text, True, color)
    elif size == "medium":
        text_surface = medium.render(text, True, color)
    elif size == "large":
        text_surface = large.render(text, True, color)
    elif size == "verylarge":
        text_surface = large.render(text, True, color)
    return text_surface, text_surface.get_rect()


# Start screen
def start_screen():
    intro = True
    while intro:
        # IF USER CLICKS ON THE X
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

            # Start Game
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    intro = False

        surface.fill(bg_color)

        # SCREEN FIELD WITH BORDER 3
        pygame.draw.rect(surface, box_color, [16, 16, screen_w-33, screen_h-33-box_size], 3)

        # START SCREEN
        message_to_screen("SNAKE", box_color, -25, size="verylarge")
        message_to_screen("PRESS SPACE TO PLAY", box_color, 35, size="verysmall")
        pygame.display.update()
        clock.tick(15)


# Message to screen
def message_to_screen(msg, color, text_y_pos=0, size="small"):
    text_surf, text_rect = text_objects(msg, color, size)
    text_rect.center = (screen_w / 2), (screen_h / 2)+text_y_pos
    surface.blit(text_surf, text_rect)


def score(score):
    text = small.render("Score: "+str((score*10)-20), True, box_color)
    surface.blit(text, [box_size, screen_h-box_size-7])


def game_loop():
    direction = "right"
    quit_game = False
    game_over = False

    # Box settings
    box_color = (43, 51, 26)

    # Defining snake position
    snakelist = []
    snakelength = 3
    snake_x_pos = screen_w / 2
    snake_y_pos= screen_h / 2
    snake_x_chg = box_size
    snake_y_chg = 0

    # Randomizing the apple position
    apple_x = random.randrange(box_size, field_x, box_size)
    apple_y = random.randrange(box_size, field_y, box_size)

    while not quit_game:
        # Game Over
        while game_over:
            surface.fill(bg_color)
            message_to_screen("GAME OVER", box_color, -10, size="large")
            message_to_screen("PRESS SPACE TO PLAY AGAIN OR Q TO QUIT", box_color, 50, size="small")

            # PLAYING FIELD
            pygame.draw.rect(surface, box_color,
                             [16, 16, screen_w - 33, screen_h - 33 - box_size], 3)

            # SCORE
            score(snakelength - 1)

            pygame.display.update()

            # Closing Game Over screen with X
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    quit_game = True
                    game_over = False

                # Closing Game Over screen with Q or Restart with space
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_a:
                        quit_game = True
                        game_over = False
                    if event.key == pygame.K_SPACE:
                        direction = "right"
                        game_loop()

        for event in pygame.event.get():
            # Closing the game
            if event.type == pygame.QUIT:
                quit_game = True
                game_over = False
            # Controlling the snake
            if event.type == pygame.KEYDOWN:
                if (event.key == pygame.K_LEFT) and direction != "right":
                    snake_x_chg = -box_size
                    snake_y_chg = 0
                    direction = "left"
                elif (event.key == pygame.K_RIGHT) and direction != "left":
                    snake_x_chg = box_size
                    snake_y_chg = 0
                    direction = "right"
                elif (event.key == pygame.K_UP) and direction != "down":
                    snake_y_chg = -box_size
                    snake_x_chg = 0
                    direction = "up"
                elif (event.key == pygame.K_DOWN) and direction != "up":
                    snake_y_chg = box_size
                    snake_x_chg = 0
                    direction = "down"

        # Screen boundaries
        if snake_x_pos > (field_x) or snake_x_pos < box_size or snake_y_pos > (field_y) or snake_y_pos < box_size:
            pygame.mixer.Sound.play(game_over_sound)
            game_over = True

        # Snake new position
        snake_x_pos += snake_x_chg
        snake_y_pos += snake_y_chg

        # Clear screen
        surface.fill(bg_color)

        # Draw and update
        pygame.draw.rect(surface, box_color, [apple_x, apple_y, box_size, box_size])
        snakehead = []
        snakehead.append(snake_x_pos)
        snakehead.append(snake_y_pos)
        snakelist.append(snakehead)

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

        for snaketail in snakelist[:-1]:
            if snaketail == snakehead:
                pygame.mixer.Sound.play(game_over_sound)
                game_over = True

        snake(box_size, snakelist)

        # PLAYING FIELD
        pygame.draw.rect(surface, box_color, [16, 16, screen_w-33, screen_h-33-box_size], 3)

        # SCORE
        score(snakelength-1)

        pygame.display.update()

        # Snake eating the apple
        if snake_x_pos == apple_x and snake_y_pos == apple_y:
            pygame.mixer.Sound.play(eat_apple_sound)
            snakelength += 1
            apple_x = random.randrange(box_size, field_x, box_size)
            apple_y = random.randrange(box_size, field_y, box_size)

        clock.tick(FPS)

    pygame.quit()
    quit()


start_screen()
game_loop()

Ответы [ 2 ]

0 голосов
/ 31 января 2019

Создайте прямоугольник в новой случайной «яблочной» позиции:

apple_rect = pygame.Rect(apple_x, apple_y, box_size, box_size)

Проверьте для каждой позиции (pos) в snakelist, сталкивается ли «яблочный» прямоугольник с частью змеина pygame.Rect.collidepoint:

apple_rect.collidepoint(*pos)

Используйте any(), чтобы проверить, сталкивается ли яблоко с какой-либо частью змеи:

any(apple_rect.collidepoint(*pos) for pos in snakelist)

Если яблоко «сталкивается» со змеей, создайте новую случайную точку и повторите процесс:

# Snake eating the apple
if snake_x_pos == apple_x and snake_y_pos == apple_y:
    pygame.mixer.Sound.play(eat_apple_sound)
    snakelength += 1
    while True:
        apple_x, apple_y = (random.randrange(box_size, fs, box_size) for fs in (field_x, field_y))
        apple_rect = pygame.Rect(apple_x, apple_y, box_size, box_size)
        if not any(apple_rect.collidepoint(*pos) for pos in snakelist): 
            break
0 голосов
/ 30 января 2019

Змея кажется списком «ящиков», содержащихся в списке snakelist.Таким образом, чтобы убедиться, что яблоко не появляется внутри частей змеи, необходимо создать сгенерированную случайную точку вне ящиков змеи.

Простой (но неэффективный) способ сделать это - продолжать генерировать случайные точки.и проверяя их на столкновение.

collision = True
while collision == True:
    # Randomizing the apple position
    apple_x = random.randrange(box_size, field_x, box_size)
    apple_y = random.randrange(box_size, field_y, box_size)
    # Check apple not within snake
    collision = False
    for XnY in snakelist:
        part = pygame.Rect( XnY[0], XnY[1], box_size, box_size )
        # is the apple-point within the snake part?
        if part.collidepoint( apple_x, apple_y ) == True:
            collision = True
            break  # any collision is final, stop checking

Стоит подумать о более эффективном способе отодвинуть точку от змеи, а не повторять петли снова и снова.Выбор случайной точки может просто выбрать ту же самую точку или близкую плохую точку снова.Кроме того, чем дольше становится змея, тем хуже будет этот цикл, поскольку на экране будет меньше «не змеиных» точек.Я предполагаю, что есть некоторые известные безопасные места, такие как пространство, из которого только что вышла змея, но они, очевидно, не случайны.

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