Python pygame

14
Stefano Ricci Quest'opera è stata rilasciata con licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported. 1 Pygame: disegnare e animare Introduzione Lo scopo di questo tutorial è di illustrare le basi della libreria Pygame che permette di disegnare (fino ad arrivare a creare dei giochi) con Python. In questa versione del tutorial si fa sempre riferimento a una macchina Windows (aspetto contributors per Linux/Mac). Prima di cominciare Pygame permette di disegnare e di riprodurre dei suoni. Per questa ragione non è possibile utilizzare ambienti di sviluppo Python online (come repl.it, ad esempio). Sulle macchine Windows è possibile scaricare Portable Python, che non richiede alcuna installazione (è sufficiente copiare i file in una cartella o su una chiavetta USB). Dopo aver scaricato Portable Python, lanciare l'eseguibile Scegliere la cartella di installazione

description

Coderdojo Milano Tutorial

Transcript of Python pygame

Page 1: Python pygame

Stefano Ricci

Quest'opera è stata rilasciata con licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.

1

Pygame: disegnare e animareIntroduzioneLo scopo di questo tutorial è di illustrare le basi della libreria Pygame che permette di disegnare (fino adarrivare a creare dei giochi) con Python.

In questa versione del tutorial si fa sempre riferimento a una macchina Windows (aspetto contributors perLinux/Mac).

Prima di cominciarePygame permette di disegnare e di riprodurre dei suoni. Per questa ragione non è possibile utilizzareambienti di sviluppo Python online (come repl.it, ad esempio).

Sulle macchine Windows è possibile scaricare Portable Python, che non richiede alcuna installazione (èsufficiente copiare i file in una cartella o su una chiavetta USB).

Dopo aver scaricato Portable Python, lanciare l'eseguibile

Scegliere la cartella di installazione

Page 2: Python pygame

Stefano Ricci

Quest'opera è stata rilasciata con licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.

2

Procedere all'installazione (tutti i moduli)

Navigando nella cartella di installazione, lanciare IDLE-Portable.exe per ottenere la Shell Python nella qualepossiamo eseguire delle operazioni o anche scrivere piccoli programmi

Page 3: Python pygame

Stefano Ricci

Quest'opera è stata rilasciata con licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.

3

Esempio 1Lanciamo IDLE-Portable e apriamo un nuovo file (Ctrl-N)

Per poter usare la libreria pygame (o una qualunque libreria) è necessario importarla, dopodiché dobbiamoinizializzare una "superficie" (in inglese Surface) sulla quale disegneremo; per fare questo usiamo ilmetordo set_mode() di pygame.display

import pygame

screen = pygame.display.set_mode((640,400))

Salviamo il file (chiamiamolo esempio_1.py) ed eseguiamolo (F5); apparirà una finestra (con sfondo nero),larga 640 pixel e alta 400 pixel.

Se proviamo a cliccare sulla in alto a destra per chiudere la finestra, otterremo (almeno sullemacchine Windows) un "Non risponde".

La motivazione sta nel fatto che non abbiamo inserito il codice che, intercettato il Click sulla ,termini "correttamente" l'uso di pygame.

Modifichiamo quindi il codice del nostro esempio come segue

import pygame

screen = pygame.display.set_mode((640,400))

Page 4: Python pygame

Stefano Ricci

Quest'opera è stata rilasciata con licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.

4

running = True

while running:

event = pygame.event.poll()

if event.type == pygame.QUIT:

running = False

pygame.quit()

Dopo l'inizializzazione della Surface (memorizzata nella variabile screen), abbiamo inserito il "ciclo deglieventi" (in inglese Event loop) – while running – all'interno del quale andiamo ad interrogare pygame se sisono verificati degli eventi (mediante il metodo pygame.event.poll()) e, se si è verificato l'eventopygame.QUIT, usciamo dal ciclo, chiamando da ultimo il metodo pygame.quit().

Se eseguiamo il codice sopra riportato, ancora una volta comparirà una finestra di 640x480 pixels, maquesta volta, cliccando su , la finestra si chiuderà senza errori.

Esempio 2Ora che abbiamo la superficie su cui disegnare…disegniamo!

Prima però modifichiamo il codice dell'esempio precedente introducendo due variabili in cui memorizzarelarghezza e altezza della superficie di disegno. Siccome sono due variabili che rimarranno "costanti" nelnostro programma, per convenzione usiamo dei nomi composti da sole lettere maiuscole.

