Skip to content
Advertisement

Pygame window isn’t updating

I’m writing a small python game just to learn how to use python better. I wanted to try to start using multiple scripts, as keeping all of the code in one script can get a little crowded. I made a second script, created a function main(scrn) and everything seems to be working fine. Calling that function in my main script, game.py, it will create the screen and everything in the main(scrn) function will show up. However, nothing will update. My character won’t move at all, with my previously tested gravity controller, or left or right. I tried moving the character controller from the hi.py script (main(scrn)) to the while Running: function, but still no movement. I then tried moving the main(scrn) function back to my original script, but it still won’t work. Nothing seems to be updating. This is the combined script, last one mentioned in description

import pygame
from pygame.locals import *

pygame.init()
SIZE = 800, 600
screen = pygame.display.set_mode(SIZE)
def main(scrn):
#VARIABLES
    RED = (255, 0, 0)
    GRAY = (150, 150, 150)
    DGRAY = (75, 75, 75)
    rx = 0
    ry = 450
    x = 50
    y = 50
    grounded = False
    grv = 0
    acc = .1
    ground = Rect(rx, ry, 200, 800)
    ch = Rect(x, y, 50, 50)

#INPUT MOVEMENT
    pressed = pygame.key.get_pressed()

    if pressed[pygame.K_RIGHT]:
        x += 3
    if pressed[pygame.K_LEFT]:
        x -= 3
    if pressed[pygame.K_UP] and grounded:
        for z in range(1):
            grv = -5
            grounded = False

#GRAVITY
    self = ch
    if ch.colliderect(ground):
        grounded = True
    if not grounded:
        acc = .1
        y += grv 
        grv += acc
    if grounded:
        y = 400
        acc = 0
    if y > 600:
        return False

#UPDATE
    scrn.fill(GRAY)
    pygame.draw.rect(scrn, DGRAY, ground)
    pygame.draw.rect(scrn, RED, ch)
    pygame.display.update()

#RUNNING
running = True
while running:
    for event in pygame.event.get():
        if event.type == QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                running = False
            if event.key == pygame.K_r and main:
                main
    main(screen)
pygame.quit()

Advertisement

Answer

Actually, the update of the window works fine. However, the variables are initialized in each frame.

You must initialize the variables before the application loop, but change the variables in the loop. Since you use a function, you have to initialize the variables in global name space. You have to use the global statement to be interpret the variable as global variable and to change them within a function.

def main(scrn):
    global x, y, grounded, rx, ry, grv, acc

    # [...]

Create the pygame.Rect objects after you have changed the variables x and y, but before the collision test:

def main(scrn):
    # [...]

    pressed = pygame.key.get_pressed()
    if pressed[pygame.K_RIGHT]:
        x += 3
    if pressed[pygame.K_LEFT]:
        x -= 3
    # [...]
    
    ground = Rect(rx, ry, 200, 800)
    ch = Rect(x, y, 50, 50)
    if ch.colliderect(ground):
        # [...]

You can use a init_varaibles function to initialize the variables. Call this function again if you want to reset the variables and restart the game.

def init_varaibles():
    global x, y, grounded, rx, ry, grv, acc
    rx = 0
    ry = 450
    x = 50
    y = 50
    grounded = False
    grv = 0
    acc = .2

Use pygame.time.Clock to control the frames per second and thus the game speed.

The method tick() of a pygame.time.Clock object, delays the game in that way, that every iteration of the loop consumes the same period of time. See pygame.time.Clock.tick():

This method should be called once per frame.

That means that the loop:

clock = pygame.time.Clock()
running = True
while running:
   clock.tick(100)

runs 100 times per second.


Complete example:

import pygame
from pygame.locals import *

pygame.init()
SIZE = 800, 600
screen = pygame.display.set_mode(SIZE)
clock = pygame.time.Clock()

RED = (255, 0, 0)
GRAY = (150, 150, 150)
DGRAY = (75, 75, 75)

def init_varaibles():
    global x, y, grounded, rx, ry, grv, acc
    rx = 0
    ry = 450
    x = 50
    y = 50
    grounded = False
    grv = 0
    acc = .2

def main(scrn):
    global x, y, grounded, rx, ry, grv, acc

    pressed = pygame.key.get_pressed()
    if pressed[pygame.K_RIGHT]:
        x += 3
    if pressed[pygame.K_LEFT]:
        x -= 3
    if pressed[pygame.K_UP] and grounded:
        grv = -5
        grounded = False

    y += grv 
    grv += acc
    
    ground = Rect(rx, ry, 200, 800)
    ch = Rect(x, y, 50, 50)
    if ch.colliderect(ground):
        grounded = True
        ch.bottom = ground.top
        grv = 0
        y = ch.y

    scrn.fill(GRAY)
    pygame.draw.rect(scrn, DGRAY, ground)
    pygame.draw.rect(scrn, RED, ch)
    pygame.display.update()

    return y > 600

init_varaibles()

running = True
while running:
    clock.tick(100)
    for event in pygame.event.get():
        if event.type == QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                running = False
            if event.key == pygame.K_r and main:
                init_varaibles()
    
    game_over = main(screen)
    if game_over:
        break

pygame.quit()
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement