我正在从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()
答案 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