import pygame

SCREEN_WIDTH = 640

SCREEN_HEIGHT = 400

screen = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))

running = True

while running:

event = pygame.event.poll()

if event.type == pygame.QUIT:

running = False

pygame.quit()

Per disegnare abbiamo bisogno dei colori. Andiamo a definirne alcuni come "costanti" all'inizio del nostroprogramma.

WHITE = (255,255,255)

BLACK = (0,0,0)

RED = (255,0,0)

GREEN = (0,255,0)

BLUE = (0,0,255)

I "colori" sono una lista di 3 numeri interi (più correttamente sono una tupla) compresi tra 0 e 255,ciascuno di essi rappresentanti l'intensità di Rosso, Verde e Blu o, abbreviato in inglese RGB (G=Green)

Page 5: Python pygame

Stefano Ricci

Quest'opera è stata rilasciata con licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.

5

Combinando i valori RGB è possibile ottenere anche gli altri colori (in effetti si possono ottenere 2563, pari a16.777.216, colori – sfumature - differenti). Così ad esempio, possiamo avere

YELLOW = (255,255,0)

MAGENTA = (255,0,255)

CYAN = (0,255,255)

O anche

CORAL = (255,127,80)

PINK = (255,192,203)

E così via.

Possiamo riempire lo sfondo, per esempio di Verde acqua (SEA_GREEN = (46,139,87)) usando il metodoscreen.fill() e specificando come parametro il colore (come tupla o come costante precedentementedefinita) scelto

import pygame

SCREEN_WIDTH = 640

SCREEN_HEIGHT = 400

WHITE = (255,255,255)

BLACK = (0,0,0)

RED = (255,0,0)

GREEN = (0,255,0)

BLUE = (0,0,255)

YELLOW = (255,255,0)

MAGENTA = (255,0,255)

CYAN = (0,255,255)

CORAL = (255,127,80)

PINK = (255,192,203)

SEA_GREEN = (46,139,87)

screen = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))

running = True

while running:

event = pygame.event.poll()

if event.type == pygame.QUIT:

running = False

screen.fill(SEA_GREEN)

pygame.quit()

Se eseguiamo il codice ora (sempre con F5), non otterremo però la finestra nel colore che abbiamo scelto.

Ma come è possibile? Dove abbiamo sbagliato? In effetti, l'istruzione screen.fill() non colora lo schermo,ma un'area di memoria non ancora visualizzata.

Page 6: Python pygame

Stefano Ricci

Quest'opera è stata rilasciata con licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.

6

E' necessario usare il metodo pygame.display.flip() per aggiornare la visualizzazione. Aggiungiamo lachiamata l'istruzione screen.fill(SEA_GREEN) ed eseguiamo il codice.

import pygame

SCREEN_WIDTH = 640

SCREEN_HEIGHT = 400

WHITE = (255,255,255)

BLACK = (0,0,0)

RED = (255,0,0)

GREEN = (0,255,0)

BLUE = (0,0,255)

YELLOW = (255,255,0)

MAGENTA = (255,0,255)

CYAN = (0,255,255)

CORAL = (255,127,80)

PINK = (255,192,203)

SEA_GREEN = (46,139,87)

screen = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))

running = True

while running:

event = pygame.event.poll()

if event.type == pygame.QUIT:

running = False

screen.fill(SEA_GREEN)

pygame.display.flip()

pygame.quit()

Questa volta comparirà una bella finestra verde acqua!

Prima di proseguire, modifichiamo il codice in modo da renderlo "modulare".

Apriamo una nuova finestra IDLE e copiamo in questa finestra le definizioni dei colori

Salviamo quindi il file come colors.py

Page 7: Python pygame

Stefano Ricci

Quest'opera è stata rilasciata con licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.

7

A questo punto, possiamo nel file esempio_2.py utilizzare le definizioni presenti in colors.py semplicementeimportando il modulo con import colors (attenzione, non si mette l'estensione .py) e modificando lachiamate al metodo fill() andando a specificare che SEA_GREEN è definita nel modulo colors conscreen.fill(colors.SEA_GREEN)

import pygame

import colors

SCREEN_WIDTH = 640

SCREEN_HEIGHT = 400

screen = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))

running = True

while running:

event = pygame.event.poll()

if event.type == pygame.QUIT:

running = False

