I'm trying out Pygame and started with a classic, creating the Snake game, the issue is that I try to blit the 'apple' on the board but the apple doesn't appear up until I crash in the walls this is when I set fps = 0 and I freeze the game. I've noticed that when I increase the fps to something like 100 or more the apple starts appearing and disappearing.
import random
import pygame
class Game:
def __init__(self):
pygame.init()
self.board = pygame.display.set_mode((400, 400))
self.apple = Apple(self.board)
self.snake = Snake(self.board, self)
self.direction = 'right'
self.going = True
self.fps = 5
def play(self):
clock = pygame.time.Clock()
while self.going:
clock.tick(self.fps)
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.going = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
self.direction = 'left'
if event.key == pygame.K_RIGHT:
self.direction = 'right'
if event.key == pygame.K_UP:
self.direction = 'up'
if event.key == pygame.K_DOWN:
self.direction = 'down'
self.apple.spawn()
self.snake.move(self.direction)
def game_over(self):
self.fps = 0
def get_fps(self):
return self.fps
class Snake:
def __init__(self, board, game):
self.board = board
self.image = pygame.Surface((10, 10))
self.game = game
self.length = 5
self.x = [10] * self.length
self.y = [10] * self.length
def move(self, direction):
for i in range(self.length-1, 0, -1):
self.x[i] = self.x[i-1]
self.y[i] = self.y[i-1]
if direction == 'right':
self.x[0] += 10
if direction == 'left':
self.x[0] -= 10
if direction == 'up':
self.y[0] -= 10
if direction == 'down':
self.y[0] += 10
if self.x[0] == self.board.get_width() or self.x[0] == -10 or\
self.y[0] == self.board.get_height() or self.y[0] == -10:
self.game.game_over()
if self.game.get_fps() != 0:
self.draw()
def draw(self):
self.board.fill((0, 255, 0))
for i in range(self.length):
self.board.blit(self.image, (self.x[i], self.y[i]))
pygame.display.flip()
class Apple:
def __init__(self, board):
self.board = board
self.image = pygame.Surface((10, 10))
self.image.fill(pygame.color.Color('red'))
self.x = random.randint(0, self.board.get_width())
self.y = random.randint(0, self.board.get_height())
def spawn(self):
self.board.blit(self.image, (self.x, self.y))
pygame.display.flip()
if __name__ == '__main__':
game = Game()
game.play()
Clear the display at the begin of the application loop and update the dispaly at the end of the application loop:
class Game:
# [...]
def play(self):
clock = pygame.time.Clock()
while self.going:
clock.tick(self.fps)
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.going = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
self.direction = 'left'
if event.key == pygame.K_RIGHT:
self.direction = 'right'
if event.key == pygame.K_UP:
self.direction = 'up'
if event.key == pygame.K_DOWN:
self.direction = 'down'
self.board.fill((0, 255, 0)) # <---
self.apple.spawn()
self.snake.move(self.direction)
pygame.display.flip() # <---
class Snake:
# [...]
def draw(self):
# self.board.fill((0, 255, 0)) <-- DELETE
for i in range(self.length):
self.board.blit(self.image, (self.x[i], self.y[i]))
# pygame.display.flip() <-- DELETE
class Apple:
# [...]
def spawn(self):
self.board.blit(self.image, (self.x, self.y))
#pygame.display.flip() <-- DELETE
fill
clears the entire Surface. Everything that was previously drawn is lost.
One update of the display at the end of the application loop is sufficient. Multiple calls to pygame.display.update()
or pygame.display.flip()
cause flickering.