Pygame hints

https://blubberquark.tumblr.com/post/630054903238262784/why-pygame-is-slow

WPROWADZENIE

Pygame to biblioteka, a nie silnik gry. Użytkownik ma swobodę projektowania pętli gry (game loop), rysowania na ekranie, korzystania z własnych algorytmów i struktur danych. Samemu należy np. wykrywać kolizje obiektów. Można przypadkowo zaimplementować coś mało wydajnie.

Generalnie nie należy za wcześnie zabierać się za optymalizację kodu. Najpierw należy się upewnić, co jest faktyczną przyczyną powolnej pracy. Czasem problem tkwi w niewłaściwych strukturach danych, niewłaściwych algorytmach użytych w grze.

Jeżeli kod działa stabilnie dla 60 FPS, to nie ma sensu zajmować się optymalizacją.

Można przyspieszyć odświeżanie pikseli na ekranie. Zamiast użyć pygame.display.flip(), które przerysowuje cały ekran, można przekazać do odświeżenia tylko te prostokąty ekranu, w których piksele rzeczywiście się zmieniły. Używa się pygame.display.update(dirty_rects) z listą obiektów Rect.

Jednym z powodów spowolnienia gry może być ładowanie plików w każdym obiegu pętli while.

PRZYCISKI

Czasem może się pojawić potrzeba stworzenia na ekranie obiektu działającego jak przycisk, którego naciśnięcie myszą powoduje wykonanie pewnej akcji. Podany przykład pokazuje, jak można zbudować przyciski na bazie klasy Sprite. Przyciski będą zmieniać tło ekranu.


import sys
import pygame

# COLORS
black = (0, 0, 0)
gray = (128, 128, 128)
white = (255, 255, 255)
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
yellow = (255, 255, 0)

# Object class
class Button(pygame.sprite.Sprite):

    def __init__(self, text, font_size):
        #pygame.sprite.Sprite.__init__(self)
        super().__init__()
        font = pygame.font.Font(None, font_size)   # load the pygame default font
        text_surf = font.render(text, True, black)   # czarne fonty
        text_rect = text_surf.get_rect()
        self.image = pygame.Surface((text_rect.width, text_rect.height))
        self.image.fill(white)   # białe tło przycisku
        self.image.blit(text_surf, text_rect)
        self.rect = self.image.get_rect()   # lub text_rect

# INITIALIZE THE GAME
pygame.init()   # to zawsze na starcie
size = (width, height) = (500, 500)
screen = pygame.display.set_mode(size)   # display Surface
pygame.display.set_caption('Buttons')

# CLOCK
FPS = 60   # frames per second setting
clock = pygame.time.Clock()

red_button = Button("Red", 50)
red_button.rect.center = (width // 4, height // 4)

blue_button = Button("Blue", 50)
blue_button.rect.center = (3*width // 4, height // 4)

green_button = Button("Green", 50)
green_button.rect.center = (width // 4, 3*height // 4)

yellow_button = Button("Yellow", 50)
yellow_button.rect.center = (3*width // 4, 3*height // 4)

buttons = pygame.sprite.Group()
buttons.add(red_button, blue_button, green_button, yellow_button)

screen_bg = black   # początkowy kolor ekranu

# MAIN GAME LOOP
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:   # QUIT Event, pygame.locals.QUIT
            pygame.quit()   # deactivates the Pygame library
            sys.exit(0)
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if red_button.rect.collidepoint(event.pos):
                screen_bg = red
                print("red button pressed ...")
            if blue_button.rect.collidepoint(event.pos):
                screen_bg = blue
                print("blue button pressed ...")
            if green_button.rect.collidepoint(event.pos):
                screen_bg = green
                print("green button pressed ...")
            if yellow_button.rect.collidepoint(event.pos):
                screen_bg = yellow
                print("yellow button pressed ...")

    # DRAWING
    screen.fill(screen_bg)   # na nowo malujemy ekran
    buttons.draw(screen)   # rysujemy przyciski

    pygame.display.flip()
    clock.tick(FPS)