
🎮 Pierwsza gra na Pygame: piszemy na Pythonie od zera
Czy chcą Państwo napisać swoją pierwszą grę, ale nie wiedzą, od której strony podejść do gamedevu? Pygame usuwa tę barierę. Piszą Państwo w czystym Pythonie i od razu widzą rezultat na ekranie: ruchomy sprite, reakcję na klawisze, ożywioną mechanikę. Bez ciężkich silników, bez tysięcy linii szablonowego kodu.
Problem większości tutoriali polega na tym, że albo zagrzebują się w teorii na 40 stron, albo rzucają Państwa z hasłem „dokończcie sami". Tutaj pójdziemy środkową drogą: wyjaśnimy dokładnie tyle, by rozumieli Państwo każdą linię, i od razu złożymy działającą grę, postać poruszającą się po ekranie za pomocą WASD. Cały kod mieści się w 60 liniach.
💡 Szybki przegląd:
- Zainstalują Państwo Pygame przez pip i utworzą plik gry, to zajmie parę minut
- Rozpracują Państwo pętlę gry: zdarzenia, obliczenia, renderowanie, trzy fazy, które żyją w nieskończonej pętli
while True - Napiszą Państwo klasę gracza i ożywią go: klawisze WASD poruszają sprite’em, ekran jest przerysowywany 60 razy na sekundę
- Zrozumieją Państwo układ współrzędnych i pracę z kolorem, dwa kamienie węgielne, na których opiera się każda grafika 2D
Czym jest Pygame i dlaczego właśnie on
Pygame to biblioteka dla Pythona, która opakowuje multimedialną bibliotekę SDL (Simple DirectMedia Layer) w wygodne API Pythona. SDL odpowiada za niskopoziomową pracę z grafiką, dźwiękiem i urządzeniami wejściowymi, a Pygame daje do tego dostęp poprzez znane klasy i metody. Aktualna wersja, 2.6.0, biblioteka jest aktywnie wspierana i działa na Windows, macOS oraz Linux.
Dla początkującego Pygame ma trzy niezaprzeczalne zalety. Po pierwsze, próg wejścia: używają Państwo zwykłego kodu Pythona, żadnego nowego języka ani edytora wizualnego. Po drugie, natychmiastowa informacja zwrotna: napisali Państwo pygame.draw.rect(...) i na ekranie pojawił się prostokąt, żadnej magii. Po trzecie, zrozumienie fundamentów: Pygame nie ukrywa przed Państwem pętli gry i kolejki zdarzeń, widzą Państwo, jak każda gra jest zbudowana od środka. Po Pygame łatwiej będzie przesiąść się na Godota czy Unity, ponieważ znają już Państwo pojęcia delta time i event polling.
Biblioteka nie próbuje być silnikiem gry. Nie ma w niej sceny, fizyki ani wbudowanego edytora poziomów i jest to świadoma decyzja. Kontrolują Państwo każdy piksel i każdy takt, a zatem uczą się myśleć jak twórca gier, a nie jak operator cudzego narzędzia.
Instalacja Pygame w dwie minuty
Python 3.9 lub nowszy już jest? W takim razie proszę otworzyć terminal i wykonać jedno polecenie:
1 pip install pygame
Dla izolacji projektu lepiej utworzyć środowisko wirtualne:
1 python -m venv game_env 2 game_env\Scripts\activate # Windows 3 source game_env/bin/activate # macOS / Linux 4 pip install pygame
Proszę sprawdzić, czy biblioteka się zaimportowała:
1 import pygame 2 print(pygame.version.ver)
Jeśli w odpowiedzi otrzymali Państwo 2.6.0 (lub nowszą, aktualną wersję można sprawdzić na pygame.org), wszystko gotowe. Proszę utworzyć folder projektu, umieścić w nim dowolny obrazek-sprite’a o rozmiarze 80×80 pikseli o nazwie player.png i plik tekstowy game.py, od niego zaczniemy.
Jak zbudowana jest pętla gry: zdarzenia, obliczenia, renderowanie
Serce każdej gry, główna pętla, zwana też main loop. Dopóki gra jest uruchomiona, wewnątrz nieskończonej pętli while True następują po sobie trzy fazy:
Przetwarzanie zdarzeń, co się stało od ostatniej klatki? Wciśnięto klawisz? Poruszono myszą? Zamknięto okno? Pygame zbiera wszystkie zdarzenia do kolejki, a my przechodzimy po niej pętlą
for event in pygame.event.get().Obliczanie logiki, jak zmienił się świat w odpowiedzi na zdarzenia? Gracz nacisnął W, zwiększamy współrzędną Y. Pocisk zderzył się z asteroidą, oznaczamy oba „do usunięcia".
Renderowanie, rysujemy wszystko, co ma być na ekranie. Wypełniamy tło, umieszczamy sprite’y według nowych współrzędnych, wywołujemy
pygame.display.update()i gracz widzi klatkę.
Te trzy kroki powtarzają się 60 razy na sekundę, dokładnie tyle klatek (FPS) ustawimy w zegarze. Iluzja ruchu opiera się na tym, że między klatkami sprite przesuwa się o kilka pikseli, a oko odbiera to jako ciągłą animację.
Piszemy pierwszy kod: poruszamy sprite’em po ekranie
Oto pełny kod gry. Proszę zapisać go w game.py i umieścić player.png w tym samym folderze:
1 #!/usr/bin/env python3 2 3 import pygame 4 import sys 5 6 WIDTH, HEIGHT = 360, 480 7 WHITE = (255, 255, 255) 8 9 class Player(pygame.sprite.Sprite): 10 11 def __init__(self, image_path): 12 super().__init__() 13 self.image = pygame.image.load(image_path) 14 self.x = WIDTH / 2 15 self.y = HEIGHT / 2 16 self.speed = 5 17 18 def move(self, dx, dy): 19 self.x += dx 20 self.y += dy 21 22 def main(): 23 pygame.init() 24 screen = pygame.display.set_mode((WIDTH, HEIGHT)) 25 pygame.display.set_caption("Первая игра на Pygame") 26 27 clock = pygame.time.Clock() 28 fps = 60 29 30 player = Player("player.png") 31 dx, dy = 0, 0 32 33 running = True 34 while running: 35 for event in pygame.event.get(): 36 if event.type == pygame.QUIT: 37 running = False 38 39 elif event.type == pygame.KEYDOWN: 40 if event.key == pygame.K_d: 41 dx = player.speed 42 elif event.key == pygame.K_a: 43 dx = -player.speed 44 elif event.key == pygame.K_w: 45 dy = -player.speed 46 elif event.key == pygame.K_s: 47 dy = player.speed 48 49 elif event.type == pygame.KEYUP: 50 if event.key in (pygame.K_d, pygame.K_a): 51 dx = 0 52 elif event.key in (pygame.K_w, pygame.K_s): 53 dy = 0 54 55 player.move(dx, dy) 56 screen.fill(WHITE) 57 screen.blit(player.image, (player.x, player.y)) 58 pygame.display.update() 59 clock.tick(fps) 60 61 pygame.quit() 62 sys.exit() 63 64 if __name__ == "__main__": 65 main()

