Skip to content

Projekt

Objektorientiertes Programmieren

Sōkoban, japanisch «Lagerhausverwalter» ist ein Spiel, dass 1982 in Japan erstmals erschien. (https://www.sokoban.jp)
Bis heute sind zahlreiche Adaptionen und Erweiterungen erschienen.

Prinzip

Der Spieler befindet sich auf einem Raster, er kann sich in alle 4 Himmelsrichtungen bewegen, sofern keine Hindernisse dort stehen. Ziel ist es, alle Kisten auf ihren Ziel-Platz zu schieben. Kisten können nur vom Spieler weggestossen werden und dies nur, wenn auf der anderen Seite der Kiste keine Mauer und auch keine andere Kiste steht.

Aufgabe: Kennenlernen

Hier kannst du eine Runde Sokoban spielen:
👉 https://sokoban.info

Spiel-Logik

Wie wollen wir das Spiel programmieren? Wer entscheidet welche Spielzüge möglich sind und wann ein Level beendet ist?

Aufgabe: Regeln

Haltet die Regeln des Spieles möglichst kurz aber komplett schriftlich fest.

Klassen

Welche Klassen wollen wir definieren? Welche Eigenschaften und Methoden sollen die Objekte haben?

Aufgabe: Design

  1. Erarbeitet einen Vorschlag in Zweier- oder Dreiergruppen und notiert diesen.
  2. Stellt den Vorschlag den anderen vor

Wir werden die Vorschläge gemeinsam diskutieren und uns hoffentlich auf ein Design einigen.

Lösung: Design
UML-Diagramm
Diamanten-Pfeile
zeigen die Verwendung der Objekte der Klassen an. So besitzt das Board eine Liste mit den Kisten crates, ein Objekt vom Typ Player und eine zwei-dimensionale Liste mit Elementen vom Typ Tile.
dreieckige Pfeile
weisen auf Vererbung hin. So erben Ground, Goal und Wall von der Klasse Tile; Crate und Player erben von Movable.

Levels

Sokoban-Levels können im sogenannten xsb-Format gespeichert werden. Dabei handelt es sich um eine Text-Datei mit speziellen Zeichen. Die Zeichen beschreiben die Felder des Levels sowie die Start-Position des Spielers.

Zeichen des xsb-Formates
ZeichenElement
#Wand
@Spieler
$Kiste
.Zielfeld
leerer Raum (Boden)
+Spieler auf Zielfeld
*Kiste auf Zielfeld

Der einfachste lösbare Level würde wie folgt aussehen:

txt
#####
#@$.#
#####

Ein etwas spannender Level ist hier abgebildet:

txt
    #####
    #   #
    #$  #
  ###  $##
  #  $ $ #
### # ## #   ######
#   # ## #####  ..#
# $  $          ..#
##### ### #@##  ..#
    #     #########
    #######

Hier findest du eine Sammlung von 50 Sokoban-Levels im xsb-Format als ZIP-Datei.

aus Datei lesen

Levels können direkt aus den Textdateien gelesen werden. Das macht unser Spiel interessant: wir können auf zahlreiche vorgefertigte Levels zugreifen.

Das folgende Code-Beispiel liest eine Textdatei und gibt diese Zeile um Zeile aus:

python
with open('level1.xsb') as f:
	for line in f:
		print(line)
mehr: «with»

Das with-Statement wird in Python zur Behandlung von Exceptions verwendet. Wenn wir nämlich auf eine Datei zugreifen, kann diverses schief gehen: Z.B. wenn die Datei gar nicht existiert, oder das System keine Rechte hat, diese zu lesen.

Wir können auch ohne with von einer Datei lesen. Dann müssen wir uns aber selber um eventuelle Exceptions kümmern (try-Block) und sicherstellen, dass die Datei nach dem Zugriff wieder geschlossen wird (close im finally-Block):

python
file = open('level1.xsb', 'w')
try:
	for line in f:
        print(line)
finally:
	file.close()

Aufgabe: Levels lesen

Versuche die Level einzulesen. Gehe dazu die Textdatei Zeile um Zeile durch. Die Zeilen wiederum gehst du Zeichen um Zeichen durch.

  • Gib für jedes Zeichen des Levels das zugehörige Element aus (mit print)
  • Gib auch die Position auf dem Spielbrett aus, also Koordinaten jedes Elementes

Grafiken

Es können die folgenden Grafiken verwendet werden:

Spieler
Kiste
Ziel
Wand
Boden

Die Bilder stammen von kenney.nl. In seinem Sokoban-Paket findet ihr weitere Bilder womit ihr die oben dargestellte Auswahl anpassen könnt:

Andere mögliche Grafikpakete die eingesetzt werden können.

Aufgabe: Grafiken

Erzeuge eine für dich passenden Bilder-Auswahl:

  • Schau dir die Bilder in den Links an, ev. suchst du weitere Grafik-Pakete
  • speichere für jedes Element des Spiels ein passendes Bild auf deinem Computer ab

Die Bilder sollten natürlich zusammenpassen – vor allem auch in ihren Dimensionen. Sonst wird das Darstellen dann komplizierter!

Pygame

Wir verwenden Pygame, um das Spiel darzustellen und den Spieler zu steuern.

Du kannst Pygame in Thonny als Paket importieren.

Darstellung

Das folgende Beispiel initialisiert Pygame, setzt die Grösse des Fensters, lädt eine Grafik als Spielfigur und zeichnet diese dann in einer Endlosschleife (game-loop) immer wieder an der Position (100,100).

python
import sys, pygame
pygame.init()

size = width, height = 320, 240
screen = pygame.display.set_mode(size)
player = pygame.image.load("player.png")

while True:
	for event in pygame.event.get():
		if event.type == pygame.QUIT:
			sys.exit()

	screen.blit(player, (100,100))
	pygame.display.flip()

Aufgabe: Level zeichnen

Nimm das Programm der Aufgabe «Level lesen» und versuche den eingelesenen Level mit den richtigen Grafiken anzuzeigen

Steuerung

Im game-loop werden auch immer wieder Ereignisse abgefragt – so kann das Spiel gesteuert werden. Wir bauen dazu ein if ein, um das keydown-Event zu überprüfen. Dieses wird beim Runterdrücken einer Taste erzeugt. Wir müssen nur noch überprüfen, um welche Taste es sich handelt:

python
...
while True:
	for event in pygame.event.get():
		if event.type == pygame.QUIT:
			sys.exit()
		if event.type == pygame.KEYDOWN:
			if event.key == pygame.K_UP:
				player.tryMovePlayer(0,-1)
			elif event.key == pygame.K_DOWN:
				player.tryMovePlayer(0,1)
...

Aufgabe: Steuerung

Baue die Steuerung ein und bewege damit deinen Spieler auf dem Spielfeld – noch ohne Einschränkungen.

Logik

Nun muss noch sichergestellt werden, dass nur gültige Züge gemacht werden können, dass sich die Kisten entsprechend verschieben und dass das Spiel merkt, wann der Level gelöst ist.

Aufgabe: Logik

Versuche die Spiellogik einzubauen:

  • Implementiere dazu die Methoden canMove() und move() der Klassen Player und Crate.
  • Zähle wie viele Kisten noch verschoben werden müssen (todo)

Erweiterungen

Einige Ideen für Erweiterungen von Sokoban inkl. Abschätzung des Aufwands resp. der Schwierigkeit (1 bis 4 ⭐):

Score
zählen wie viele Schritte der Spieler bis zur Lösung des Levels braucht
Stats-Overlay
Spiel-Info als Text oder als Status-Bar anzeigen (z.B. Level-Name, Anzahl gemachte Schritte, Anzahl Boxen die noch platziert werden müssen, …)
⭐⭐
Co-Op
Ein kooperativer Modus, wo zwei Spieler einander helfen. Man könnte sich die Kisten übergeben und müsste dann weniger grosse Distanzen zurücklegen.
⭐⭐
Richtung
Den Spieler nicht nur mit einem Bild darstellen, sondern mit 4 Bildern – eines für jede Richtung.
⭐⭐⭐
Auto-Level
bei Level-Ende automatisch den nächsten Level laden
⭐⭐⭐
Undo
Eine Undo-Funktion, so dass man die letzten Schritte rückgängig machen kann
⭐⭐⭐⭐

Gymnasium Kirchenfeld, fts & lem