I am making the game snake in pygame and have completed the game. I have one problem that does not happen every time, but every once in a while, it does not process the keys being pressed if I press them quickly. For instance if the apple is next to a wall and I need to turn really quickly to get it, I sometimes just run into the wall. I have clock.tick
set to 8 in order to get the slow 'jumps' that snake usually has. I'm wondering if this means it only checks if I have pressed something 8 times per second. If so, is there a way to make event checking much faster while also keeping the frame rate relatively slow?
Here is the main code:
import random
import pygame
from settings import WINDOW_SIZE, BACKGROUND_COLOR, FRAME_RATE
from snake import Snake
from apple import Apple
from high_score import high_score
# Initialize pygame and the screen and make a clock, so we can control the framerate
pygame.init()
screen = pygame.display.set_mode(WINDOW_SIZE)
clock = pygame.time.Clock()
pygame.display.set_caption("Snake")
# This is our great snake that will be doing all the work
snake = Snake()
# Our apple will never actually change. It will always be the same object
# but once they hit it, it will just register that it hit and movel locations
apple = pygame.sprite.GroupSingle(Apple())
apple.sprites()[0].place()
# If the screen should be up or not
running = True
# If we are playing or not (this will be false once the score is displayed)
playing = True
# Main game loop
while running:
# Check if the user wants to quit
for event in pygame.event.get():
# Pressing the close button the window shuts it down
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
# Pressing escape shuts it down too
if event.key == pygame.K_ESCAPE:
running = False
elif event.key == pygame.K_w or event.key == pygame.K_UP:
snake.up()
elif event.key == pygame.K_d or event.key == pygame.K_RIGHT:
snake.right()
elif event.key == pygame.K_s or event.key == pygame.K_DOWN:
snake.down()
elif event.key == pygame.K_a or event.key == pygame.K_LEFT:
snake.left()
elif event.key == pygame.K_RETURN and not playing:
snake = Snake()
apple = pygame.sprite.GroupSingle(Apple())
apple.sprites()[0].place()
playing = True
# If we are still playing, update things
if playing:
# Update the apple and then the snake (the apple may be under the snake)
apple.update()
snake.update()
# If the snake has hit the apple, add a new body part and place the apple elsewhere
if snake.body[0].rect.colliderect(apple.sprites()[0].rect):
snake.add_new_body_part()
apple.sprites()[0].place()
# If the snake is dead then we are done
if snake.is_dead():
playing = False
# Fill the background
screen.fill(BACKGROUND_COLOR)
# Draw apple
apple.draw(screen)
# Draw snake
snake.draw(screen)
# And if we are not playing we need to display a score
if not playing:
high_score_file = open("high_score.py", "w")
font = pygame.font.SysFont("feesanbolt.ttf", 100)
# If we have beaten the high score, display a happy message!
if snake.length() >= high_score:
high_score = snake.length()
high_score_text = font.render("New High Score!", True, (80, 80, 80), BACKGROUND_COLOR)
high_score_text_rect = high_score_text.get_rect()
high_score_text_rect.center = (WINDOW_SIZE.width // 2, WINDOW_SIZE.height // 4)
screen.blit(high_score_text, high_score_text_rect)
# Update high_score (if snake.length < high_score, the file won't change)
high_score_file.write(f"high_score = {high_score}")
# Display the score
score_text = font.render(str(snake.length()), True, (80, 80, 80), BACKGROUND_COLOR)
score_text_rect = score_text.get_rect()
score_text_rect.center = (WINDOW_SIZE.width // 2, WINDOW_SIZE.height // 2)
screen.blit(score_text, score_text_rect)
# Update screen
pygame.display.flip()
# We want a slow framerate so we can get the slow and discrete snake moving in jumps
clock.tick(FRAME_RATE)
pygame.quit()
I am really not sure what to do. I am new to pygame so am not sure the relationship between the events and the framerate. I tried looking for some information in the documentation and on stack overflow, but could not find anything that specifically talked about this. Any direction would be helpful. Thank you in advance!
I suggest using a higher frame rate but a timer event for the movement and update (see Do something every x (milli)seconds in pygame):
FRAME_RATE = 60
update_interval = 100 # 0.1 seconds
update_event_id = pygame.USEREVENT + 1
pygame.time.set_timer(update_event_id, update_interval)
while running:
# Check if the user wants to quit
for event in pygame.event.get():
# Pressing the close button the window shuts it down
if event.type == pygame.QUIT:
running = False
# [...]
elif event.type == update_event_id:
if playing:
# Update the apple and then the snake (the apple may be under the snake)
apple.update()
snake.update()
# [...]
clock.tick(FRAME_RATE)