gpt4 book ai didi

python - pygame贪吃蛇游戏,蛇在快速改变方向时不会移动

转载 作者:行者123 更新时间:2023-12-01 02:28:28 24 4
gpt4 key购买 nike

我刚刚使用 pygame 模块编写了一个贪吃蛇游戏。

经过测试,我发现当我快速改变蛇的方向时。例如。快速按两个方向键将蛇的 body 移动到下一行或改变到相反的方向,蛇的 react 不准确。大多数时候它会起作用,但也有少数时候蛇不动。我相信这是因为 FPS 较低,但如果我提高它,蛇会移动得很快。

代码如下:

# snake game

import pygame, sys, random, time

# game initialization
check_errors = pygame.init()

if check_errors[1] > 0:
print('(!) Got {0} errors during initializing pygame \
exiting...'.format(check_errors[1]))
sys.exit(-1)
else:
print('(+) pygame successfully initialized.')

# game screen
screen_width = 750
screen_height = 495
game_screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Snake game')

# colors
red = pygame.Color(255, 0, 0) # game over
green = pygame.Color(0, 255, 0) # snake body
black = pygame.Color(0, 0, 0) # player score
white = pygame.Color(255, 255, 255) # game background
brown = pygame.Color(165, 42, 42) # food

# FPS controller
fps_controller = pygame.time.Clock()

# game variables
start_x = 300
start_y = 150
step = 15 # block width is 10
initial_body_length = 3
snake_head = [start_x, start_y] # snake start position [x, y]
# initialize snake body, index 0 contains the snake head
snake_body = [[start_x - i * step, start_y] for i in range(initial_body_length)]
score = 0
level = 1

food_pos = [random.randrange(2, screen_width / step - 1) * step, \
random.randrange(2, screen_height / step - 1) * step] # don't put food at the border of the screen
food_spawn = True

direction = 'RIGHT'
next_direction = direction # new direction after user hits keyboard


def draw_game_menu():
count = 3
my_font = pygame.font.SysFont('monaco', 60)
while True:
game_screen.fill(white)

start_surface = my_font.render('Start in {0} seconds.'.format(count), True, black)
start_rect = start_surface.get_rect()
start_rect.midtop = (screen_width / 2, 80)
game_screen.blit(start_surface, start_rect)

esc_surface = my_font.render('''Press Esc to exit during game.''', True, black)
esc_rect = esc_surface.get_rect()
esc_rect.midtop = (screen_width / 2, 150)
game_screen.blit(esc_surface, esc_rect)

pause_surface = my_font.render('''Press Space to pause the game.''', True, black)
pause_rect = pause_surface.get_rect()
pause_rect.midtop = (screen_width / 2, 220)
game_screen.blit(pause_surface, pause_rect)

pygame.display.flip() # update the game screen
time.sleep(1)
fps_controller.tick()
count -= 1
if count == 0: break

def draw_game_pause():
my_font = pygame.font.SysFont('monaco', 40)
while True:
pause_surface = my_font.render('Press Space to continue.', True, black)
pause_rect = pause_surface.get_rect()
pause_rect.midtop = (screen_width / 2, 150)
game_screen.blit(pause_surface, pause_rect)
pygame.display.flip()
fps_controller.tick()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE: return

def show_score(game_over=False):
my_font = pygame.font.SysFont('monaco', 40)
score_surface = my_font.render('Score: {0}'.format(score), True, black)
score_rect = score_surface.get_rect()
if game_over == False:
score_rect.midtop = (75, 10)
else:
score_rect.midtop = (screen_width / 2, 130)
game_screen.blit(score_surface, score_rect)

# game over function
def draw_game_over():
my_font = pygame.font.SysFont('monaco', 60)
GO_surface = my_font.render('Game Over !', True, red)
GO_rect = GO_surface.get_rect()
GO_rect.midtop = (screen_width/2, 60)
game_screen.blit(GO_surface, GO_rect)

show_score(game_over=True)
pygame.display.flip() # update the game screen

time.sleep(4)
pygame.quit() # quit the game
sys.exit() # exit the console

def get_food(food_pos, snake_body):
for block in snake_body:
if block[0] == food_pos[0] and block[1] == food_pos[1]:
return True
return False


# game start menu
draw_game_menu()

# main logic of the game
while True:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN: # if user press any button
if event.key == pygame.K_RIGHT or event.key == ord('d'):
next_direction = 'RIGHT'
elif event.key == pygame.K_LEFT or event.key == ord('a'):
next_direction = 'LEFT'
elif event.key == pygame.K_UP or event.key == ord('w'):
next_direction = 'UP'
elif event.key == pygame.K_DOWN or event.key == ord('s'):
next_direction = 'DOWN'
elif event.key == pygame.K_ESCAPE: # if user choose to quit the game
pygame.event.post(pygame.event.Event(pygame.QUIT))
elif event.key == pygame.K_SPACE:
draw_game_pause()
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()

# validation of direction
if next_direction == 'RIGHT' and direction != 'LEFT':
direction = 'RIGHT'
elif next_direction == 'LEFT' and direction != 'RIGHT':
direction = 'LEFT'
elif next_direction == 'DOWN' and direction != 'UP':
direction = 'DOWN'
elif next_direction == 'UP' and direction != 'DOWN':
direction = 'UP'

# move snake head
if direction == 'RIGHT':
snake_head[0] += step
elif direction == 'LEFT':
snake_head[0] -= step
elif direction == 'DOWN':
snake_head[1] += step
elif direction == 'UP':
snake_head[1] -= step

