Search code examples
pythonpygamegame-development

Scaling up window in pygame causing lag


Recently I've been trying to build a game in pygame in a low res, pixel art style.

In order to make my game usable I have to scale up my window, so here's a basic example of the code I've developed to do that, where SCALE in the value by which the whole window is scaled up, and temp_surf is the surface I blit my graphics onto before the scale function scales them up.

import sys
import ctypes
import numpy as np
ctypes.windll.user32.SetProcessDPIAware()

FPS = 60
WIDTH = 150
HEIGHT = 50
SCALE = 2

pg.init()
screen = pg.display.set_mode((WIDTH*SCALE, HEIGHT*SCALE))
pg.display.set_caption("Example resizable window")
clock = pg.time.Clock()
pg.key.set_repeat(500, 100)

temp_surf = pg.Surface((WIDTH, HEIGHT))


def scale(temp_surf):
    scaled_surf = pg.Surface((WIDTH*SCALE, HEIGHT*SCALE))
    px = pg.surfarray.pixels2d(temp_surf)
    scaled_array = []
    for x in range(len(px)):
            for i in range(SCALE):
                    tempar = []
                    for y in range(len(px[x])):
                            for i in range(SCALE):
                                    tempar.append(px[x, y])
                    scaled_array.append(tempar)

    scaled_array = np.array(scaled_array)
    pg.surfarray.blit_array(scaled_surf, scaled_array)
    return scaled_surf


while True:
    clock.tick(FPS)
    #events
    for event in pg.event.get():
        if event.type == pg.QUIT:
            pg.quit()
            sys.exit()
        if event.type == pg.KEYDOWN:
            if event.key == pg.K_ESCAPE:
                pg.quit()
                sys.exit()

    #update
    screen.fill((0,0,0))
    temp_surf.fill ((255,255,255))
    pg.draw.rect(temp_surf, (0,0,0), (0,0,10,20), 3)
    pg.draw.rect(temp_surf, (255,0,0), (30,20,10,20), 4)

    scaled_surf = scale(temp_surf)


    #draw
    pg.display.set_caption("{:.2f}".format(clock.get_fps()))
    screen.blit(scaled_surf, (0,0))

    
    pg.display.update()
    pg.display.flip()

pg.quit()

For this example, there is very little lag. However when I try to implement this code in my game, the fps drops from 60 to more like 10.

Is there a more efficient way of scaling up a pygame window that I don't know about? Would there be a way for my code to run more efficiently? I'm open to any suggestions.


Solution

  • Do not recreate scaled_surf in every frame. Creating a pygame.Surface my be an time consuming operation. Create scaled_surf once and continuously use it.
    Furthermore I recommend to use pygame.transform.scale() or pygame.transform.smoothscale(), which are designed for this task:

    scaled_surf = pg.Surface((WIDTH*SCALE, HEIGHT*SCALE))
    
    def scale(temp_surf):
        pg.transform.scale(temp_surf, (WIDTH*SCALE, HEIGHT*SCALE), scaled_surf)
        return scaled_surf