Proszę uruchomić python game.py, otworzy się okno z białym tłem i Państwa sprite’em na środku. Proszę przytrzymać W, A, S lub D, postać się porusza. Puścili Państwo klawisz, zatrzymuje się. To już prawdziwa gra, choć minimalna.
Co ulepszono w porównaniu z klasycznymi tutorialami: dodano KEYUP, obsługę puszczenia klawisza. Bez tego sprite po pierwszym naciśnięciu pojechałby za krawędź ekranu na zawsze. A także kod opakowano w konstrukcję if __name__ == "__main__", dobrą praktykę, która pozwala zaimportować plik jako moduł bez uruchamiania gry.
Układ współrzędnych i praca z kolorem
W Pygame współrzędne są liczone od lewego górnego rogu: (0, 0) to sam szczyt po lewej. Ruch w prawo zwiększa X, ruch w dół zwiększa Y. Różni się to od szkolnego układu współrzędnych, gdzie Y rośnie w górę, proszę to po prostu zapamiętać i sprawdzić się przy pierwszych dwóch uruchomieniach: nacisnęli Państwo S, sprite pojechał w dół, nacisnęli W, w górę.
Kolor określa się krotką trzech liczb (R, G, B), każda od 0 do 255. Białemu odpowiada (255, 255, 255), czarnemu odpowiada (0, 0, 0), czerwonemu odpowiada (255, 0, 0). Metoda screen.fill(WHITE) wypełnia cały ekran wybranym kolorem przed renderowaniem każdej klatki. Jeśli tego nie zrobić, sprite będzie zostawiał za sobą smugę z poprzednich pozycji.
Co dzieje się pod maską: analiza krok po kroku
Klasa Player dziedziczy po pygame.sprite.Sprite, to wbudowana klasa Pygame dla obiektów gry. W konstruktorze ładujemy obrazek przez pygame.image.load() i ustawiamy pozycję startową na środku ekranu: WIDTH / 2 i HEIGHT / 2. Metoda move(dx, dy) otrzymuje przesunięcie i dodaje je do bieżących współrzędnych, czysta arytmetyka, żadnej magii.
Funkcja main() składa wszystko w całość. pygame.init() uruchamia wewnętrzne podsystemy. pygame.display.set_mode() tworzy okno, a screen to powierzchnia (Surface), na której rysujemy. pygame.time.Clock() tworzy zegar: jego metoda tick(fps) na końcu pętli mówi Pygame „czekaj, aż minie 1/60 sekundy od poprzedniej klatki", w ten sposób ustalamy częstotliwość klatek i nie obciążamy procesora bez potrzeby.
Główna pętla while running kręci się, dopóki flaga running nie stanie się False. Wewnątrz, trzy fazy, o których mówiliśmy wyżej:

