私はちょうどpygameモジュールを使ってスネークゲームを書いた。pygame snake game、急速に方向を変えるとスネークが動かない
テストの後、私は急速にスネークの方向を変えたときにそれを見つけました。例えば。 2つの矢印キーを非常に速く押すと、ヘビ本体が次の行に移動したり、反対方向に移動したりすると、ヘビは正確に反応しません。たいていの場合、動作しますが、ヘビが動かないことはほとんどありません。私はこれが低い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)
、感謝を改善する方法があるかどうかを確認するために助けてください:ここでは
はコードがあります。
貴重なご意見ありがとうございました。それは問題を解決することができます。あなたが私に示したあなたの別の投稿[link](https://stackoverflow.com/a/14727074/142637)を見て、私は自分のプログラムを変更するためにステートマシンアプローチを使用しようとしました。しかし、私は新しい質問を見つけました。 – cyz1996
貴重な提案をありがとうございました。それは問題を解決することができます。あなたが私に示したあなたの別の投稿[link](https://stackoverflow.com/a/14727074/142637)を見て、私は自分のプログラムを変更するためにステートマシンアプローチを使用しようとしました。しかし、handle_event()メソッドでは実際に状態を初期化するので、新しい質問が見つかりました。私の問題は、GamePlayを続行するための一時停止から、設定が初期化されることでした。一時停止状態でゲームの現在の状態を「覚えている」ようにすることは非常にありますか? – cyz1996