Projekt Snake
Das Futter platzieren
Kommen wir zur Nahrung der Schlange.
Das Futter besteht aus Quadraten, die genauso groß sind, wie der Kopf der Schlange. In unserem Fall also 10 Pixel breit und 10 Pixel hoch. Um das Futter farblich von der Schlange zu unterscheiden, wählen wir grün.
Das Erscheinen des Futters im Fenster erfolgt genau wie das Erzeugen des
Schlangenkopfes. Wir duplizieren also die Zeilen mit der Anweisung
pygame.draw.rect
.
pygame.draw.rect(fenster, ROT, [snake_x, snake_y, quadrat_seite, quadrat_seite])
und setzen statt "snake" einfach "essen" ein und nehmen als Farbe
GRUEN
:
pygame.draw.rect(fenster, GRUEN, [essen_x, essen_y, quadrat_seite, quadrat_seite])
fertig.
Aber wie finden wir jetzt die Werte für essen_x
und
essen_y
?
Da wird es jetzt etwas knifflig. Mit der Bibliothek random()
haben wir
ja ein Werkzeug, das uns Zufallszahlen aus einem vorher definierten Zahlenpool
liefert, also eigentlich kein Problem.
Ich greife mal vor auf das nächste Kapitel. Wie prüfen wir, dass die Schlange das Essen gefunden hat?
Na, wennsnake_x
undessen_x
gleich sind UND wennsnake_y
und essen_y gleich sind, dann ist die Schlange genau über dem Futter.
Und das ist auch schon der Knackpunkt. Die Schlange bewegt sich in 10er Schritten nach links, rechts, oben und unten. Sollte die Funktionrandom()
die x-Position 142 ausgewählt haben, schaffen wir es nie, unseren Happen zu essen, weil wir entweder mit x = 140 oder x = 150 ankommen.
Blöd...
Ich habe mir nun überlegt, dass random()
sich gleich aus 10er
Schritten bedienen soll, sowohl für die
Wir erstellen und also 2 Listen, eine für die Werte der
Das lassen wir vor der Spielschleife tun, damit diese das ganze Spiel über zur
Verfügung stehen. Dazu wird eine neue Funktion bereitgestellt
(futter_vorbereiten()
), den Code gibt es gleich unten.
Schauen wir uns also den Code dazu an:
###################################################
# Definition der Importe
###################################################
import pygame
import random
###################################################
# Definition der Konstanten und Variablen
###################################################
# Werte fuer das Spielefenster
BREITE = 800
HOEHE = 400
# Spielsteuerung
spielen = True
# Farben RGB (Red, Green, Blue), jeweils 0 - 255
ROT = (255,0,0)
GRUEN = (0,255,0)
BLAU = (0,0,255)
WEISS = (255, 255, 255)
SCHWARZ = (0, 0, 0)
# Positionen der oberen linken Ecke des Kopfes
snake_x = 400
snake_y = 200
# Groesse des Quadrats
quadrat_seite = 10
# Bewegungen auf der x- und der y-Achse
snake_bewegung_x = 0
snake_bewegung_y = 0
# Geschwindigkeiten
zeit = pygame.time.Clock()
snake_geschwindigkeit = 20
# Essen zubereiten
# Liste der x-Positionen
liste_essen_x = []
# Liste der y-Positionen
liste_essen_y = []
# Position von x
essen_x = 0
# Position von y
essen_y = 0
###################################################
# Definition der Funktionen
###################################################
def futter_vorbereiten():
print('in futter_vorbereiten')
e_x = 0
e_y = 0
for i in range (0, int(BREITE/quadrat_seite)):
liste_essen_x.append(e_x)
e_x += quadrat_seite
#print('liste_essen_x = ', liste_essen_x)
for j in range (0, int(HOEHE/quadrat_seite)):
liste_essen_y.append(e_y)
e_y += quadrat_seite
#print('liste_essen_y = ', liste_essen_y)
def fenster_definieren():
print('in fenster_definieren')
pygame.init()
f = pygame.display.set_mode((BREITE,HOEHE))
pygame.display.set_caption('Snake - das Schlangenspiel')
return f
def spielschleife_aufrufen():
print('in spielschleife_aufrufen')
global spielen, snake_x, snake_y, quadrat_seite, snake_bewegung_x,\
snake_bewegung_y
essen_x = random.choice(liste_essen_x)
essen_y = random.choice(liste_essen_y)
while spielen:
for event in pygame.event.get():
# print(event)
if event.type == pygame.QUIT:
spielen = False
# die Tastatur abfragen
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
snake_bewegung_x = quadrat_seite
snake_bewegung_y = 0
elif event.key == pygame.K_LEFT:
snake_bewegung_x = quadrat_seite * -1
snake_bewegung_y = 0
elif event.key == pygame.K_UP:
snake_bewegung_x = 0
snake_bewegung_y = quadrat_seite * -1
elif event.key == pygame.K_DOWN:
snake_bewegung_x = 0
snake_bewegung_y = quadrat_seite
# Abfrage, ob die Schlange aus dem Fenster verschwindet.
# Wenn ja, dann hoert das Spiel auf
if snake_x >= BREITE or snake_x < 0 or snake_y >= HOEHE or snake_y < 0:
print('Verloren!')
spielen = False
# Wenn nein, wird
# - die Veraenderung als neue Position gespeichert
# - und das Fenster wird neu aufgebaut
else:
snake_x += snake_bewegung_x
snake_y += snake_bewegung_y
fenster.fill(SCHWARZ)
pygame.draw.rect(fenster, GRUEN,
[essen_x, essen_y, quadrat_seite, quadrat_seite])
pygame.draw.rect(fenster, ROT,
[snake_x, snake_y, quadrat_seite, quadrat_seite])
pygame.display.update()
zeit.tick(snake_geschwindigkeit)
def spiel_verlassen():
print('in spiel_verlassen')
pygame.quit()
quit()
###################################################
# Programmstart
###################################################
print('Programmstart!')
futter_vorbereiten()
fenster = fenster_definieren()
spielschleife_aufrufen()
spiel_verlassen()
Den Import haben wir ja schon besprochen.
Die Deklaration der (globalen) Variablen erfolgt ab Zeile 42. Zunächst haben wir
die beiden Listen für die Positionen auf der
Die konkreten Werte essen_x
bzw. essen_y
starten mit 0.
Nun zur Funktion futter_vorbereiten()
ab Zeile 54.
Was passiert darin?
Mit e_x
und e_y
haben wir 2 lokale(!) Variablen, die nur in
dieser Funktion angesprochen werden.
Es folgt die Schleife zur Ermittlung der Werte für die int(BREITE/quadrat_seite)
lassen
wir das
Programm selbst bestimmen, wann die Schleife zu Ende ist. Aktuell haben wir 800 /
10, also nach 80 Durchläufen ist Ende.
In der Schleife selbst addieren wir zum aktuellen Wert von e_x
die
Seitenlänge des Quadrats dazu (Zeile 59) und hängen den neuen Wert
e_x
an das Ende der Liste (Zeile 60).
Der erste Eintrag in der Liste ist also die 0, der zweite die 10 und so weiter, der 80. Eintrag ist dann 790.
Klar soweit, oder? Falls nicht, aktiviert mal die Ausgaben in der Zeile 61, dann wird das klar.
Die 2. Schleife erstellt analog die Liste für die Werte des
In der Spielschleife selbst, müssen wir auch Änderungen vornehmen, diese sind ab Zeile 81 zu finden.
Bevor es in die Schleife geht, besorgen wir uns eine
Das Ausgeben des Futter-Quadrats machen wir direkt vor dem Ausgeben der Schlange, also in den Zeilen 118-119.
Jetzt bleibt uns nur noch, die Funktion futter_vorbereiten()
aufzurufen,
dazu fügen wir Zeile 138 ein.
Prima, damit sind wir auch mit der Erstellung des Futters und der Platzierung im Fenster durch.
Wenn wir das Programm laufen lassen, sieht das bei mir so aus:Allerdings macht das jetzt noch nicht so viel Spaß, weil die Schlange das Futter nicht aufnimmt.
Genau das gehen wir im nächsten Kapitel an.
Inhaltsverzeichnis:
1. Vorwort2. Das Projekt
3. Vorarbeiten
4. Projekt Snake
4.1. Der Funktionsumfang
4.2. Die Planung der Umsetzung
4.3. Das Coden
4.3.1. Das Grundgerüst
4.3.2. Das Fenster
4.3.3. Der Schlangenkopf
4.3.4. Die Bewegung der Schlange
4.3.5. Kleine Verbesserungen
4.3.6. Das Futter platzieren
4.3.7. Die Schlange wächst
4.3.8. Den Spielstand ausgeben
4.3.9. Die Wiederholung
4.3.10. Der finale Stand
5. Abschluss