Pygame蛇-苹果在蛇体内产卵

时间:2019-01-29 20:48:43

标签: python pygame

我正在从youtube上的thenewboston教程中学习如何在pygame中制作蛇游戏并将其制作为我自己的游戏。 游戏中存在一个问题,其中“苹果”在蛇的位置后面生成,这是我不希望的。

我确定我必须声明苹果的位置不能与蛇相同,但不能弄清楚它的位置:

# 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 :(得分:0)

这条蛇似乎是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

值得考虑的是一种更有效的方法来将点移离蛇,而不是一遍又一遍地循环。选择一个随机点可能只是选择相同的点,或者再次选择一个接近坏点的点。同样,蛇越长,循环越差,因为屏幕上的“非蛇”点更少。我猜这里有一些已知的安全区域,例如蛇刚刚移出的空间,但是这些显然不是随机的。

答案 1 :(得分:0)

在新的随机“苹果”位置创建一个矩形:

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