Luke Redwine
Luke Redwine

Reputation: 83

Pygame sprite is too slow

I've been working on a game lately in Pygame. It loads in two different backgrounds (for parallax scrolling in the future) and then ads in a sprite that can be controlled with arrow keys and can jump and move left and right. It all loads in fine when I run it until I try to control the sprite. It responds slowly and I have to keep re-pressing the arrow keys to make it move. The code I used to make the sprite move is the same that I've used before in another program that simply loaded in the background and the sprite and controlled the sprite's movement. For my new program, I just added screen resize and fullscreen options. That is when it became slow. What is slowing it down? Do I need to better optimize my code?

If this helps, I also noticed that when I rapidly hit another key along with my arrow keys it moves it at the right speed. It is like this updates it. Is some kind of updating possibly what needs to be done? Also, I've already used "Pygame.display.update()" in my if statement for sprite key control.


import pygame
from pygame.locals import *

pygame.init()

#two backgrounds
bg = pygame.image.load('/Users/luke.redwine/Documents/Python/PyGame/Llama game/Llama imaging/backgrounds concepts/Mountains/PPP_BG1.png')
fg = pygame.image.load('/Users/luke.redwine/Documents/Python/PyGame/Llama game/Llama imaging/backgrounds concepts/Mountains/PPP_fg1.png')

clock = pygame.time.Clock()

def Sresize():
    #screen resize:
    pygame.event.pump()                                                                 

    event=pygame.event.wait()                                                            

    if event.type==QUIT:
        pygame.quit()                                              

    elif event.type==VIDEORESIZE:                                                           
        sprite.screen=pygame.display.set_mode(event.dict['size'],HWSURFACE|DOUBLEBUF|RESIZABLE)
        sprite.screen.blit(pygame.transform.scale(bg,event.dict['size']),(0,0))
        sprite.screen.blit(pygame.transform.scale(fg,event.dict['size']),(0,0))
        pygame.display.update()


#PLAYER CLASS

class player(object):
    def __init__(self,x, y, width, height):     
        self.x = x                                   
        self.y = y                          
        self.width = width                            
        self.height = height                          
        self.velocity = 15
        self.isJump = False
        self.jumpCount = 7
        self.right = False
        self.left = False
        self.walkCount = 0
        self.screen = pygame.display.set_mode((1280, 800), HWSURFACE|DOUBLEBUF|RESIZABLE)
        self.walkRight = [pygame.image.load('/Users/luke.redwine/Documents/Python/PyGame/Examples/sprite-Game/sprite characters main/R %s.png' % frame) for frame in range(1, 9)]
        self.walkLeft = [pygame.image.load('/Users/luke.redwine/Documents/Python/PyGame/Examples/sprite-Game/sprite characters main/L %s.png' % frame) for frame in range(14, 21)]
        self.char = pygame.image.load('/Users/luke.redwine/Documents/Python/PyGame/Examples/sprite-Game/sprite characters main/character 25.png')


    def draw(self, screen):                         

        if self.walkCount + 1 >= 8:  
            self.walkCount = 0      

        if self.left:
            self.screen.blit(self.walkLeft[self.walkCount//1], (self.x, self.y))
            self.walkCount += 1

        elif self.right:
            self.screen.blit(self.walkRight[self.walkCount//1], (self.x, self.y))
            self.walkCount += 1

        else:
            self.screen.blit(self.char, (self.x, self.y))



sprite = player(4, 480, 16, 16)

def redrawGamescreen():                      

    sprite.screen.blit(pygame.transform.scale(bg,(1280, 800)),(0,0))   
    sprite.screen.blit(pygame.transform.scale(fg,(1280, 800)),(0,0))   
    sprite.draw(sprite.screen)
    pygame.display.update()



#mainloop:-----------------------------------------------------------------
run = True

while run:
    keys = pygame.key.get_pressed()
    Sresize()
    clock.tick(20)
#left

    if keys[pygame.K_LEFT] and sprite.x > sprite.velocity:
        sprite.x -= sprite.velocity
        sprite.left = True
        sprite.right = False

#right 

    elif keys[pygame.K_RIGHT] and sprite.x < 1280 - sprite.width - sprite.velocity:
        sprite.x += sprite.velocity
        sprite.right = True
        sprite.left = False

#otherwise, stand still

    else:
        sprite.right = False
        sprite.left = False
        sprite.walkCount = 0

#jumping


    if not(sprite.isJump):

        if keys[pygame.K_SPACE]:
            sprite.isJump = True
            sprite.right = False
            sprite.left = False

    else:
        if sprite.jumpCount >= -7:
            neg = 1        
            pygame.display.update()
            if sprite.jumpCount < 0:
                neg = -1

            sprite.y -= (sprite.jumpCount ** 2) * 0.5 * neg 
            sprite.jumpCount -= 1

        else:
            sprite.isJump = False
            sprite.jumpCount = 7 
            sprite.velocity = 15

    redrawGamescreen()

pygame.quit()








Upvotes: 3

Views: 401

Answers (1)

Rabbid76
Rabbid76

Reputation: 211277

The issue is the call to event=pygame.event.wait(). Note pygame.event.wait() waits for a single event from the queue. If the queue is empty this function will wait until one is created. That makes your game lag. The issue is compounded by the fact that pygame.event.pump() is called right before.

pygame.event.pump()                                                                 
event=pygame.event.wait()

Use pygame.event.get() instead:

events=pygame.event.get()

pygame.event.get() gets removes all messages from the event queue and.

e.g.:

def HandleEvents():
                                                                   
    events = pygame.event.get()                                                            
    for event in events:
        if event.type==QUIT:
            pygame.quit()                                              

        elif event.type==VIDEORESIZE:                                                           
        
            sprite.screen=pygame.display.set_mode(event.dict['size'],HWSURFACE|DOUBLEBUF|RESIZABLE)
            sprite.screen.blit(pygame.transform.scale(bg,event.dict['size']),(0,0))
            sprite.screen.blit(pygame.transform.scale(fg,event.dict['size']),(0,0))
            pygame.display.update()

Note, for a good control flow, you have to implement on event loop in the application loop. The event loop has to process all the user inputs.

Upvotes: 3

Related Questions