Questa è la terza parte di una serie di tutorial in cinque parti sulla creazione di giochi con Python 3 e Pygame. Nella seconda parte, abbiamo coperto il TextObject
classe usata per rendere il testo sullo schermo, ha creato la finestra principale e imparato a disegnare oggetti come mattoni, la palla e la pagaia.
In questa parte, ci tufferemo nel cuore di Breakout e impareremo come gestire gli eventi, incontrare la classe Breakout principale e vedere come spostare i diversi oggetti di gioco.
In Breakout, ci sono tre tipi di eventi: eventi per la pressione dei tasti, eventi del mouse e eventi del timer. Il ciclo principale nella classe Game si occupa degli eventi del mouse e della tastiera e li consegna agli abbonati (chiamando una funzione di gestore).
Mentre la classe Game è molto generica e non ha conoscenze specifiche di Breakout, l'abbonamento stesso e come gestire ogni evento sono molto specifici.
La classe Breakout è dove viene gestita la maggior parte della conoscenza del dominio sul gioco Breakout. Incontreremo la lezione di Breakout diverse volte durante questa serie. Ecco le righe che registrano i vari gestori di eventi.
Nota che tutti eventi chiave per entrambi i tasti freccia sinistra e destra andranno allo stesso metodo gestore della pagaia.
# Registra il metodo handle_mouse_event () di un oggetto button self.mouse_handlers.append (b.handle_mouse_event) # Registra il metodo handle () della paddle per gestire gli eventi chiave self.keydown_handlers [pygame.K_LEFT] .append (paddle.handle) self.keydown_handlers [pygame.K_RIGHT] .append (paddle.handle) self.keyup_handlers [pygame.K_LEFT] .append (paddle.handle) self.keyup_handlers [pygame.K_RIGHT] .append (paddle.handle)
La classe Game chiamerà i gestori registrati per ogni evento chiave e passerà la chiave. Si noti che non è la classe Paddle. In Breakout, l'unico oggetto interessato a questi eventi è la pagaia. Quando un tasto viene premuto o rilasciato, è maniglia()
il metodo è chiamato.
La Paddle non ha bisogno di sapere se si trattava di un key down o di un evento key up perché gestisce lo stato corrente attraverso una coppia di variabili booleane: moving_left
e moving_right
. Se moving_left
è vero allora significa che il tasto freccia sinistra è premuto e il prossimo evento sarà key up, che lo rilascerà. Lo stesso vale per il tasto freccia destra. La logica è semplice come alternare queste variabili in risposta a qualsiasi evento.
def handle (self, key): if key == pygame.K_LEFT: self.moving_left = not self.moving_left else: self.moving_right = not self.moving_right
Breakout ha un menu di gioco che incontrerai presto. Il pulsante del menu gestisce vari eventi del mouse come movimento e clic (mouse down e mouse su eventi). In risposta a questi eventi, il pulsante aggiorna una variabile di stato interna. Ecco il codice di gestione del mouse:
def handle_mouse_event (self, type, pos): se type == pygame.MOUSEMOTION: self.handle_mouse_move (pos) elif type == pygame.MOUSEBUTTONDOWN: self.handle_mouse_down (pos) elif type == pygame.MOUSEBUTTONUP: self.handle_mouse_up ( pos) def handle_mouse_move (self, pos): se self.bounds.collidepoint (pos): if self.state! = 'pressed': self.state = 'hover' else: self.state = 'normal' def handle_mouse_down (self , pos): se self.bounds.collidepoint (pos): self.state = 'pressed' def handle_mouse_up (self, pos): se self.state == 'pressed': self.on_click (self) self.state = ' hover'
Si noti che il handle_mouse_event ()
il metodo registrato per ricevere gli eventi del mouse controlla il tipo di evento e lo inoltra al metodo specifico che gestisce quel tipo di evento.
Gli eventi del timer non vengono elaborati attraverso il loop principale. Tuttavia, poiché il loop principale viene chiamato ogni frame, è facile verificare se è necessario un determinato evento temporizzato. Ne vedrai un esempio più avanti quando discuterai di effetti speciali a tempo.
Un'altra situazione è quando vogliamo bloccare il gioco, ad esempio quando si visualizza un messaggio che il lettore dovrebbe essere in grado di leggere senza distrazioni. Il show_message ()
il metodo della classe Breakout utilizza questo approccio e chiama time.sleep ()
. Ecco il codice rilevante:
import config as c class breakout (Game): def show_message (self, text, color = colors.WHITE, font_name = "Arial", font_size = 20, centralizzato = False): message = TextObject (c.screen_width // 2, c .screen_height // 2, lambda: text, color, font_name, font_size) self.draw () message.draw (self.surface, centralized) pygame.display.update () time.sleep (c.message_duration)
La parte del gameplay è dove vengono a giocare le regole di Breakout (vedi cosa ho fatto lì?). Il gameplay riguarda lo spostamento dei diversi oggetti in risposta agli eventi e la modifica dello stato del gioco in base alle loro interazioni.
Hai visto prima che la classe Paddle risponde ai tasti freccia aggiornando la sua moving_left
e moving_right
campi. Il movimento attuale avviene nel aggiornare()
metodo. C'è qualche computazione in corso qui se la pagaia è vicino al bordo sinistro o destro dello schermo. Non vogliamo che la paletta si sposti oltre i bordi dello schermo (incluso un offset predefinito).
Quindi, se il movimento lo avrebbe portato oltre il bordo, il codice regola il movimento per fermarsi esattamente sul bordo. Poiché la paletta si muove solo orizzontalmente, la componente verticale del movimento è sempre zero.
import pygame import config as c from game_object import GameObject class Paddle (GameObject): def __init __ (auto, x, y, w, h, colore, offset): GameObject .__ init __ (self, x, y, w, h) self. color = color self.offset = offset self.moving_left = False self.moving_right = False ... def update (self): se self.moving_left: dx = - (min (self.offset, self.left)) elif self.moving_right: dx = min (self.offset, c.screen_width - self.right) else: return self.move (dx, 0)
La palla usa solo la funzionalità del GameObject
classe base, che sposta gli oggetti del gioco in base alla loro velocità (con componenti orizzontali e verticali). La velocità della palla è determinata da molti fattori nella classe Breakout che vedrai presto. Poiché lo spostamento è solo aggiungendo la velocità alla posizione corrente, la direzione in cui la palla si muove è completamente determinata dalla sua velocità lungo gli assi orizzontale e verticale.
La palla in Breakout appare dal nulla all'inizio del gioco ogni volta che il giocatore perde una vita. Si materializza appena fuori dall'etere e inizia a scendere verso il basso o leggermente inclinato. Quando la palla viene creata nel create_ball ()
metodo, riceve una velocità con una componente orizzontale casuale tra -2 e 2 e un componente verticale, che è determinato nel modulo config.py (attualmente impostato su 3).
def create_ball (self): speed = (random.randint (-2, 2), c.ball_speed) self.ball = Ball (c.screen_width // 2, c.screen_height // 2, c.ball_radius, c.ball_color , velocità) self.objects.append (self.ball)
In questa parte, abbiamo trattato la gestione degli eventi come pressioni dei tasti, movimento del mouse e clic del mouse. Ci siamo anche immersi in alcuni degli elementi di gameplay di Breakout come spostare la paletta, spostare la palla e controllare la velocità della palla.
Ricorda anche di vedere cosa abbiamo a disposizione per la vendita e per studiare nel mercato Envato se stai cercando di studiare altro materiale relativo a Python.
Nella quarta parte, affronteremo l'importante argomento del rilevamento delle collisioni e vediamo cosa succede quando la palla colpisce vari oggetti di gioco come la pagaia, i mattoni e persino le pareti, il soffitto e il pavimento.
Quindi rivolgeremo la nostra attenzione al menu di gioco. Creeremo pulsanti personalizzati che utilizzeremo come menu che possiamo mostrare e nascondere in base alle esigenze.