Pygame 4

In de vorige opgave werden reeds botsingen gedetecteerd tussen onze kogel en het vijandelijke ruimteschip. We speelden een geluid af als we raak geschoten hadden, maar helaas leek er iets niet te kloppen. Je geluid werd meermaals afgespeeld, en je zag ook meermaals ‘hit’ op het scherm verschijnen. Dit is omdat de kogel het ruimteschip raakte, maar zowel de kogel als de vijand verdwenen niet, waardoor de kogel het ruimteschip opnieuw bleef raken zolang ze elkaar overlapten.

Opgave 25

We passen in de code de gegevens die we bijhouden over het vijandelijk ruimteschip uit met het al dan niet in geraakt zijn van het vijandelijke ruimteschip. We gebruiken hiervoor een variabele van het type “bool”.

Hieronder vinden jullie de onvolledige code voor deze aanpassing. Bekijk de regels gemarkeerd met ‘nieuw’ aandachtig, en pas ze aan zodat een kogel de vijand slechts eenmaal raakt.

import random
import pygame
from pygame import Rect

WIDTH = 800
HEIGHT = 600

pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))

# Start de klok
clock = pygame.time.Clock()


sound = pygame.mixer.Sound("bow.wav")
explosion = pygame.mixer.Sound("explosion.wav")
player = pygame.image.load("ship.png")
bullet = pygame.image.load("bullet.png")
enemy = pygame.image.load("enemyship.png")


# Positie van de speler, en verplaatsing van de speler
x = WIDTH / 2
y = HEIGHT - 110
xchange = 0
ychange = 0

# Positie van de kogel, en verplaatsing van de kogel
bullet_x = 0
bullet_y = 0
bullet_x_change = 0
bullet_y_change = 0

# Positie van de vijand, en verplaatsing van de vijand
enemy_alive = # nieuw: leeft de vijand nog?
enemy_x = WIDTH - 200
enemy_y = 0
enemy_x_change = 0
enemy_y_change = 1


running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                sound.play()
                bullet_x = x
                bullet_y = y
                bullet_y_change = -5
            elif event.key == pygame.K_LEFT:
                xchange = -1.5
            elif event.key == pygame.K_RIGHT:
                xchange = 1.5
            elif event.key == pygame.K_UP:
                ychange = -1.5
            elif event.key == pygame.K_DOWN:
                ychange = 1.5
        elif event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT:
                xchange = 0
            elif event.key == pygame.K_RIGHT:
                xchange = 0
            if event.key == pygame.K_UP:
                ychange = 0
            elif event.key == pygame.K_DOWN:
                ychange = 0
    # Verplaats de speler
    x += xchange
    y += ychange

    # Verplaats de kogel
    bullet_y += bullet_y_change

    if enemy_alive:  # nieuw: Als de vijand nog leeft, doe dan het volgende
        # Verplaats de vijand
        enemy_x += enemy_x_change
        enemy_y += enemy_y_change

        # Als de vijand buiten het scherm gaat,
        # plaats hem dan terug bovenaan het scherm
        if enemy_y > HEIGHT:
            enemy_y = 0
            enemy_x = random.randint(0, WIDTH)

        # Kijk of er een botsing is
        enemy_rect = Rect(enemy_x, enemy_y, 32, 32)
        bullet_rect = Rect(bullet_x, bullet_y, 8, 8)
        if enemy_rect.colliderect(bullet_rect):
            explosion.play()
            print("hit")
            enemy_alive =  # nieuw: Wat is de nieuwe status van de vijand?

    # Teken de speler, de vijand en  de kogel
    screen.fill("white")
    screen.blit(player, (x, y))
    screen.blit(enemy, (enemy_x, enemy_y))
    screen.blit(bullet, (bullet_x, bullet_y))

    pygame.display.flip()

    # Wacht zodanig dat we maximal 60 FPS halen
    clock.tick(60)

Link naar opgave25.py

Opgave 26

Hoewel we in de vorige opdracht het ruimteschip raakten, veranderde er visueel niets aan het ruimteschip.

_images/enemyship_slain.png

Pas de code in opgave 25 aan zodat je na het raken van een vijandelijk ruimteschip, de nieuwe afbeelding gebruikt bij het tekenen van het vijandelijk ruimteschip.

Dit doe je door:

  • De nieuwe afbeelding in te laden net zoals je de kogel, je eigen ruimteschip, en het vijandelijk ruimteschip nu al inlaadt.

  • Bij het raken van het ruimteschip, de afbeelding ‘enemy’ te vervangen door ‘enemy_slain’.

Meerdere kogels

Je hebt vast gemerkt dat hoeveel je ook schiet, je slechts 1 kogel op het scherm kan doen verschijnen. De vorige kogel lijkt te verdwijnen zodra je een tweede maal schiet. De reden hiervoor is dat we ook slechts informatie over 1 kogel bijhouden in ons spel:

# Positie van de kogel, en verplaatsing van de kogel
bullet_x = 0
bullet_y = 0
bullet_x_change = 0
bullet_y_change = 0

Je zou een tweede kogel kunnen toevoegen, door nieuwe variabelen te introduceren:

# Positie van kogel 2, en verplaatsing van kogel 2
bullet2_x = 0
bullet2_y = 0
bullet2_x_change = 0
bullet2_y_change = 0

Maar, dit zou snel problematisch worden als je vele kogels zou willen afvuren.

Merk trouwens op, dat we eigenlijk niet alle gegevens per kogel hoeven bij te houden. We kunnen veronderstellen dat iedere kogel even snel vliegt, en dan per kogel enkel een nieuw paar x- en y-coördinaten bijhouden:

# Positie van de kogel, en verplaatsing van de kogel
bullet_x_change = 0
bullet_y_change = 0

bullet1_x = 0
bullet1_y = 0
bullet2_x = 0
bullet2_y = 0

Hoewel dit de code een beetje eenvoudiger maakt, is ook deze code niet praktisch bruikbaar als je veel kogels wil kunnen afschieten.

Wat we zouden willen doen, is zoveel kogels afschieten als we willen, en het programma de posities van alle kogels laten bijhouden. Dit kunnen we doen door gebruik te maken van een lijst:

# Positie van de kogel, en verplaatsing van de kogel
bullet_x_change = 0
bullet_y_change = 0

# Een Python lijst waarin we de coördinaten van kogels bijhouden
bullets = [
    0, 0, # bullet1_x, bullet1_y
    0, 0, # bullet2_x, bullet2_y
]