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?

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
Schwarze Pfeile
zeigen die Verwendung der Objekte der Klassen an. So besitzt das Board eine Liste von Crates, ein Objekt vom Typ Character und eine zwei-dimensionale Liste von Tiles.
Weisse Pfeile
weisen auf Vererbung hin. So erben Ground, Goal und Wall von der Klasse Tile und Crate und Character 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:

#####
#@$.#
#####
1
2
3

Ein etwas spannender Level ist hier abgebildet:

    #####
    #   #
    #$  #
  ###  $##
  #  $ $ #
### # ## #   ######
#   # ## #####  ..#
# $  $          ..#
##### ### #@##  ..#
    #     #########
    #######
1
2
3
4
5
6
7
8
9
10
11

Hier findest du eine Sammlung von Sokoban-Levels im xsb-Format (TODO)

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:

with open('level1.xsb') as f:
	for line in f:
		print(line)
1
2
3

Aufgabe: Levels lesen

Versuch 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:

SpielerKisteZielWandBoden

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

Andere mögliche Grafikpakete die eingesetz werden können.
👉 OpenGameArt
👉 PlanetCute

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.

👉 https://www.pygame.org

Darstellung

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()
1
2
3
4
5
6
7
8
9
10
11
12
13
14

Aufgabe: Level zeichnen

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

Steuerung

...
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.up()
			elif event.key == pygame.K_DOWN:
				player.down()
...
1
2
3
4
5
6
7
8
9
10
11

Aufgabe: Steuerung

Baue die Steuerung ein und bewege damit deinen Spieler auf dem Spielfeld