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

anzeigen verstecken

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 und vy
    • 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

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

anzeigen verstecken

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)

anzeigen verstecken

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)
anzeigen verstecken

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)
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)

anzeigen verstecken

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
anzeigen verstecken

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
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
46
47

# Aufgaben

Aufgabe : Spiel auswählen

Schaue dir die 4 vorgeschlagenen Spielideen an. Kennst du sie bereits? Wähle ein Spiel aus das du programmieren möchtest.

Aufgabe : 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.)

Aufgabe : 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!

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

Aufgabe : Testdurchführung

Lasse deine Kolleg*innen ans Steuer und lass dir Rückmeldungen zu deinem Spiel geben!

Letzte Änderung: 14.1.2020, 20:23:01