W pętli for event in pygame.event.get() odpytujemy kolejkę zdarzeń. pygame.QUIT to sygnał „użytkownik kliknął krzyżyk okna": ustawiamy running = False i przy następnej iteracji pętla się zakończy. pygame.KEYDOWN wyzwala się przy naciśnięciu klawisza, a KEYUP przy puszczeniu. Dla D i A zmieniamy dx, dla W i S zmieniamy dy. Kiedy klawisz jest puszczany, zerujemy odpowiednią składową prędkości, sprite się zatrzymuje.
screen.blit(player.image, (player.x, player.y)), metoda, która „nakłada" jeden obraz na drugi. W naszym przypadku, sprite gracza na główną powierzchnię ekranu według bieżących współrzędnych. pygame.display.update() odświeża okno i gracz widzi gotową klatkę.
Proszę zwrócić uwagę: player.move() jest wywoływane przed screen.fill(). Jeśli zamienić je miejscami, sprite będzie wymazywany w tej samej milisekundzie, w której się pojawia, po prostu go Państwo nie zobaczą na ekranie. Kolejność operacji w pętli gry jest krytyczna.
Klikają Państwo krzyżyk, pygame.quit() poprawnie wyładowuje podsystemy Pygame, a sys.exit() kończy proces Pythona. Bez pygame.quit() okno może zawisnąć przy zamykaniu, drobiazg, ale kod powinien być schludny.
Krótkie wideo na temat
Jeśli instrukcja tekstowa nie do końca wchodzi, oto świetny kurs wideo po angielsku, gdzie krok po kroku buduje się Space Invaders na Pygame. Wszystkie koncepcje z artykułu są pokazane na żywo:
⁉️🤔 Często zadawane pytania
Czy trzeba znać OOP do Pygame?
Tak, na poziomie podstawowym. Klasy, metody, dziedziczenie i
selfbędą Państwu potrzebne od pierwszego dnia: gracz, wrogowie, pociski i bonusy naturalnie układają się w model obiektowy. Jeśli przeszli Państwo jakikolwiek kurs wprowadzający do Pythona, gdzie wyjaśnianoclassi__init__, to wystarczy. Resztę dobiorą Państwo po drodze: Pygame nie wymaga wzorców projektowych, zwykłe dziedziczenie poSpritewystarcza do dziesiątków prototypów. Obiekt gry w Pygame to klasa dziedzicząca popygame.sprite.Sprite. W konstruktorze ładują Państwo sprite’a przezpygame.image.load(), ustawiają początkowe współrzędne i prędkość. Metodaupdate()(lub własna, w rodzajumove()) zmienia pozycję w każdej klatce. Główna pętla wywołujeupdate()na wszystkich obiektach, potem renderuje je przezscreen.blit(). Żadnej magii, po prostu wywoływanie metod we właściwej kolejności 60 razy na sekundę.
Czy Pygame spowalnia przy złożonej grafice 2D?
Przy rozsądnej liczbie sprite’ów nie. Powierzchnie (Surface) w Pygame żyją w pamięci RAM, a
blitto szybkie kopiowanie pikseli, a nie programowe renderowanie. Przy tysiącach jednocześnie poruszających się obiektów mogą Państwo natknąć się na ograniczenia wydajności Pythona, ale dla platformówki, strzelanki top-down czy tower defence zapas mocy jest wystarczający. Jeśli trzeba wycisnąć maksimum, proszę użyćpygame.sprite.Groupz automatycznym renderowaniem i dirty-rectangles do częściowego odświeżania ekranu.
Czy w Pygame można dodać dźwięk i muzykę?
Tak, od razu po instalacji. Moduł
pygame.mixerpotrafi odtwarzać WAV i MP3. Dźwięk strzału uruchamia się przezpygame.mixer.Sound("shoot.wav").play(), a muzykę w tle ładuje się przezpygame.mixer.music.load("theme.mp3")ipygame.mixer.music.play(-1)(flaga-1zapętla). Jedyny niuans:pygame.mixer.init()trzeba wywołać przed załadowaniem dźwięków, a dla MP3 na Linuksie może być potrzebna bibliotekalibmpg123.
Czy jest sens uczyć się Pygame w 2026 roku, kiedy są Godot i Unity?
Absolutnie. Pygame nie jest konkurentem Godota, to narzędzie edukacyjne i lekka warstwa do prototypów 2D. Nie uczą się Państwo C# po to, by przesunąć kwadracik, i nie rozgryzają systemu węzłów dla Ponga. Pygame daje zrozumienie, jak gry działają na niskim poziomie: pętla gry, buforowanie klatek, kolizje. Programiści, którzy startowali z Pygame, łatwiej opanowują Unity i Godota, ponieważ widzą za abstrakcjami silnika żywą mechanikę. Na Pygame pisze się prawdziwe projekty indie, w tym komercyjne, niewielką platformówkę czy puzzle można wydać na Steamie, nie dotykając C++.
Co zrobić, jeśli sprite wychodzi poza krawędź ekranu?
Proszę dodać sprawdzanie granic w metodzie
move(): jeśliself.x < 0, proszę zrównać z 0; jeśliself.x + ширина_спрайта > WIDTH, proszę zrównać zWIDTH - ширина_спрайта. To samo dla Y. Nazywa się to clamping i bez tego postać prędzej czy później wjedzie w niewidoczny obszar. W bardziej zaawansowanych grach granicami służą ściany poziomu, zdefiniowane przez siatkę kafelków lub tablicę kolizji.
Gotowi uruchomić swoją pierwszą grę?
Proszę skopiować kod z sekcji „Piszemy pierwszy kod", zapisać w game.py, umieścić obok dowolny obrazek-sprite’a i po kilku sekundach zobaczą Państwo okno z ruchomą postacią. To jest właśnie punkt wejścia do gamedevu: nie czytać, tylko uruchomić i zacząć kręcić parametrami.
Proszę zmienić WIDTH i HEIGHT, okno stanie się większe. Proszę ustawić player.speed = 10, postać przyspieszy. Proszę zastąpić WHITE przez (35, 35, 35), otrzymają Państwo ciemne tło. Proszę poeksperymentować, a zrozumieją Państwo, że program gry to nie magia, tylko sekwencja kroków, które Państwo kontrolują.
Kiedy opanują Państwo ruch, proszę wziąć się za kolizje (pygame.sprite.collide_rect()), animację (zmiana klatek arkusza sprite’a) i proceduralną generację poziomów. Na start wystarczy jeden plik game.py i chęć rozpracowania, jak to wszystko jest zbudowane.



