User Tools

Site Tools


pygame-intro

Arhivă cu exemple și exerciții

Introducere

Instalare pygame

Folositi acest link. next next, ar trebui sa mearga.

Crearea unei ferestre

O fereastra se creeaza foarte simplu, rulati in interpretor:

import pygame
# set_mode primeste ca prim parametru rezolutia: width x height
screen = pygame.display.set_mode((500,500))

Fereastra mai poate primi ca argumente pentru set_mode si niste parametri precum DOUBLEBUF sau FULLSCREEN. Vom folosi DOUBLEBUF in general, creeaza o impresie vizuala mai buna.

Important: trebuie apelat pygame.display.flip(), ca in scheletul urmator, pentru ca schimbarile facuse sa devina vizibile.

import pygame
from pygame.locals import DOUBLEBUF
screen = pygame.display.set_mode((500,500), DOUBLEBUF)
 
# desenam ceva, vom vedea cum in sectiunile urmatoare
 
# trebuie sa apelam flip() pentru a se afisa ce am desenat anterior.
pygame.display.flip()

Bucla principală

In general in dezvoltarea unei aplicatii grafice exista o bucla infinita (facuta explicit, intentionat de programator). Daca nu am avea o bucla infinita, programul nostru s-ar incheia (la iesirea din program, de exemplu prin return 0 in C) si asta ar face ca aplicatia grafica pe care am desenat-o sa se inchida si ea.

Astfel bucla arata astfel:

import pygame
 
# Acest if e similar cu "int main() {" in C, folosit in acelasi scop
# In python codul se scrie indentat, asa vom proceda si noi cu continutul blocului if.
if __name__ == '__main__':
    screen = pygame.display.set_mod((400,400), pygame.locals.DOUBLEBUF)
 
    running = True
    while running:
        # procesare evenimente utilizator (mouse, apasare taste, joystick etc.)
 
        # daca utilizatorul a apasat pe inchiderea ferestrei sau a dat Alt+F4, vrem sa iesim
        if eveniment_iesire():
            running = False
 
        # desenare elemente care s-au schimbat de la pasul anterior buclei
        # ...
 
        pygame.display.flip()
 
    pygame.quit()

Desenare forme: pygame.draw

Desenarea formelor geometrice in pygame se face cu pygame.drawDocumentatie oficiala.

O multime de forme suportate: dreptunghi, poligon, cerc, elipsa, arc, tipuri diverse de linii.

circle

Vom desena foarte simplu un cerc, apoi vom “tine” fereastra mai mult, pentru a putea vedea rezultatele.

import pygame
from pygame.locals import *
 
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
 
screen = pygame.display.set_mode((400,400), DOUBLEBUF)
 
# semnatura draw.cricle: circle(Surface, color, pos, radius, width=0) -> Rect
# width are un parametru implicit; daca nu-i pasam un argument, va lua valoarea implicita (aici 0).
# si intoarce un obiect de tip Rect
pygame.draw.circle(screen, WHITE, [200, 200], 40)
pygame.draw.circle(screen, WHITE, [100, 200], 20, 5)
 
# Pentru a se afisa, nu uitati :)
pygame.display.flip()
 
# Mai "tinem" 2000 ms pentru a vedea ce se intampla.
pygame.time.wait(2000)

:!: TASK: desenati sigla Audi cu Gri, cautati pe net daca sunteti printre aceia care n-o stiu!

:!: Completați sub comentatile ce conțin TODO în fișierul draw_audi.py din arhiva cu exerciții.

rectangle

import pygame
from pygame.locals import *
 
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
 
screen = pygame.display.set_mode((400,400), DOUBLEBUF)
 
# semnatura draw.cricle: circle(Surface, color, pos, radius, width=0) -> Rect
# width are un parametru implicit; daca nu-i pasam un argument, va lua valoarea implicita (aici 0).
# si intoarce un obiect de tip Rect
pygame.draw.rect(screen, WHITE, [150, 10, 50, 20])
pygame.draw.rect(screen, BLUE, [200, 200, 50, 50], 2)
 
