Reputation: 17
I'm doing tutorial for platform game but my Pygame window displays a black screen.
I don't know how to solve this.
I tried closing and opening Visual Studio Code again but nothing happens.
import pygame
SCREEN_SIZE = (700,500)
DARK_GREY = (50,50,50)
OGURKOWY = (21,179, 58)
pygame.init()
screen = pygame.display.set_mode(SCREEN_SIZE)
pygame.display.set_caption("Platformówka")
player_image = pygame.image.load("ogurek\doggo.png")
player_x = 300
platforms = [
pygame.Rect(100,300,400,50),
pygame.Rect(100,250 ,50,50),
pygame.Rect(450,250,50,50),
pygame.Rect(450,250,100,50)
]
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
if keys[pygame.K_a]:
player_x -= 2
if keys[pygame.K_a]:
player_x += 2
#tło
screen.fill(DARK_GREY)
#platformy
for p in platforms:
pygame.draw.rect(screen, (OGURKOWY), p)
#gracz
screen.blit(player_image, (player_x,100))
#
pygame.display.flip()
pygame.quit()
Upvotes: 2
Views: 227
Reputation: 9377
How to fix this apparent indentation issue was commented by Ari Cooper-Davis and answered by Rabbid76.
My answer aims to avoid such issues by design (keeping loops short and segregating nested constructs into methods).
Advice to avoid such indentation typos and improve readability of your code:
while running:
) shortfor
/if
/functions, etc.This recipe follows Single Responsibility Principle (SRP) and structures your code like your comments did. Moreover it makes the code more expressive, because method-calls will document same as comments to the reader.
def handle_exit_events():
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
def handle_key_events():
keys = pygame.key.get_pressed()
if keys[pygame.K_a]:
player_x -= 2
if keys[pygame.K_a]:
player_x += 2
def draw_background():
# tło
screen.fill(DARK_GREY)
def draw_platforms():
# platformy
for p in platforms:
pygame.draw.rect(screen, (OGURKOWY), p)
def draw_player():
# gracz
screen.blit(player_image, (player_x,100))
def update_display():
pygame.display.flip()
Note the 2 blank lines between each method definition.
Now that we declared the methods (before), we can use them to shorten the loop:
# methods declared (from above)
# inits (screen/game-objects/color definitions) omitted to focus on game-loop
running = True
while running:
handle_exit_events()
handle_key_events()
draw_background() # currently static, could move above loop
draw_platforms() # currently static, could move above loop
draw_player() # player move triggered by key-press only
update_display()
pygame.quit()
See how your original comments inside the game-loop (# platformy
, # tło
and # gracz
) were transformed to method-calls. Thus your code documents itself (making these comments obsolete).
Now we can think and recognize dependencies inside the loop. The game-loop is for interactive parts like reacting to events or updating the screen.
So the handle_x_events
methods fit well inside the loop. But some static scenery like background and platforms are fixed objects in your game. They can be drawn once before entering the game-loop. Because they don't change with any of the events (like quit or key-pressed).
# methods declared (from above)
# inits (screen/game-objects/color definitions) omitted to focus on game-loop
draw_background()
draw_platforms()
running = True
while running:
Next is more questionable and depends on your design-approach.
draw_player()
is needed once before the loop because when the game starts, the player is placed into the world. Then the player uses key-presses to change its position (see handle_key_events()
) which will trigger the player-image to be re-positioned (horizontally only, player_x
) and drawn on the screen.
You could express that dependency in code:
player_y = 100 # initial vertical position (fixed at the moment)
player_x = 300
player_x_speed = 2 # pixels delta per horizontal movement
def move_player_forward():
player_x += player_x_speed
screen.blit(player_image, (player_x, player_y))
def move_player_backward():
player_x -= player_x_speed
screen.blit(player_image, (player_x, player_y))
def handle_key_events():
keys = pygame.key.get_pressed()
if keys[pygame.K_a]:
move_player_backward()
if keys[pygame.K_a]:
move_player_forward()
# remaining code
while running:
handle_exit_events()
handle_key_events()
update_display()
pygame.quit()
See how the horizontal movement is expressed in code. The player_x
modification was internalized into the movement methods.
Usually you would work with Player
class and objects or at least player-coordinates, for example defined as tuple, which has some benefits:
player_position = (300, 100) # pixel coordinates of players initial position`
player_x_speed = 2 # pixels delta per horizontal movement
player_jump_height = 10 # pixels to jump vertically, e.g. on a platform
# walk forward
player_position[0] += player_x_speed
# jump forward
player_position = (player_position[0] + player_x_speed, player_position[1] + player_jump_height)
# directly drawn
screen.blit(player_image, player_position)
Upvotes: 0
Reputation: 210889
It is a matter of Indentation. The for
-loop that draws the platforms (for p in platforms:
) must be *in the application loop instead of after the application loop:
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
if keys[pygame.K_a]:
player_x -= 2
if keys[pygame.K_a]:
player_x += 2
#tło
screen.fill(DARK_GREY)
#platformy
# INDENTATION
#-->|
for p in platforms:
pygame.draw.rect(screen, (OGURKOWY), p)
#gracz
screen.blit(player_image, (player_x,100))
#
pygame.display.flip()
Upvotes: 1