Lernziele
Wir vertiefen unsere Programmierkenntnisse bei einem grösseren Projekt. Dabei erlernen wir Grundzüge der Softwareentwicklung kennen
# Softwareentwicklung
Bei der Softwareentwicklung wird nicht einfach drauflosprogrammiert. Oft macht das eigentliche «Coden» nur einen geringen Teil der Arbeit aus. Diese wird häufig in die folgenden vier Teile unterteilt:
- Spezifikation
- Was soll unser Programm/Spiel können?
- Design
- Wie können wir das umsetzen?
- Realisierung
- Die Umsetzung in der Programmiersprache – das «Coden»
- Testdurchführung
- Testen und ausprobieren
# Spielideen
# Pong
Der Spieleklassiker aus zwei Schlägern und einem Ball. Die Schläger lassen sich mit der Tastatur steuern. Der Ball bewegt sich von selbst und prallt an den Schlägern und den Rändern oben und unten ab. Wenn er den linken oder rechten Rand erreicht gibt’s Punkte für den Spieler auf der anderen Seite.
https://de.wikipedia.org/wiki/Pong (opens new window)
Tipp
Elemente:
- 2 Schläger:
- Actor
- können vom Spieler in vertikaler Richtung verschoben werden
- horizontal sind die Positionen fix
- Ball:
- Actor mit Geschwindigkeits-Komponenten
vx
undvy
- prallt oben und unten am Rand ab (
vy = -vy
) - prallt am Schläger ab (
vx = -vx
) - wenn rechter oder linker Rand berührt, Punkt für linken resp. rechten Spieler
- Actor mit Geschwindigkeits-Komponenten
Erweiterungen:
- Anfangsrichtung des Balls zufällig
- Punkte zählen
- Abprallen an Schläger variieren, je nachdem ob in der Mitte oder am Rand
# Asteroids
Der Spieler steuert ein Raumschiff und muss dabei Asteroiden ausweichen. Als Erweiterung können Asteroiden beschossen werden. Sie zerfallen dabei in mehrere kleine Asteroiden.
https://de.wikipedia.org/wiki/Asteroids (opens new window)
Tipp
Elemente:
- Raumschiff
- Actor
- hat Winkel und Geschwindigkeit
- Bewegung (Verschiebung x- und y-Richtung) mit Sinus und Cosinus berechnen
- kann vom Spieler gedreht, beschleunigt und gebremst werden
- Asteroiden:
- Actors
- entstehen zufällig ausserhalb des Spiels
- Bewegen sich ins Spielfeld hinein
Ausbaustufen:
- Kollision zwischen Raumschiff und Asteroiden
- Raumschiff kann schiessen
- Asteroiden zerfallen bei Treffer in kleinere Asteroiden
# Snake
Der Spieler kontrolliert eine Schlange und sammelt Gegenstände. Dabei wird die Schlange immer länger. Fährt man in ein Hindernis oder in sich selbst, verliert man.
https://de.wikipedia.org/wiki/Snake_(Computerspiel) (opens new window)
Tipp
Die Schlange als Liste von Actors:
- bei jedem Schritt ein neuer Actor (Schlangenkopf) vorne anhängen
- der Actor wird gar nie bewegt, die Bewegung entsteht durch hinzufügen eines neuen Elements reps. entfernen des hintersten Elements
- Kopf braucht Geschwindigkeit in x- und y-Richtung
- mit den Steuerungstasten ändern diese Geschwindigkeiten
Spielschritt, also neuer Kopf nicht in Update, sondern mit clock.schedule_interval
z.B. alle Zehntel-Sekunde.
Erweiterungen:
- Items erscheinen zufällig und lassen sich einsammeln
- Hindernisse erscheine zufällig und dürfen nicht berührt werden
- eigene Schlange darf nicht berührt werden
- Schlange wächst (mit der Zeit oder dank Einsammeln)
Lösung
KACHEL_GROESSE = 12
WIDTH = 80*KACHEL_GROESSE
HEIGHT = 60*KACHEL_GROESSE
schlange = []
schlangen_laenge = 10
schlangen_kopf = Actor("yellow")
schlangen_kopf.vx = 1
schlangen_kopf.vy = 0
schlange.append(schlangen_kopf)
def draw():
screen.clear()
for teil in schlange:
teil.draw()
def on_key_down(key):
schlangen_kopf = schlange[len(schlange)-1]
if key == keys.W:
schlangen_kopf.vx = 0
schlangen_kopf.vy = -1
elif key == keys.S:
schlangen_kopf.vx = 0
schlangen_kopf.vy = 1
elif key == keys.D:
schlangen_kopf.vx = 1
schlangen_kopf.vy = 0
elif key == keys.A:
schlangen_kopf.vx = -1
schlangen_kopf.vy = 0
def bewege_schlange():
schlangen_kopf = schlange[len(schlange)-1]
neuer_kopf = Actor("yellow")
neuer_kopf.x = schlangen_kopf.x + KACHEL_GROESSE*schlangen_kopf.vx
neuer_kopf.y = schlangen_kopf.y + KACHEL_GROESSE*schlangen_kopf.vy
neuer_kopf.vx = schlangen_kopf.vx
neuer_kopf.vy = schlangen_kopf.vy
schlange.append(neuer_kopf)
if len(schlange) > schlangen_laenge:
schlange.pop(0)
clock.schedule_interval(bewege_schlange, 0.1)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# Tron
Variante von Snake: Zwei Spieler bewegen ihre Figur über die Bühne, die Figur hinterlässt einen Strich. Wenn man in den gegnerischen (oder den eigenen) Strich reinfährt hat man verloren.
https://de.wikipedia.org/wiki/Tron_(Computerspiel) (opens new window)
Tipp
Das Gefährt hinterlässt eine Spur:
- man könnte z.B. den Bildschirm einfach nicht löschen im update-Unterprogramm
- oder man setzt die Spur aus einer Liste von Actor zusammen (analog zu snake)
- oder man zeichnet die Pixel der Spur auf ein
surface
– dazu braucht man aber einige Befehlt von pygame (ohne zero)
In allen Fällen kann man sich die durchgefahrenen Positionen in einer Liste von Koordinaten merken. So kann eine Kollision einfacher entdeckt werden.
Erweiterungen:
- zweiter Spieler
- Punkte zählen
Lösung
Diese Lösung verwendet Elemente von pygame (ohne Zero): Der gefahrene Pfad wird Pixelweise gezeichnet und dann um den Faktor 5 vergrössert und mit dem pygame zero-Bild gemischt!
Denkbar wäre auch ein Gefährt so wie bei der Lösung von «Snake».
from pygame import Surface
from pygame import transform
WIDTH = 800
HEIGHT = 800
KACHEL_GROESSE = 5
BLACK = (0, 0, 0)
spur_bild = Surface((round(WIDTH / KACHEL_GROESSE), round(HEIGHT / KACHEL_GROESSE)))
geschwindigkeit = KACHEL_GROESSE
toeff = Actor('green', anchor_x=28)
spur_bild.fill(BLACK)
toeff.pos = (WIDTH + KACHEL_GROESSE) // 2, (HEIGHT + KACHEL_GROESSE) // 2
toeff.vx = geschwindigkeit
toeff.vy = 0
toeff.spur = []
def update():
toeff.x = toeff.x + toeff.vx
toeff.y = toeff.y + toeff.vy
spur_position = (round(toeff.x / KACHEL_GROESSE), round(toeff.y / KACHEL_GROESSE))
spur_bild.set_at(spur_position, (255, 255, 255))
if spur_position in toeff.spur:
exit()
toeff.spur.append(spur_position)
def draw():
transform.scale(spur_bild, (WIDTH, HEIGHT), screen.surface)
toeff.draw()
def on_key_down(key):
if key == keys.RIGHT:
toeff.vx = geschwindigkeit
toeff.vy = 0
elif key == keys.DOWN:
toeff.vx = 0
toeff.vy = geschwindigkeit
elif key == keys.LEFT:
toeff.vx = -geschwindigkeit
toeff.vy = 0
elif key == keys.UP:
toeff.vx = 0
toeff.vy = -geschwindigkeit
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# Aufgaben
Spiel auswählen
Schaue dir die 4 vorgeschlagenen Spielideen an. Kennst du sie bereits? Wähle ein Spiel aus das du programmieren möchtest.
Spezifikationen
Notiere stichwortartig was das Spiel können soll. Erstelle ev. Skizzen. Achte darauf, dass du ein simples Minimalprodukt formulierst, und nicht ganz so wichtige Dinge als Zusätze notierst. (Das Spiel sollte spielbar sein. Wenn aber keine Punkte gezählt werden, ist das nicht so schlimm.)
Design
Lies deine Spezifikationen durch und überlege dir, wie du das Umsetzen kannst:
- Welche Actor brauchst du?
- Welche Bilder müssen verwendet werden? (einen Startsatz an Bildern ist auf Teams verfügbar)
- Wie kann die Figur gesteuert werden?
- Welche Eigenschaften hat die Figur? (Geschwindigkeit, Richtung, Punkte, Leben, …)
- Wie bewegt sich die Figur?
- …
Mache wiederum einige Notizen zu deinem Vorhaben. Ev. helfen grafische Darstellungen!
Realisierung
Programmiere einen ersten kleinen Teil deines Spiels. Beginne z.B. mit der Hauptfigur und deren Steuerung. Füge weitere Figuren und den Hintergrund hinzu. Erstelle Kollisionsabfragen und zähle Punkte, usw.
Testdurchführung
Lasse deine Kolleg*innen ans Steuer und lass dir Rückmeldungen zu deinem Spiel geben!