20.03.2025

Ich hatte es schon im letzten Post angekündigt. Dieses mal hatten wir uns Entities angeschaut. Und wie diese in Luanti implementiert werden.

Jetzt stellt sich aber natürlich eine wichtige Frage: Was genau sind Entities? Entities können fast alles sein. Mit ihnen kann man Blöcke, Monster oder auch Tiere erstellen wobei die zwei letzteren, die Hauptverwendung von Entities sein sollten. Eine tiefgründige Erklärung, wie Entities von Items zum Beispiel verschieden sind, gibt es hier in dem sehr guten und anfängerfreundlichem Guide von Ruben Wardy. Da er auf English ist, erkläre ich das gröbste.

Zu aller erst definieren wir uns erstmal eine Entity. Wir legen einen Lua Tabelle an und definieren hier jetzt Anfangswerte, wie z.B. die Anzahl an Leben, die unsere Entity hat, Funktionen, die beschreiben wie z.B. die Entity sich bewegt, und andere Daten, die wir benötigen für unsere Entity. Hier im Beispiel eine Nachricht (message), die abgesendet werden soll, wenn die Entity geschlagen wird.

local entity = {
    initial_properties = {
        hp_max = 20,
        physical = true,
        collide_with_objects = true,
        collisionbox = {-0.3, -0.3, -0.3, 0.3, 0.3, 0.3},
        visual = "mesh",
        visual_size = {x = 1, y = 1, z = 1},
        mesh = "Steve.obj",
        textures = {"steve.png"},
        spritediv = {x = 1, y = 1},
        initial_sprite_basepos = {x = 0, y = 0},
    },

    message = "I got hit",
}

Das wichtigste ist, wenn eine Entity entweder geladen oder neu erstellt(gespawnt wird), kopiert diese Entity ihre Definitionstabell. Nehmen wir an, ein Villager wird in unserer Welt gespawnt, dann bekommt sie alle Werte aus der oberen Tabelle. Das passiert aber auch wenn dieser Villager geladen wird. Sagen wir wir hätten die Nachricht des Villagers durch z.B. Dialog mit ihm geändert, würden wir ihn jetzt entladen und wieder laden, dann würde ein Gespräch mit ihm wieder die aller erste Nachricht aufbringen. Wie man das umgeht übersteigt für heute aber den Rahmen dieses Posts und wir werden das in der Zukunft uns eh noch anschauen müssen. Wenn ihr aber Lust habt euch das jetzt schon anzuschauen empfehle ich den Guide von Ruben Wardy aber der Stelle hier

Jetzt zur Erklärung des Codes von oben. Dabei möchte ich nur auf ein paar wichtige Eigenschaften eingehen. Wenn ihr eine volle Übersicht über alle Eigenschaften, die ihr setzen könnt haben wollt, gibt es die hier.

  1. initial_properties = {:
    • initial_properties ist ein von luanti erforderte Lua Tabelle die wichtige basis Eigenschaften für die Luanti Engine birgt
  2. visual = "mesh":
    • "mesh" bedeutet, dass wir ein 3D Model benutzen, um die Entity anzuzeigen.
  3. visual_size = {x = 1, y = 1, z = 1}:
    • setzt die Skalierung des 3D Model’s in x (Nord/Süd), y (Oben/Unten) und z (Ost/West) Richtung
  4. mesh = "Steve.obj":
    • Hier geben wir an, welches 3D Model wir benutzen möchten für unsere Entity
  5. textures = {"steve.png"}:
    • Ähnlich zu tiles von unserem Block, setzt die Texturen für die Entity. Hier können auch mehrere Bentuzt werden, welche dann im 3D Model bestimmt gemappt werden müssen
  6. message = "I got hit":
    • benutzerdefinierte Eigenschaft. Wir benutzen diese hier um eine Nachricht in den Chat zu senden, wenn die Entity geschlagen wird

Jetzt haben wir erst einmal Standardeigenschaften für die Entity definiert. Wenn wir die Entity jetzt so kreieren würden, würde sie nur dastehen und nichts machen. Wir müssen also Logik für sie erstellen.

function entity:on_step(dtime)
    local pos      = self.object:get_pos()
    local pos_down = vector.subtract(pos, vector.new(0, 1, 0))

    local delta
    if core.get_node(pos_down).name == "air" then
        delta = vector.new(0, -1, 0)
    elseif core.get_node(pos).name == "air" then
        delta = vector.new(0, 0, 1)
    else
        delta = vector.new(0, 1, 0)
    end

    delta = vector.multiply(delta, dtime)

    self.object:move_to(vector.add(pos, delta))
end

function entity:on_punch(hitter)
    core.chat_send_player(hitter:get_player_name(), self.message)
end

Wir definieren zwei Funktionen auf der Entity: entity:on_step und entity:on_punch, welche jeweils jeden Tick und jedes mal, wenn die Entity geschlagen wird, aufgerufen werden.

In on_step holen wir uns die Position von uns selbst mit self.object:get_pos() und kalkulieren die Position, des Blockes unter der Entity. Anschließend berechnen wir unsere Bewegung. Wenn der Block unter der Entity Luft ist, dann soll sich die Entity nach unten Bewegen. Wenn die Entity an ihrer geradigen Position kein Block hat (sie also auf einer Ebenen ist), dann soll sie sich in z Richtung (Ost/Westen) bewegen. Und wenn unter uns und an unserer Position ein Block ist, dann müssen wir an der Kante eines anderen Blockes der Höher als die Entity ist sein, die Entity muss sich also nach oben bewegen.

Um eine fließende Bewegung zu implementieren, weil das Spiel kann ja an zufälligen Stellen hängen, müssen wir die Positionsveränderung der Entity mit der Zeit, die abgelaufen ist multiplizieren. Dannach ändern wir die Position der Entity mit self.object:move_to(vector.add(pos, delta))und haben somit die Entity in eine bestimmte Richtung bewegt.

In on_punch bekommen wir als Parameter den Spieler oder die Entity, die unsere Entity geschlagen hat. Mit dem namen des Spielers können wir jetzt mit core.chat_send_player die Nachricht self.message an den Spieler senden.

Um jetzt zu guter letzt unsere Entity zu registrieren und zu spawnen rufen wir core.register_entity auf und übergeben mit dem Namen der Entity auch unsere Definitionstabelle der Entity.

core.register_entity("entity_mod:entity", entity)
core.add_entity({x = 1, y = 2, z = 3}, "entity_mod:entity", nil)

core.add_entity spawnt dann die Entity an einer bestimmten Stelle in der Welt. Hier ist das {x = , y = 2, z = 3}. Man kann die Entity dann aber auch über den Command: /spawnentity entity_mod:entity spawnen.

Zusammenfassung

Diese Woche haben wir gelernt, wie man Entities definiert, Logik auf ihnen implementiert und die Entities dann auch im Spiel spawnt. Es gibt noch vieles hier zu machen, wie z.B. das Laufen bei der Entity zu verbessern. Oder wenn man z.B. einen Zombie machen möchte diesen auf den Spieler zulaufen zu lassen.

By Mentor

Leave a Reply

Your email address will not be published. Required fields are marked *