screen.fill(colors.SEA_GREEN)

pygame.display.flip()

pygame.quit()

Possiamo ora disegnare delle linee, dei rettangoli o dei cerchi usando i metodi

pygame.draw.line() pygame.draw.rect() pygame.draw.circle()

Nota: le coordinate cartesiane della "superficie" di disegno (il nostro screen) partono con (0,0) nell'angoloin alto a sinistra e arrivano a (SCREEN_WIDTH-1, SCREEN_HEIGHT-1) nell'angolo in basso a destra.

Page 8: Python pygame

Stefano Ricci

Quest'opera è stata rilasciata con licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.

8

I metodi sopra riportati devono essere chiamati con dei parametri. Vediamo nel dettaglio

pygame.draw.line(surface, color, start_pos, end_pos, width=1)

dove:

surface: è la superficie di disegno (il nostro screen) color: è la tupla che identifica il colore in RGB start_pos: è la coppia di coordinate (Xs,Ys) del punto di partenza della linea end_pos: è la coppia di coordinate (Xe,Ye) del punto di arrivo della linea width (con valore di default 1): è lo spessore della linea

pygame.draw.rect(surface, color, Rect, width=0)

dove:

surface: è la superficie di disegno (il nostro screen) color: è la tupla che identifica il colore in RGB Rect: è la tupla di 4 valori che identificano rispettivamente, l'ascissa e l'ordinata del vertice in alto a

sinistra, la larghezza e l'altezza del rettangolo width (con valore di default 0): è lo spessore della bordo del rettangolo (se 0, allora il rettangolo è

pieno)

Page 9: Python pygame

Stefano Ricci

Quest'opera è stata rilasciata con licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.

9

pygame.draw.circle(surface, color, pos, radius, width=0)

dove:

surface: è la superficie di disegno (il nostro screen) color: è la tupla che identifica il colore in RGB pos: è la coppia di coordinate cartesiane (X,Y) che rappresentano il centro del cerchio radius: è il raggio width (con valore di default 0): è lo spessore della bordo del cerchio (se 0, allora il cerchio è pieno)

Page 10: Python pygame

Stefano Ricci

Quest'opera è stata rilasciata con licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.

10

Ecco il nostro esempio completo

import pygame

import colors

SCREEN_WIDTH = 640

SCREEN_HEIGHT = 400

screen = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))

running = True

while running:

event = pygame.event.poll()

if event.type == pygame.QUIT:

running = False

screen.fill(colors.SEA_GREEN)

pygame.draw.line(screen, colors.BLACK, (50,300), (350,100), 3)

pygame.draw.rect(screen, colors.RED, (10,10,60,300), 5)

pygame.draw.circle(screen, colors.YELLOW, (400,200), 100)

pygame.display.flip()

pygame.quit()

Possiamo ora fare un po' di esperimenti con quanto appreso finora!

Per maggiori riferimenti su questi metodi, e altri ancora per disegnare archi, ellissi e poligoni si puòconsultare la documentazione online

http://www.pygame.org/docs/ref/draw.html

Page 11: Python pygame

Stefano Ricci

Quest'opera è stata rilasciata con licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.

11

Esempio 3Pygame non serve solo per disegnare…ma anche per creare animazioni.

Ma cos'è una animazione? Possiamo pensarla come una sequenza di disegni, ciascuno leggermentedifferente dal precedente, mostrati in sequenza.

Iniziamo disegnando un cerchio rosso su sfondo blu al centro dello schermo.

import pygame

import colors

SCREEN_WIDTH = 640

SCREEN_HEIGHT = 400

screen = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))

running = True

pos = (SCREEN_WIDTH/2, SCREEN_HEIGHT/2)

while running:

events = pygame.event.get()

for event in events:

if event.type == pygame.QUIT:

running = False

screen.fill(colors.BLUE)

pygame.draw.circle(screen, colors.RED, pos, 20)

pygame.display.flip()

pygame.quit()