# Pentru a se afisa, nu uitati :)
pygame.display.flip()
 
# Mai "tinem" 2000 ms pentru a vedea ce se intampla.
pygame.time.wait(2000)

:!: TASK: Desenați un triunghi în interiorul unui cerc. Puteți folosi fie un poligonm, fie 3 linii.

:!: Completați sub comentatile ce conțin TODO în fișierul draw_triangle.py din arhiva cu exerciții.

:!: BONUS: Desenati cercurile olimpice (poza). (Hint: Veti avea nevoie de draw.circle si de draw.arc)

:!: Completați sub comentatile ce conțin TODO în fișierul draw_olympic.py din arhiva cu exerciții.

Adăugare imagini

Adaugarea imaginilor se realizeaza la fel de simplu. Intai trebuie insa sa incarcam de pe disc in memorie imaginea, folosind comanda pygame.image.load(cale_imagine.png). Apoi folosim screen.blit pentru a pune imaginea pe ecran.

screen.blit (Block Image Transfer)

import pygame
from pygame.locals import *
 
screen = pygame.display.set_mode((400,400), DOUBLEBUF)
car = pygame.image.load('car.png')
# Al doilea argument reprezinta pozitia coltului stanga sus al imaginii 'car.png'.
screen.blit(car, (0,0))
pygame.display.flip()
 
# Mai "tinem" 2000 ms pentru a vedea ce se intampla.
pygame.time.wait(2000)

Animații

Animatiile se realizeaza prin stergerea si redesenarea unei imagini rapid, astfel incat sa fie perceputa schimbarea de coordonate ca o miscare. Avem nevoie sa putem sterge totul de pe ecran, vom face asta cu screen.fill()'. Conceptual, codului de mai sus trebuie sa-i aplicam o redesenare repetata:

import pygame
from pygame.locals import *
 
screen = pygame.display.set_mode((400,400), DOUBLEBUF)
car = pygame.image.load('car.png')
 
for i in range(100):
    # stergem totul de pe ecran, punand negru peste tot
    screen.fill((0,0,0))
    # redesenam masina la o noua coordonata, ce depinde de i ; 
    # asta face ca coordonata x sa creasca, deci o miscare spre dreapta
    screen.blit(car, (i,0))
    pygame.display.flip()

:!: TASK: animați o imagine astfel încât să meargă dintr-o parte în alta a ecranului, iar atunci când se lovește de margine să schimbe direcția în care merge.

:!: Completați sub comentatile ce conțin TODO în fișierul move_image.py din arhiva cu exerciții.

Transformări

Putem aplica diferite transformari asupra unor imagini (nu si asupra unor forme) folosind pygame.transform. Documentatia oficiala

Tipuri de transformari posibile: flip (intoarcere vertical/orizontal), rotiri, scalari etc. Vom aplica niste transformari de baza asupra unei imagini (car.png).

import pygame
from pygame.locals import *
 
screen = pygame.display.set_mode((400,400), DOUBLEBUF)
car = pygame.image.load('car.png')
 
# Scalarea poate fi foarte utila in cazul nostru cand imaginea este mult mai mare decat fereastra.
# Parametrul al doilea este o pereche de forma (width x height), noile dimensiuni de scalare.
car = pygame.transform.scale(car, (100,50))
# Rotire in sens trigonometic cu numarul de grade primit ca parametru.
car = pygame.transform.rotate(car, 30)
# Simetria fata de o axa (Ox, Oy) se face cu flip()
# flip(Surface, xbool, ybool) -> Surface
# Facem o intoarcere fata de axa Ox.
car = pygame.transform.flip(car, 1, 0)
 
# Al doilea argument reprezinta pozitia coltului stanga sus al imaginii 'car.png'.
screen.blit(car, (0,0))
pygame.display.flip()
 
