Ladeebene#

A typical use case: You want to start a new level when the on-screen character reaches the edge or goes through a door, etc.

This is how it goes:

  • Save your level in a database, a text file, or a simple list.

  • You need a function that loads your level as soon as something happens (you reach the edge, touch an actor, …)

Speichern deiner Ebene als Liste#

You can store your level in a multidimensional list. In a very simple case, it might look like this, for example:

r00 = [    "  d",
           "  w",
           "www"]

You will then need a translation in Actors, w stands for a Wall, d for a Door.

You can then store the rooms in a list or as a dictionary, for example, like this as a list:

rooms = [r00, r01]

…oder so als Wörterbuch:

rooms = {0: r00, 1: r01}

Creating classes for the individual objects#

In order to create an object of a specific type, it makes sense to store a class for this object.

This could look like this, for example:

class Wall(Actor):
    def on_setup(self):
        self.add_costume("wall")

The class Wall defines objects that behave like actors but differ from the standard actor in that they always have an image of a wall as a costume.

Translating the list#

You can now translate the list into Actors:

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) 

First, in the first for-loop, all actors except the player object are deleted

In the second loop, the lists are now iterated over. Each time a corresponding actor is found in the string list, a corresponding actor is created.

Changing the room#

With the preliminary work, it is easy to change the room: You just have to call the setup_room method at the appropriate place to change the room, for example like this:

    def on_key_down(self, keys):
        global r01
        if "SPACE" in keys:
            if self.detect_actor(Wall):
                setup_room(rooms[1]) 

Here is what the entire program might look like:

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

Once a player stands on the door and presses the space bar, the room will change.

Raumwechsel