# move snake body mechanism
# 1. insert a new block at the beginning of the body
# 2. check if snake has reached a food
# 2.1 if yes, then keep the modified body
# 2.2 if not, then delete the end of the body
snake_body.insert(0, list(snake_head))
if snake_head[0] == food_pos[0] and snake_head[1] == food_pos[1]:
food_spawn = False
score += 1
else:
snake_body.pop()

while food_spawn == False:
food_pos = [random.randrange(2, screen_width / step - 1) * step,
random.randrange(2, screen_height / step - 1) * step]
if get_food(food_pos, snake_body) == True:
food_spawn = False
else:
food_spawn = True

# fill game background
game_screen.fill(white)

# draw snake body
for pos in snake_body:
pygame.draw.rect(game_screen, green, pygame.Rect(pos[0], pos[1], step, step))

# draw food
pygame.draw.rect(game_screen, brown, pygame.Rect(food_pos[0], food_pos[1], step, step))

# check if snake hits the border
if (snake_head[0] > screen_width - step) or (snake_head[0] < 0) or \
(snake_head[1] > screen_height - step) or (snake_head[1] < 0):
draw_game_over()

# check if snake hits itself
for block in snake_body[1:]:
if snake_head[0] == block[0] and snake_head[1] == block[1]:
draw_game_over()

level = score//5 + 1
if level > 3:
level = 3

show_score(game_over=False)
pygame.display.flip()

if level == 1:
fps_controller.tick(8)
elif level == 2:
fps_controller.tick(10)
elif level == 3:
fps_controller.tick(12)

请帮忙看看是否有改进的方法,谢谢。

最佳答案

首先,您应该尝试使用单个主循环。

在渲染开始或结束屏幕时,您无法与窗口交互,因为没有事件循环运行。这段时间你不能移动或关闭窗口,这很烦人。也许看看here有关如何处理此问题的示例。

其次,真正使用更高的帧速率,并且不要将游戏对象的速度与帧速率联系起来。

有几种方法可以处理这个问题,一个例子是使用 event当蛇应该移动时发出信号。 Here's我为另一个问题编写的示例。

这是当前代码的简单实现:

MOVE_SNAKE = pygame.USEREVENT
pygame.time.set_timer(MOVE_SNAKE, 300)

# main logic of the game
while True:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN: # if user press any button
if event.key == pygame.K_RIGHT or event.key == ord('d'):
next_direction = 'RIGHT'
elif event.key == pygame.K_LEFT or event.key == ord('a'):
next_direction = 'LEFT'
elif event.key == pygame.K_UP or event.key == ord('w'):
next_direction = 'UP'
elif event.key == pygame.K_DOWN or event.key == ord('s'):
next_direction = 'DOWN'
elif event.key == pygame.K_ESCAPE: # if user choose to quit the game
pygame.event.post(pygame.event.Event(pygame.QUIT))
elif event.key == pygame.K_SPACE:
draw_game_pause()
elif event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == MOVE_SNAKE:
# move snake head
if direction == 'RIGHT':
snake_head[0] += step
elif direction == 'LEFT':
snake_head[0] -= step
elif direction == 'DOWN':
snake_head[1] += step
elif direction == 'UP':
snake_head[1] -= step

# move snake body mechanism
# 1. insert a new block at the beginning of the body
# 2. check if snake has reached a food
# 2.1 if yes, then keep the modified body
# 2.2 if not, then delete the end of the body
snake_body.insert(0, list(snake_head))
if snake_head[0] == food_pos[0] and snake_head[1] == food_pos[1]:
food_spawn = False
score += 1
else:
snake_body.pop()

# validation of direction
if next_direction == 'RIGHT' and direction != 'LEFT':
direction = 'RIGHT'
elif next_direction == 'LEFT' and direction != 'RIGHT':
direction = 'LEFT'
elif next_direction == 'DOWN' and direction != 'UP':
direction = 'DOWN'
elif next_direction == 'UP' and direction != 'DOWN':
direction = 'UP'



while food_spawn == False:
food_pos = [random.randrange(2, screen_width / step - 1) * step,
random.randrange(2, screen_height / step - 1) * step]
if get_food(food_pos, snake_body) == True:
food_spawn = False
else:
food_spawn = True

# fill game background
game_screen.fill(white)

# draw snake body
for pos in snake_body:
pygame.draw.rect(game_screen, green, pygame.Rect(pos[0], pos[1], step, step))

# draw food
pygame.draw.rect(game_screen, brown, pygame.Rect(food_pos[0], food_pos[1], step, step))

# check if snake hits the border
if (snake_head[0] > screen_width - step) or (snake_head[0] < 0) or \
(snake_head[1] > screen_height - step) or (snake_head[1] < 0):
draw_game_over()

# check if snake hits itself
for block in snake_body[1:]:
if snake_head[0] == block[0] and snake_head[1] == block[1]:
draw_game_over()

new_level = score//5 + 1
if new_level != level:
pygame.time.set_timer(MOVE_SNAKE, 300 / new_level)
if new_level <= 3:
level = new_level

show_score(game_over=False)
pygame.display.flip()

fps_controller.tick(60)

看看现在控制蛇的速度是多么容易:它现在每 300 毫秒移动一次。

关于python - pygame贪吃蛇游戏,蛇在快速改变方向时不会移动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47099116/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com