2

I am trying to make a game, but when I try to blit a few flowers onto the screen it slows down from 60 FPS to 12 FPS.

At first, I tried to .convert() all my images, but then they turned pink. So I used .convert_alpha() instead. using .convert_alpha() made the images not pink, but it only made the FPS go up a teeny bit.

the relevant parts of my code are

### Creates a random assortment of Flora ###
def createFlora(screenSize, cellSize):
    flower1 = pygame.transform.scale(pygame.image.load("Flower1.PNG"), (64, 64))
    flower1 = flower1.convert_alpha()
    flower2 = pygame.transform.scale(pygame.image.load("Flower2.PNG"), (64, 64))
    flower2 = flower2.convert_alpha()
    flowers = [flower1, flower2]
    flower1ds = pygame.transform.scale(pygame.image.load("Flower1DropShadow.PNG"), (64, 64))
    flower1ds = flower1ds.convert_alpha()
    flower2ds = pygame.transform.scale(pygame.image.load("Flower2DropShadow.PNG"), (64, 64))
    flower2ds = flower2ds.convert_alpha()
    flowersds = [flower1ds, flower2ds]


    flora = []
    for i in range(screenSize[0] // cellSize + 1):
        floraRow = []
        for j in range(screenSize[1] // cellSize + 1):
            if randint(0, len(flowers) * 4) < len(flowers):
                choice = randint(0, len(flowers) - 1)
                floraRow.append((flowers[choice],
                               (i * cellSize, j * cellSize),
                               randint(0, 3) * 90, choice))
            else: floraRow.append(False)
            flora.append(floraRow)

    floraFinal = []
    for i in range(len(flora)):
        for j in range(len(flora[0])):
            if flora[i][j] != False:
                if flora[i][j][3] == 0:
                    if flora[i][j][2] == 0: #depending on the rotation of parent plant, the shadow will be changed.
                        floraFinal.append((pygame.transform.rotate(flowersds[flora[i][j][3]], flora[i][j][2]), flora[i][j][1]))
                    elif flora[i][j][2] == 90:
                        floraFinal.append((pygame.transform.rotate(flowersds[flora[i][j][3]], flora[i][j][2]), (flora[i][j][1][0], flora[i][j][1][1] + 8)))
                    elif flora[i][j][2] == 180:
                        floraFinal.append((pygame.transform.rotate(flowersds[flora[i][j][3]], flora[i][j][2]), (flora[i][j][1][0] + 8, flora[i][j][1][1] + 8)))
                    elif flora[i][j][2] == 270:
                        floraFinal.append((pygame.transform.rotate(flowersds[flora[i][j][3]], flora[i][j][2]), (flora[i][j][1][0] + 8, flora[i][j][1][1])))

                elif flora[i][j][3] == 1: 
                    if flora[i][j][2] == 0:
                        floraFinal.append((flowersds[flora[i][j][3]], flora[i][j][1]))
                    elif flora[i][j][2] == 90:
                        floraFinal.append((flowersds[flora[i][j][3]], (flora[i][j][1][0], flora[i][j][1][1] + 4)))
                    elif flora[i][j][2] == 180:
                        floraFinal.append((flowersds[flora[i][j][3]], (flora[i][j][1][0] + 4, flora[i][j][1][1] + 4)))
                    elif flora[i][j][2] == 270:
                        floraFinal.append((flowersds[flora[i][j][3]], (flora[i][j][1][0] + 4, flora[i][j][1][1])))
                floraFinal.append((pygame.transform.rotate(flora[i][j][0], flora[i][j][2]), flora[i][j][1]))
    return floraFinal

def renderFlora(flora, screen):
    for i in range(len(flora)):
        screen.blit(flora[i][0], flora[i][1])
def main():
    os.environ['SDL_VIDEO_CENTERED'] = '1' #center the screen
    pygame.init()
    screenSize = (1856, 960) #24 x 14 cells
    onTop(pygame.display.get_wm_info()['window']) #move pygame window to the front

    screen = pygame.display.set_mode(screenSize)
    screen.fill((25, 25, 25))

    """ VARS """
    cellSize = 64

    pygame.font.init() 
    myfont = pygame.font.SysFont('Comic Sans MS', 30)

    path = createPath()
    flora = createFlora(screenSize, cellSize)
    tileMap = createTileMap(screenSize, cellSize)

    tileGridOn = False
    currentButton = 0

    buttons = []
    gridButtonImg = pygame.transform.scale(pygame.image.load("GridButton.PNG").convert_alpha(), (48, 48))
    #Grid Button Toggles a grid so you can see where Tiles are easier
    buttons.append(Button((20, screenSize[1] - 64), False, gridButtonImg, screen, 48))


    pathSds = pygame.transform.scale(pygame.image.load("StraightPathDropShadow.PNG").convert_alpha(), (64, 64))
    pathCds = pygame.transform.scale(pygame.image.load("CornerPathDropShadow.PNG").convert_alpha(), (64, 64))

    #==# MAIN LOOP #==#
    clock = pygame.time.Clock()
    while True:
        screen.fill((25, 25, 25))
        for evt in pygame.event.get():
            if evt.type == pygame.QUIT:
                pygame.quit()
                quit()

        #Draw Background Tiles
        renderBackground(tileMap, screen)

        #Draw Midground Items/Tiles
        renderFlora(flora, screen)

        #Draw Foreground Items/Tiles
        renderPath(path, screen, pathSds, pathCds)

        textsurface = myfont.render(str(round(clock.get_fps() * 10) / 10), False, (0, 0, 0))
        screen.blit(textsurface,(15, 15))

        ### Buttons ###
        for i in range(len(buttons)):
            buttons[i].update(screen)
            if buttons[i].getCTF():
                currentButton = i
            #Toggle Grid
        tileGridOn = buttons[0].getValue()
        if tileGridOn: drawGrid(screenSize, cellSize, screen)

        pygame.display.flip()
        clock.tick(60)
main()

The flora is created before the main loop, so I'm not creating images every cycle, I'm just passing a list through the render function, which only blits the images onto the screen.

If I comment out the renderFlora() method it goes to 60 FPS, but if I leave it in it drops significantly, I don't know why, because I already blit a lot more images for the tiled background. method.

Astrocow
  • 75
  • 4
  • 2
    how many items do you have in `flora` ? if they don't change position then you could blit them on separated [Surface](https://www.pygame.org/docs/ref/surface.html) at start, and late you can blit single surface. – furas May 09 '19 at 22:35

1 Answers1

0

Improve performance by pre-treating the flora. Render on a surface before the application loop and blit the surface in the application loop:

def main():

    # [...]

    flora_surf = pygame.Surface(screen.get_size())
    renderFlora(flora, flora_surf)

    while True:

        # [...]

        #Draw Midground Items/Tiles
        # renderFlora(flora, screen) <-- DELETE
        screen.blit(flora_surf, (0, 0))       

        # [...]
Rabbid76
  • 202,892
  • 27
  • 131
  • 174