Level 2–3 – Richtungen & Vektoren

Richtungen verstehen & eine Brücke vor dem Spieler bauen

Lehrer-Hinweise (Richtungen & Chatkommando)

Level-Empfehlung: Klasse 7–9, Level 2–3.

Lernziel: Spielerblick als Vektor lesen, Einheitsvektoren verstehen und in einem Chatkommando nutzen.

Für Chatbefehle, die „vor dem Spieler“ bauen oder prüfen, zählt nur die Blickrichtung als Vektor: kein absolutes „rechts/links“, sondern X/Y/Z und der Einheitsvektor des Spielers.

1. Kompass in Luanti: Achsen & Blickrichtung

Die Welt ist ein Voxel-Gitter, jede Position hat die Adresse (x, y, z). Vektoren beschreiben darauf Richtung und Länge einer Bewegung.

Die Kamera liefert player:get_look_dir() als Einheitsvektor (Länge = 1). Beispiele: Osten (1, 0, 0), Norden (0, 0, 1), diagonal (0.7, 0, 0.7) (nach Normalisierung wieder Länge 1).

Lua: Blickrichtung holen und auf die Ebene projizieren
local player = core.get_player_by_name(name)
if not player then
    return false, "Nur im Spiel nutzbar."
end

-- Blickrichtung (Einheitsvektor), danach y entfernen und neu normalisieren
local dir = player:get_look_dir()
dir.y = 0

-- falls Spieler genau nach oben/unten schaut, Standard-Richtung setzen
if dir.x == 0 and dir.z == 0 then
    dir = { x = 0, y = 0, z = 1 }
else
    dir = vector.normalize(dir)
end

2. Rechts- und Quer-Vektor

Um Breite zu bauen, brauchen wir einen zweiten Vektor, der nach rechts zeigt. Den bekommen wir aus der Drehung auf der Ebene:

Diese Konstruktion entspricht dem Kreuzprodukt mit der Welt-“Up”-Achse. Bei einem Einheits-forward ist right ebenfalls Länge 1.

3. Horizontal bauen: Y auf 0

Für Brücken wollen wir eine Ebene. Darum:

So bleibt der Bau waagerecht, auch wenn der Spieler nach oben/unten schaut.

4. Mini-Rezept für den Brückenbau

5. Chatkommando: Brücke vor dem Spieler

Das Kommando /bridge <laenge> <breite> [node] baut eine flache Brücke vor dem Spieler. Standardblock ist default:wood. Länge 1–50, Breite 1–9.

Schritte im Code:

Lua: /bridge Chatkommando
core.register_chatcommand("bridge", {
    params      = "<laenge> <breite> [node]",
    description = "Baut vor dir eine Bruecke. Standard: default:wood",
    func = function(name, param)
        local len_s, width_s, node =
            param:match("^(%d+)%s+(%d+)%s*(%S*)$")
        if not len_s then
            return false, "Nutze: /bridge <laenge> <breite> [node]"
        end

        local length = tonumber(len_s)
        local width  = tonumber(width_s)
        node = (node and node ~= "") and node or "default:wood"

        if length < 1 or length > 50 then
            return false, "Laenge 1-50 waehlen."
        end
        if width < 1 or width > 9 then
            return false, "Breite 1-9 waehlen."
        end

        local player = core.get_player_by_name(name)
        if not player then
            return false, "Nur im Spiel nutzbar."
        end

        -- Blickrichtung auf Bodenebene, normalisiert
        local forward = player:get_look_dir()
        forward.y = 0
        if forward.x == 0 and forward.z == 0 then
            forward = { x = 0, y = 0, z = 1 }
        else
            forward = vector.normalize(forward)
        end

        local right = { x = forward.z, y = 0, z = -forward.x }

        -- Startpunkt: direkt vor den Fuessen
        local start = vector.round(player:get_pos())
        start.y = start.y - 1

        -- Für Breite auch bei geraden Zahlen symmetrisch verteilen
        local half = math.floor(width / 2)

        for l = 1, length do
            local forward_pos = {
                x = start.x + forward.x * l,
                y = start.y,
                z = start.z + forward.z * l,
            }

            for w = -half, width - 1 - half do
                local p = {
                    x = math.floor(forward_pos.x + right.x * w + 0.5),
                    y = forward_pos.y,
                    z = math.floor(forward_pos.z + right.z * w + 0.5),
                }
                core.set_node(p, { name = node })
            end
        end

        return true, ("Bruecke gebaut: %dx%d aus %s"):format(length, width, node)
    end,
})

Wie testen?

Extension-Idee

Lass fortgeschrittene Schüler:innen eine „Geländer“-Option ergänzen: zwei zusätzliche Reihen auf y + 1, wenn /bridge ... rail aufgerufen wird.