Search code examples
pythonperformancepygamepygame-surfacepygame-tick

Improve performance while executing pygame?


My pygame is running way too slow. Without using class oop it was running perfectly but now using oop its very slow.

I have tested putting that separate class file in main file also but the result was same.

import pygame
from snake import Snake

pygame.init()
surf_width = 800
surf_height = 600
clock = pygame.time.Clock()

dis_surf = pygame.display.set_mode((surf_width, surf_height))
pygame.display.set_caption("snake game")
run = True
def game_loop():
    x = 255
    y = 255
    x_change = 0
    y_change = 0
    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
        dis_surf.fill((255, 255, 255))
        game = Snake(dis_surf, x, y, x_change, y_change)
        x = game.x
        y = game.y

another file: import pygame

class Snake():
    def __init__(self, dis_surf, x, y, x_change, y_change):
        self.dis_surf = dis_surf
        self.x = x
        self.y = y
        self.width = 20
        self.height = 20
        self.x_change = x_change
        self.y_change = y_change
        self.vel = 5
        self.draw()

    def draw(self):
        pygame.draw.rect(self.dis_surf, (0, 255, 0), (self.x, self.y, self.width, self.height))
        self.run()
        pygame.display.update()

    def run(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RIGHT:
                    self.x_change = self.vel
                    self.y_change = 0
                elif event.key == pygame.K_LEFT:
                    self.x_change = -self.vel
                    self.y_change = 0
                elif event.key == pygame.K_UP:
                    self.y_change = -self.vel
                    self.x_change = 0
                elif event.key == pygame.K_DOWN:
                    self.y_change = self.vel
                    self.x_change = 0
            print(event)
        self.x += self.x_change
        self.y += self.y_change


        x_change = game.x_change
        y_change = game.y_change
        pygame.display.update()
        clock.tick(60)

game_loop()

Solution

  • A few things are wrong.

    1) You are instantiating a new Snake class every game loop when you do game = Snake() inside of the while loop. This in combination with number 2 is your main problem. I moved this line outside of the while loop for you.

    2) You are calling run() inside of __init__. This is something you should never do in a constructor, constructors generally should only be used for setting initial data. This also contributed to problem number 1 significantly because this was happening every game loop. I removed the call self.run() inside __init__ for you.

    3) pygame.display.update() was being called twice. Not the cause of your problem, but still unnecessary.

    Made some small corrections for you.

    import pygame
    
    pygame.init()
    surf_width = 800
    surf_height = 600
    clock = pygame.time.Clock()
    
    dis_surf = pygame.display.set_mode((surf_width, surf_height))
    pygame.display.set_caption("snake game")
    run = True
    
    def game_loop():
        x = 255
        y = 255
        x_change = 0
        y_change = 0
        game = Snake(dis_surf, x, y, x_change, y_change)
        while run:
            dis_surf.fill((255, 255, 255))
            game.draw()
    
    class Snake():
        def __init__(self, dis_surf, x, y, x_change, y_change):
            self.dis_surf = dis_surf
            self.x = x
            self.y = y
            self.width = 20
            self.height = 20
            self.x_change = x_change
            self.y_change = y_change
            self.vel = 5
    
        def draw(self):
            pygame.draw.rect(self.dis_surf, (0, 255, 0), (self.x, self.y, self.width, self.height))
            self.run()
    
        def run(self):
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    quit()
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_RIGHT:
                        self.x_change = self.vel
                        self.y_change = 0
                    elif event.key == pygame.K_LEFT:
                        self.x_change = -self.vel
                        self.y_change = 0
                    elif event.key == pygame.K_UP:
                        self.y_change = -self.vel
                        self.x_change = 0
                    elif event.key == pygame.K_DOWN:
                        self.y_change = self.vel
                        self.x_change = 0
            self.x += self.x_change
            self.y += self.y_change
            pygame.display.update()
            clock.tick(60)
    
    game_loop()