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:
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“.