Ora, alla fine del ciclo while (ma sempre al suo interno – attenti all'indentazione!), modifichiamo lecoordinate del centro del cerchio (pos), aggiungendo una quantità random.

x = pos[0] + random.randint(-10,10)

y = pos[1] + random.randint(-10,10)

pos = (x,y)

per usare la funzione random.randint() dobbiamo importare il modulo random all'inizio del nostrocodice.

Eseguendo il codice, osserviamo due problema:

1. la nostra pallina rossa sembra sparire ogni tanto2. la visualizzazione è "mossa", nel senso che vediamo più palline nello stesso istante.

Il primo è dovuto al fatto che non abbiamo inserito nessun controllo sui valori di x e y, le coordinate dellaposizione della pallina. Aggiungendo delle quantità random, di tanto in tanto x e y "escono" dallo schermo.

Page 12: Python pygame

Stefano Ricci

Quest'opera è stata rilasciata con licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.

12

Introduciamo quindi un controllo

x = pos[0] + random.randint(-10,10)

if x < 0: x = 0

elif x > SCREEN_WIDTH: x = SCREEN_WIDTH

y = pos[1] + random.randint(-10,10)

if y < 0: y = 0

elif y > SCREEN_HEIGHT: y = SCREEN_HEIGHT

pos = (x,y)

Il secondo problema è invece dovuto al fatto che disegniamo lo schermo con una frequenza troppo alta, piùalta di quella che i nostri occhi riescono a percepire, per cui "vediamo" in effetti più "frame" sovrapposti.

Per risolvere questo problema dobbiamo "rallentare" la nostra animazione, facendo disegnare, ad esempio,"solo" 30 volte al secondo lo schermo.

Per fare definiamo, fuori dal ciclo while, una variabile clock = pygame.time.Clock() e nel ciclo whileinseriamo la chiamata clock.tick(30), dove 30 è il numero di "disegni" al secondo che vogliamo fare.

Modificando il valore del parametro passato a clock.tick() si può rallentare o accelerare l'animazione.

Ecco il codice completo

import pygame

import random

import colors

SCREEN_WIDTH = 640

SCREEN_HEIGHT = 400

screen = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))

running = True

pos = (SCREEN_WIDTH/2, SCREEN_HEIGHT/2)

clock = pygame.time.Clock()

while running:

clock.tick(30)

events = pygame.event.get()

for event in events:

if event.type == pygame.QUIT:

running = False

screen.fill(colors.BLUE)

pygame.draw.circle(screen, colors.RED, pos, 20)

pygame.display.flip()

Page 13: Python pygame

Stefano Ricci

Quest'opera è stata rilasciata con licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.

13

x = pos[0] + random.randint(-10,10)

if x < 0: x = 0

elif x > SCREEN_WIDTH: x = SCREEN_WIDTH

y = pos[1] + random.randint(-10,10)

if y < 0: y = 0

elif y > SCREEN_HEIGHT: y = SCREEN_HEIGHT

pos = (x,y)

pygame.quit()

Esempio 4Modifichiamo ora l'esempio precedente così che la pallina rossa, anziché muoversi a caso, segua il mouse.

Per fare questo abbiamo bisogno di conoscere la posizione del mouse

mouse_pos = pygame.mouse.get_pos()

nota la posizione del mouse e quella attuale della pallina, possiamo calcolare la nuova posizione facendoavvicinare la pallina al mouse del 20% (0.2) della distanza attuale

x = pos[0] + int(vel*(mouse_pos[0]-pos[0]))

y = pos[1] + int(vel*(mouse_pos[1]-pos[1]))

otteniamo così:

Page 14: Python pygame

Stefano Ricci

Quest'opera è stata rilasciata con licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.

14

import pygame

import random

import colors

SCREEN_WIDTH = 640

SCREEN_HEIGHT = 400

screen = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))

running = True

pos = (SCREEN_WIDTH/2, SCREEN_HEIGHT/2)

clock = pygame.time.Clock()

vel = 0.2

while running:

clock.tick(30)

events = pygame.event.get()

for event in events:

if event.type == pygame.QUIT:

running = False

screen.fill(colors.BLUE)

pygame.draw.circle(screen, colors.RED, pos, 20)

pygame.display.flip()

mouse_pos = pygame.mouse.get_pos()

x = pos[0] + int(vel*(mouse_pos[0]-pos[0]))

if x < 0: x = 0

elif x > SCREEN_WIDTH: x = SCREEN_WIDTH

y = pos[1] + int(vel*(mouse_pos[1]-pos[1]))

if y < 0: y = 0

elif y > SCREEN_HEIGHT: y = SCREEN_HEIGHT

pos = (x,y)

pygame.quit()

Il prossimo passo è quello di controllare la pallina con i tasti freccia…ma per ora

That's all folks!