Why is my character ignoring the clock tick when i add the background?

76 Views Asked by At

This is what happens when i don't have a background: https://www.youtube.com/watch?v=S-bv-j8le24

this is the code:

import pygame

pygame.init()

#####Variables#####

white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
gameWindowWidth = 1280
gameWindowHeight = 720
gameRunning = True
clock = pygame.time.Clock()

###################

#####Loading#####

ninja01 = pygame.image.load("C:\\Users\Tom\Desktop\gameImages\charSprite\s_Idle__000.png")
background = pygame.image.load("C:\\Users\Tom\Desktop\gameImages\Background\DistantCity\PNG\m_image.png")

#################

#####Classes#####

class player():
    def __init__(self):
        self.playerX = gameWindowWidth * 0.2
        self.playerY = gameWindowHeight * 0.8
        self.changeOnX = 0

    def changingX(self):
        if event.type == pygame.KEYDOWN and event.key == pygame.K_RIGHT:
            self.changeOnX = 5
        if event.type == pygame.KEYDOWN and event.key == pygame.K_LEFT:
            self.changeOnX = -5
        if event.type == pygame.KEYUP and event.key == pygame.K_RIGHT:
            self.changeOnX = 0
        if event.type == pygame.KEYUP and event.key == pygame.K_LEFT:
            self.changeOnX = 0

    def move(self):
        self.playerX = self.playerX + self.changeOnX

        gameWindow.blit(ninja01, (self.playerX, self.playerY))


################

ninja = player()
gameWindow = pygame.display.set_mode((gameWindowWidth, gameWindowHeight))
pygame.display.set_caption("Platformer Game")

while gameRunning == True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            gameRunning = False


    #gameWindow.blit(background, (0, 0))
    ninja.changingX()
    ninja.move()
    pygame.display.update()
    clock.tick(144)

this is what happens when i do have a background: https://www.youtube.com/watch?v=l89zZQ_8kzg

this is the code:

import pygame

pygame.init()

#####Variables#####

white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
gameWindowWidth = 1280
gameWindowHeight = 720
gameRunning = True
clock = pygame.time.Clock()

###################

#####Loading#####

ninja01 = pygame.image.load("C:\\Users\Tom\Desktop\gameImages\charSprite\s_Idle__000.png")
background = pygame.image.load("C:\\Users\Tom\Desktop\gameImages\Background\DistantCity\PNG\m_image.png")

#################

#####Classes#####

class player():
    def __init__(self):
        self.playerX = gameWindowWidth * 0.2
        self.playerY = gameWindowHeight * 0.8
        self.changeOnX = 0

    def changingX(self):
        if event.type == pygame.KEYDOWN and event.key == pygame.K_RIGHT:
            self.changeOnX = 5
        if event.type == pygame.KEYDOWN and event.key == pygame.K_LEFT:
            self.changeOnX = -5
        if event.type == pygame.KEYUP and event.key == pygame.K_RIGHT:
            self.changeOnX = 0
        if event.type == pygame.KEYUP and event.key == pygame.K_LEFT:
            self.changeOnX = 0

    def move(self):
        self.playerX = self.playerX + self.changeOnX

        gameWindow.blit(ninja01, (self.playerX, self.playerY))


################

ninja = player()
gameWindow = pygame.display.set_mode((gameWindowWidth, gameWindowHeight))
pygame.display.set_caption("Platformer Game")

while gameRunning == True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            gameRunning = False


    gameWindow.blit(background, (0, 0))
    ninja.changingX()
    ninja.move()
    pygame.display.update()
    clock.tick(144)

The code is exactly the same appart from the fact that "gameWindow.blit(background, (0, 0))" is commented out in the first one.

My question is why is my character going so much slower when i add the background?

Also in the second one his movement speed doesn't change until i lower the clock.tick to around 30 & below.

2

There are 2 best solutions below

0
On BEST ANSWER

The timing of all of your entire game loop is being controlled by the Clock.tick method. So you are only running your input and position update code once each frame. The more sprites you have, the more it will slow down this cycle which is what you are observing when you include the background. You can separate the timing of your input and update logic from the rendering cycle and this would solve your problem. Consider the refactor I have performed below:

import pygame

pygame.init()

#####Variables#####

white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
gameWindowWidth = 1280
gameWindowHeight = 720
gameRunning = True
clock = pygame.time.Clock()

###################

#####Loading#####

ninja01 = pygame.image.load("/path/to/your/ninja/sprite")
background = pygame.image.load("/path/to/your/background/sprite")

#################

#####Classes#####

class player():
    def __init__(self):
        self.playerX = gameWindowWidth * 0.2
        self.playerY = gameWindowHeight * 0.8
        self.velocity = 0.0

    def setVelocity(self, velocity):
        self.velocity = velocity

    def update(self, dt):
        self.playerX += self.velocity * dt

    def draw(self):
        gameWindow.blit(ninja01, (self.playerX, self.playerY))


################

ninja = player()
gameWindow = pygame.display.set_mode((gameWindowWidth, gameWindowHeight))
pygame.display.set_caption("Platformer Game")

fps = 60
target_frame_time = 1.0 / fps
current_frame_time = 0.0

while gameRunning == True:
    dt = clock.tick()

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            gameRunning = False
        if event.type == pygame.KEYDOWN and event.key == pygame.K_RIGHT:
            ninja.setVelocity(1)
        if event.type == pygame.KEYDOWN and event.key == pygame.K_LEFT:
            ninja.setVelocity(-1)
        if event.type == pygame.KEYUP and event.key == pygame.K_RIGHT:
            ninja.setVelocity(0)
        if event.type == pygame.KEYUP and event.key == pygame.K_LEFT:
            ninja.setVelocity(0)

    ninja.update(dt)

    current_frame_time += dt

    if current_frame_time >= target_frame_time:
        gameWindow.blit(background, (0, 0))
        ninja.draw()

        pygame.display.flip()

        current_frame_time -= target_frame_time

When update is called on the ninja, the position is calculated using the equation:

distance = velocity * time

With these code changes, you can now achieve a consistent frame rate while your input and game update logic run continuously.

0
On

clock.tick(144) means maybe pause if the rendering speed is happening faster than 144 fps. And since that's a high enough framerate, and rendering is still taking long enough, perhaps clock.tick is returning immediately and no delay is necessary.

So when you draw in a background, the rendering certainly wont be done any faster so it would still be slow enough that clock.tick returns immediately. Except now the rendering is a little slower, so you notice the delay from the render.