Sito web di notizie tecnologiche e videogames.

Pygame Shooter Parte 10: Lo scudo per il player

1

Questo articolo è la decima parte del progetto PyShooter, oggi vedremo come aggiungere uno scudo protettivo alla navicella ed una barra per visualizzarne lo stato.

Aggiungere uno scudo

Nello stato attuale del nostro videogioco la navicella è distrutta dalla collisione con una singola meteora, per questo aggiungiamo un attributo ‘shield’ al nostro player.

class Player(pygame.sprite.Sprite):
    def __init__(self):
        self.speedx = 0
        # valore iniziale dello scudo
        self.shield = 100

Ogni volta che il player è colpito da una meteora diminuiamo il valore di shield. Quando lo scudo raggiunge il valore 0 il player è distrutto.

Per rendere il gioco più interessante possiamo fare in modo che le meteore più grandi infliggano un danno maggiore al player rispetto a quelle più piccole.

Danneggiare il player

Attualmente il nostro sistema di gestione delle collisioni tra i mob ed il player è molto semplice:

# check to see if a mob hit the player   
hits = pygame.sprite.spritecollide(player, mobs, False, pygame.sprite.collide_circle)   
if hits:       
    running = False 

Dobbiamo quindi fare un paio di modifiche:

hits = pygame.sprite.spritecollide(player, mobs, True, pygame.sprite.collide_circle)
    for hit in hits:
        player.shield -= hit.radius * 2
        if player.shield <= 0:
            running = False

NB: Da notare come nella funzione spritecollide() abbiamo cambiato il valore booleano da False a True. Questo perché vogliamo che nel momento in cui un mob collide con il player venga eliminato. Se non eliminassimo il mob verrebbero registrate collisioni per ogni frame in cui il mob continua a toccare il player!

In questo modo scorriamo la lista hits e per ogni hit sottraiamo un valore da shield basandoci sul valore del raggio della meteora. Così facendo maggiore sarà il raggio della meteora, maggiore sarà il danno inflitto. Una volta che il valore di shield arriva a 0 il gioco sarà terminato.

Dato che ogni volta che viene rilevata una collisione un mob viene eliminato il numero di mob totali nel gioco diminuisce.
Questo è il modo in cui spawniamo i mob nel videogioco:
for i in range(8):
    m = Mob()
    all_sprites.add(m)
    mobs.add(m)

Dato che avremo bisogno di richiamare queste istruzioni ogni volta che un mob viene eliminato creiamo una funzione newmob() che ha proprio quelle istruzioni:

def newmob():
    m = Mob()
    all_sprites.add(m)
    mobs.add(m)

A questo punto non dobbiamo fare altro che richiamare la funzione all’inizio del programma e quando viene rilevata una collisione tra un bullet ed un mob e tra un mob ed il player.

for i in range(8):
    newmob()
# check to see if a bullet hit a mob
hits = pygame.sprite.groupcollide(mobs, bullets, True, True)
for hit in hits:
    score += 50 - hit.radius
    random.choice(expl_sounds).play()
    newmob()
# check to see if a mob hit the player
hits = pygame.sprite.spritecollide(player, mobs, True, pygame.sprite.collide_circle)
for hit in hits:
    player.shield -= hit.radius * 2
    newmob()
    if player.shield <= 0:
        running = False

Pygame Shooter Parte 10: Lo scudo per il player

Shield bar

A questo punto non dobbiamo fare altro che disegnare sullo schermo una barra che visualizzi lo stato dello shield in modo che esso sia visibile all’utente.

Aggiungiamo quindi la seguente funzione al nostro programma:

def draw_shield_bar(surf, x, y, pct):
    if pct < 0:
        pct = 0
    BAR_LENGTH = 100
    BAR_HEIGHT = 10
    fill = (pct / 100) * BAR_LENGTH
    outline_rect = pygame.Rect(x, y, BAR_LENGTH, BAR_HEIGHT)
    fill_rect = pygame.Rect(x, y, fill, BAR_HEIGHT)
    pygame.draw.rect(surf, GREEN, fill_rect)
    pygame.draw.rect(surf, WHITE, outline_rect, 2)

Questa funzione disegna una barra BAR_LENGTH * BAR_HEIGHT alla posizione (x, y) di contorno bianco e al suo interno disegna una ulteriore barra di colore verde di lunghezza proporzionale al valore di shield.

Richiamiamo quindi la funzione nel game loop:

draw_text(screen, str(score), 18, WIDTH / 2, 10)
draw_shield_bar(screen, 5, 5, player.shield)
Link al codice: code

 

Commenti