# Mai "tinem" 2000 ms pentru a vedea ce se intampla.
pygame.time.wait(2000)

:!: TASK: Rotiți o imagine cu 90 de grade.

:!: Completați sub comentatile ce conțin TODO în fișierul transfor_rotate.py din arhiva cu exerciții.

Evenimente

Evenimentele sunt importante daca vrem ca aplicatia noastra sa faca ceva pe baza interactiunii cu utilizatorul.

Sunt trei moduri de asteptare a unui eveniment:

import pygame
pygame.event.wait()
pygame.event.poll()
pygame.event.get()

wait se va bloca in asteptarea unui eveniment. Daca o masina se misca pe ecran, aceasta se va opri deci (aplicatia ingheata) pana cand apare un eveniment (mouse, tastatura etc.). poll nu se va bloca, si intoarce NOEVENT in cazul in care nu exista niciun eveniment. get este ca poll, doar ca va intoarce toate evenimentele disponibile la acel moment. Evenimentele pot fi si filtrate sa fie doar evenimente de mouse, tastatura etc.

Clock

Ceasul controleaza cat de des (de cate ori intr-o secunda) se vor redesena elementele de pe ecran, cat si cat de repede (tot de cate ori pe secunda) va raspunde aplicatia noastra la inputul utilizatorului. Asadar acesta joaca un rol foarte important in experienta utilizatorului.

Daca nu setam explicit ceasul, PyGame il va seta la parametri “cei mai buni posibili”. In mod normal, ceasul tick(30) este suficient de rapid cat sa ni se para naturala miscarea (inseamna 30 cadre pe secunda daca sistemul poate asigura 30FPS). Daca nu setam explicit, e posibil sa fie un FPS mai mare, cel mai mare posibil permis de sistem.

import pygame
 
clock = pygame.time.Clock()
FRAMES_PER_SECOND = 30
# deltat reprezinta intervalul in milisecunde dintre apelurile tick.
deltat = clock.tick(FRAMES_PER_SECOND)

Input de la utilizator

Inputul de la utilizator se realizeaza asteptand evenimente. Vedeti cateva exemple:

import pygame
from pygame.locals import *
 
screen = pygame.display.set_mode((400,400), DOUBLEBUF)
running = True
while running:
    for event in pygame.event.get():
        # Calea noastra de iesire, declansat cand inchidem fereastra.
        if event.type == pygame.QUIT:
            running = False
            break
 
        # Pastram doar evenimente care au fost declansate de o apasare de tasta.
        if not hasattr(event, 'key'):
            continue
 
        if event.type == KEYDOWN:
            if event.key == K_UP:
                print 'sageata sus'
            elif event.key == K_DOWN:
                print 'sageata jos'
            elif event.key == K_LEFT:
                print 'sageata stanga'
            elif event.key == K_RIGHT:
                print 'sageata dreapta'
            elif event.key == K_SPACE:
                print 'space'
pygame.quit()

:!: TASK: Faceți în așa fel ca la apăsarea tastei SPACE imaginea din fereastră să se mute la o poziție random. Hint: puteți folosi random.randint(a, b) pentru a genera numere random în intervalul [a, b].

:!: Completați sub comentatile ce conțin TODO în fișierul random_image.py din arhiva cu exerciții.

[EXTRA] Sprite

:!: TASK: Faceți în așa fel ca la apăsarea tastei SPACE oaia din animație să sară. O variantă este ca atunci când tasta apăsată să o mutați mai sus iar când tasta este eliberată să o mutați la loc.

:!: Completați sub comentatile ce conțin TODO în fișierul sprites_keymove.py din arhiva cu exerciții.

Materiale

Pentru mai multe exemple si detalii, puteti consula jones-rapidgamedev.pdf, cat si Documentatia Oficiala.

pygame-intro.txt · Last modified: 2014/04/10 01:59 by anpetre