Level Loading#
Ein typischer Anwendungsfall: Du möchtest ein neues Level starten, wenn die Bildschirmfigur den Rand erreicht oder durch eine Tür geht, usw.
Dies geht folgendermaßen:
Speichere dein Level in einer Datenbank, einer Textdatei oder einer einfachen Liste.
Du brauchst eine Funktion, die dein Level lädt, sobald etwas passiert (du erreichst den Rand, berührst ein Actor, …)
Speichern deines Levels als Liste#
Du kannst dein Level in einer mehrdimensionalen Liste speichern. In einem ganz einfachen Fall könnte dies z.B. so aussehen:
r00 = [ " d",
" w",
"www"]
Du brauchst dann eine Übersetzung in Actors, w
steht hier für eine Wall
, d
für eine Door
.
Die Räume kannst du dann in einer Liste oder als Dictionary speichern, z.B. so als Liste:
rooms = [r00, r01]
…oder so als Dictionary:
rooms = {0: r00, 1: r01}
Anlegen von Klassen für die einzelnen Objekte#
Damit ein Objekt einer bestimmten Art erzeugt werden kann, ist es sinnvoll, eine Klasse für dieses Objekt zu speichern.
Dies könnte z.B. so aussehen:
class Wall(Actor):
def on_setup(self):
self.add_costume("wall")
Die Klasse Wall
definiert Objekte, sich wie Actors verhalten, aber von dem Standard-Actor insofern unterscheidet, dass diese immer als Kostüm ein Bild mit einer Wand besitzen.
Übersetzen der Liste#
Die Liste kannst du nun in Actors übersetzen:
def setup_room(room):
for actor in world.actors:
if actor != player:
actor.remove()
for i, row in enumerate(room):
for j, column in enumerate(row):
x = j
y = i
if room[i][j] == "w":
t = Wall(x, y)
if room[i][j] == "d":
d = Door(x, y)
Zunächst werden in der ersten For-Schleife alle Actors bis auf das Player-Objekt gelöscht
In der zweiten Schleife wird nun über die Listen iteriert. Dabei wird jedesmal, wenn ein entsprechender Actor in der String-Liste gefunden wird, ein entsprechendes Actor angelegt.
Wechseln des Raums#
Mit der Vorarbeit ist es einfach den Raum zu wechseln: Du musst einfach nur die Methode setup_room an geeigneter Stelle aufrufen um den Raum zu wechseln, z.B. so:
def on_key_down(self, keys):
global r01
if "SPACE" in keys:
if self.detect_actor(Wall):
setup_room(rooms[1])
So könnte das ganze Programm aussehen:
from miniworlds import *
world = TiledWorld()
world.columns = 3
world.rows = 3
r00 = [ " d",
" w",
"www"]
r01 = ["w ",
"w ",
"w ",
]
rooms = {0: r00, 1: r01}
class Player(Actor):
def on_setup(self):
self.add_costume("knight")
self.costume.is_rotatable = False
self.layer = 1
def on_key_down_w(self):
self.move_up()
def on_key_down_s(self):
self.move_down()
def on_key_down_a(self):
self.move_left()
def on_key_down_d(self):
self.move_right()
def on_detecting_not_on_world(self):
self.move_back()
def on_detecting_wall(self, other):
self.move_back()
def on_key_down(self, keys):
global r01
if "SPACE" in keys:
if self.detect_actor(Wall):
setup_room(rooms[1])
class Wall(Actor):
def on_setup(self):
self.add_costume("wall")
class Door(Actor):
def on_setup(self):
self.add_costume("door_closed")
@world.register
def on_setup(self):
setup_room(r00)
def setup_room(room):
for actor in world.actors:
if actor != player:
actor.remove()
for i, row in enumerate(room):
for j, column in enumerate(row):
x = j
y = i
if room[i][j] == "w":
t = Wall(x, y)
if room[i][j] == "d":
d = Door(x, y)
player = Player(0, 0)
world.run()
Sobald ein Spieler auf der Tür steht und die Leertaste drückt, wird der Raum gewechselt.