Python Tutorial
- jetzt Python programmieren lernen

Gegner abschießen – Berechnung, wann Geschoss trifft

Jetzt wollen wir auch eine Aktion haben, wenn die Kugel den Gegner trifft. Dazu benötigen wir eine „Collision Detection“ – sprich eine Kontrolle, ob ein Zusammenstoß vorliegt zwischen Kugel und Gegner.

Jetzt kommt eine kleine Portion Mathe ins Spiel – endlich kann man auch mal Schulwissen ergiebig umsetzen. Das Zauberwort bei dem Abstand zwischen zwei Punkten im kartesischen Koordinatensystem basiert auf den Satz des Pythagoras. Damit kann man sich die folgende Formel herleiten, um die Berechnung des Abstands zweier Punkte durchzuführen. Lange her? Egal – wenn man die Formel sieht, darf man nicht erschrecken:

Formel für die Berechnung des Abstands zweier Punkte
Formel für die Berechnung des Abstands zweier Punkte

Also wenden wir diese Formel für die Berechnung des Abstands zweier Punkte einfach an.

Grundsätzlich benötigen wir nun auch das Python-Modul „math“, das wir am Anfang unseres Python-Programms importieren:

# Importieren u. initialisieren der Pygame-Bibliothek
import pygame
from pygame.locals import *
import random
import math

Dazu Erstellen wir eine neue Funktion in Python mit dem Namen „kollisionskontrolle()“.

In dieser Funktion benötigen wir für die Berechnung die Position unserer Kugel (X wie Y) wie auch die Position unseres Gegners (X wie Y):

def kollisionskontrolle(kugelX, kugelY, gegnerX, gegnerY):
    abstand = math.sqrt(math.pow(kugelX-gegnerX,2) + math.pow(kugelY-gegnerY,2))
    print("Abstand zwichen Kugel und Gegner: ", abstand)

Wir lassen uns in der Konsole nun auch die Werte für den Abstand zwischen Kugel und Gegner ausgeben. Hier sieht man schön den Abstand (mit zig Nachkommastellen). Das ist deutlich zu viel der Genauigkeit. Also lassen wir uns einfach Ganzzahlen über int() zurückliefern.

def kollisionskontrolle(kugelX, kugelY, gegnerX, gegnerY):
    abstand = int( math.sqrt(math.pow(kugelX-gegnerX,2) + math.pow(kugelY-gegnerY,2)) )
    print("Abstand zwischen Kugel und Gegner: ", abstand)

Und jetzt können wir einfach festlegen, wenn die Kugel trifft. Wir lassen uns von der Funktion „True“ zurückliefern, wenn die Distanz unter 25 liegt und „False“, wenn die Kugel weiter vorbei geht.

def kollisionskontrolle(kugelX, kugelY, gegnerX, gegnerY):
    abstand = int( math.sqrt(math.pow(kugelX-gegnerX,2) + math.pow(kugelY-gegnerY,2)) )
    # print("Abstand zwischen Kugel und Gegner: ", abstand)

    if abstand < 25:
        return True
    else:
        return False

Wenn man genau hinsieht, merkt man, dass die Kugel auch oberhalb trifft aber nicht die komplette Gegnerfigur am unteren Bereich. Diese Ungenauigkeit kommt daher, dass wir für die Berechnung die Punkt 0,0 von den Grafiken nehmen. Aber unsere Kugel ist 19 hoch und der Gegner hat eine Höhe von 50. Wenn wir also eine Y-Korrektur von 25 vornehmen, dass sollte das Treffen deutlich besser passen – zusätzlich noch eine Korrektur bei X um 30 (was der Kugelbreite entspricht):

def kollisionskontrolle(kugelX-30, kugelY+25, gegnerX, gegnerY):

Und können nun können wir auf einen Treffer entsprechend reagieren:

    if kugelstatus == True:
        kugelX += kugelXbewegung

        if kollisionskontrolle(kugelX,kugelY,gegnerX, gegnerY) == True:
            # Kugel hat getroffen
            print("Kugel hat getroffen")
            kugelstatus = False

        if kugelX > W:
            kugelstatus = False

Natürlich wollen wir auch Siegpunkte für einen Treffer. Also führen wir eine Variable für die Siegpunkte mit dem aussagekräftigen Namen „siegpunkte“ ein und bei jedem Treffer wird diese um 1 erhöht und in der Konsole ausgeben.

        if kollisionskontrolle(kugelX,kugelY,gegnerX, gegnerY) == True:
            # Kugel hat getroffen
            # print("Kugel hat getroffen")
siegpunkte += 1
print("aktueller Stand der Siegpunkte: ", siegpunkte)
            kugelstatus = False

Testen

Hier der bisherige Code komplett:

# Importieren u. initialisieren der Pygame-Bibliothek
import pygame
from pygame.locals import *
import random
import math
pygame.init()

# Variablen/KONSTANTEN setzen
W, H = 800, 600
FPS  = 30
SCHWARZ = ( 0, 0, 0)
WEISS   = ( 255, 255, 255)

spielaktiv = True

spieler = pygame.image.load("bilder/biene-sprite-sheet.png")
bereich = ['','','','','','']
bereich[0] = (0,0,100,100)
bereich[1] = (101,0,100,100)
bereich[2] = (202,0,100,100)
bereich[3] = (303,0,100,100)
bereich[4] = (404,0,100,100)
bereich[5] = (505,0,100,100) 
animbereich = 0

spielerposY = 300
spielerbewegung = 0 

# Gegner
gegnerBild = pygame.image.load("bilder/varroa.png")
# gegnerX = W - 100
gegnerX = random.randint(W/2, W-50)
# gegnerY = 20
gegnerY = random.randint(50, H-50)
gegnerbewegung = 5

# Kugel
kugelBild = pygame.image.load("bilder/honigtropfen.png")
kugelX = 0
kugelY = 0
kugelXbewegung = 12
kugelstatus = False

siegpunkte = 0

# Definieren und Öffnen eines neuen Fensters
fenster = pygame.display.set_mode((W, H))
pygame.display.set_caption("Varroa Invaders")
clock = pygame.time.Clock()

def gegner(x, y):
    fenster.blit(gegnerBild, (x, y))

def kugelfliegt(x, y):
    fenster.blit(kugelBild, (x, y))

def kollisionskontrolle(kugelX, kugelY, gegnerX, gegnerY):
    abstand = int( math.sqrt(math.pow(kugelX-gegnerX,2) + math.pow(kugelY-gegnerY,2)) )
    # print("Abstand zwichen Kugel und Gegner: ", abstand)

    if abstand < 25:
        return True
    else:
        return False

# Schleife Hauptprogramm
while spielaktiv:
    # Überprüfen, ob Nutzer eine Aktion durchgeführt hat
    for event in pygame.event.get():
        # Beenden bei [ESC] oder [X]
        if event.type==QUIT:
            spielaktiv = False

        if event.type == KEYDOWN:
            # print("Spieler hat Taste gedrückt")

            # Taste für Spieler 1
            if event.key == K_UP:
                # print("Spieler hat Pfeiltaste hoch gedrückt")
                spielerbewegung = -6
            elif event.key == K_DOWN:
                # print("Spieler hat Pfeiltaste runter gedrückt")
                spielerbewegung = 6
            elif event.key == K_ESCAPE:
                spielaktiv = False

            elif event.key == K_SPACE:
                # print("Kugel abfeuern")
                # nur möglich, wenn keine Kugel sichtbar ist
                if kugelstatus == False:
                    kugelstatus = True
                    kugelX = 200
                    kugelY = spielerposY+50

        if event.type == KEYUP:
            # print("Spieler stoppt bewegung")
            spielerbewegung = 0

    # Spiellogik
    if spielerbewegung  != 0:
        spielerposY += spielerbewegung 

    if spielerposY < 0:
        spielerposY = 0
        spielerbewegung = 0 

    if spielerposY > H - 90:
        spielerposY = H - 90
        spielerbewegung = 0 

    gegnerY += gegnerbewegung

    if gegnerY < 10:
        gegnerbewegung *= -1
        gegnerX -= 30

    if gegnerY > H - 50:
        gegnerbewegung *= -1
        gegnerX -= 30

    if kugelstatus == True:
        kugelX += kugelXbewegung

        if kollisionskontrolle(kugelX,kugelY,gegnerX, gegnerY) == True:
            # Kugel hat getroffen
            # print("Kugel hat getroffen")
            siegpunkte += 1
            print("aktueller Stand der Siegpunkte: ", siegpunkte)
            kugelstatus = False

        if kugelX > W:
            kugelstatus = False

    # Spielfeld löschen
    fenster.fill(WEISS)

    # Spielfeld/figuren zeichnen
    animbereich  += 1

    if animbereich  > 5:
        animbereich  = 0

    fenster.blit(spieler, (100, spielerposY), bereich[animbereich])    

    if kugelstatus == True:
        kugelfliegt(kugelX,kugelY)

    gegner(gegnerX, gegnerY)

    # Fenster aktualisieren
    pygame.display.flip()
    clock.tick(FPS)

Wenn wir jetzt den einzigen Gegner killen, wäre das Spiel sofort aus. Also brauchen wir dringend mehr Gegner. Im nächsten Kapitel erzeugen wir jede Menge Gegner getreu dem Motto: „viel Gegner, viel Ehr“.