Pygame FirstGame (6) – Saving framerate with Group

See how to same frame rate grouping all sprites and showing them all at once on the screen, rather than showing them individually. With Group of the class sprite of the module pygame (that I called pg) you can group more sprites and thed update the group, instead of a single sprite. Watch the video to see how the framerate gain a lot of benefits from this and how I avoided grouping the sprites every frame.

I made this change:

g = pg.sprite.Group()
group_all_sprites()

after I created the group that I called g

def group_all_sprites():
    "Iterate all the sprites in the dsprites"
    for s in dsprites:
        g.add(dsprites[s])

I called this function above that takes all the sprites in the dictionary, that is the following

dsprites = {
    "pwalk" : Sprite(50, 30, "cat", "Walk"),
    "prun": Sprite(200, 70, "cat", "Run"),
    "pjump": Sprite(150, 150, "dog", "Jump"),
}

So that, now, I got all my sprite in g.

Then I just update g in the while loop

while loop:
    update_screen()

The while loop calls the update_screen every frame

def update_screen():
    "The while loop updates"
    quitbutton()
    clear_screen()
    display_fps()
    show_sprites()
    refresh_screen()

So that the udpate screen clears the screen and calls show_sprites()

def show_sprites():
    g.draw(screen)
    g.update()

That draws the group and update the animation image (prepare to show in the next frame (or 180 frames that I used to slow down the image progression to make it go slower).

The whole code

# Pygame first gamet - tutorial 4
import pygame as pg
import sys
from glob import glob


class Sprite(pg.sprite.Sprite):
    def __init__(self, pw, ph, folder, action):
        "loads all the image that starts with 'action' in position pw, ph"
        super().__init__()

        self.pw = pw
        self.ph = ph
        self.current = 0
        self.countframe = 0
        self.folder = folder
        self.action = action
        self.order_images()
        self.position_sprite()

    def order_images(self):
        "take the list of images (load_images()) and order them"
        lst = self.load_images()
        img = [f for f in lst if len(f) == len(lst[0])]
        img.extend([f for f in lst if len(f) != len(lst[0])])
        self.sprites = [pg.image.load(x) for x in img]
        self.image = self.sprites[self.current]

    def load_images(self):
        "Load images that starts with action"
        lst = glob(f"{self.folder}\\{self.action}*")
        return lst

    def position_sprite(self):
        self.rect = self.image.get_rect()
        self.rect.topleft = [self.pw, self.ph]

    def update(self):
        "This animate the sprite, it is called in the while loop by th update(sprite) function"
        self.countframe += 1
        # the more is the number the more the animation is slow
        if self.countframe == 180:
            # restart the counter
            self.countframe = 0
            # The new animation image is flipped after 4 frames
            self.current += 1
            # check if the images of the animations are ended
            if self.current >= len(self.sprites):
                # if so it goes back to the initial image
                self.current = 0
            # and now it shows the next image or the initial one
            self.image = self.sprites[self.current]


def update(sprite):
    sprite.draw(screen)
    sprite.update()


def window(title, w=400, h=400):
    "Create the screen + title and the clock object for the frame"

    screen = pg.display.set_mode((w, h))
    pg.display.set_caption(title)
    return screen, pg.time.Clock()


def quitbutton():
    "Look for the key events"
    global loop
    for event in pg.event.get():
        if event.type == pg.QUIT:
            loop = 0


def clear_screen():
    screen.fill((0, 64, 128))


def refresh_screen():
    pg.display.flip()
    clock.tick()


def group_all_sprites():
    "Iterate all the sprites in the dsprites"
    for s in dsprites:
        g.add(dsprites[s])


def show_sprites():
    update(g)


# ============== FRAME RATE FUNCTIONS =====

def create_fonts(font_sizes_list):
    "Creates different fonts with one list"
    fonts = []
    for size in font_sizes_list:
        fonts.append(
            pg.font.SysFont("Arial", size))
    return fonts


def render(fnt, what, color, where):
    "Renders the fonts as passed from display_fps"
    text_to_show = fnt.render(what, 1, pg.Color(color))
    screen.blit(text_to_show, where)


def display_fps():
    "Data that will be rendered and blitted in _display"
    render(
        fonts[0],
        what=str(round(clock.get_fps(), 1)),
        color="white",
        where=(0, 0))
# put this after pygame.init() or pg.init()
# fonts = create_fonts([32, 16, 14, 8])
# ==== END ==== #



def update_screen():
    "The while loop updates"
    quitbutton()
    clear_screen()
    display_fps()
    show_sprites()
    refresh_screen()

# All the sprites that are updated in update_screen => show_sprites

# klist = []
# for f in glob("cat\\*.png"):
#     print(f)
#     klist.append(f.split(" ")[0])
# print(klist)

# pos = [
#     [50,30],
#     [200, 70],
#     [150, 150]]

# dsprites = 
# for k in klist:
#     d

dsprites = {
    "pwalk" : Sprite(50, 30, "cat", "Walk"),
    "prun": Sprite(200, 70, "cat", "Run"),
    "pjump": Sprite(150, 150, "dog", "Jump"),
}

pg.init()
g = pg.sprite.Group()
group_all_sprites()
fonts = create_fonts([32, 16, 14, 8])
screen, clock = window("Game", w=500, h=500)
loop = 1
# ============== Where everything happens
while loop:
    update_screen()
# ======================== engine end ===

pg.quit()
sys.exit()

Video

Other Pygame's posts

Published by pythonprogramming

Started with basic on the spectrum, loved javascript in the 90ies and python in the 2000, now I am back with python, still making some javascript stuff when needed.