Es werde Licht

Du hast dein „Hello World“ aus Teil 2 dieser Serie erfolgreich durchgeführt? Super! Dann kann es jetzt ja weiter gehen.

In diesem Teil wollen wir das erste mal mit InGame Objekten interargieren.


Wir benutzen einfach unser Script aus Space Engineers InGame Scripting Teil 2 weiter. Dies sieht ja wie folgt aus:

namespace IngameScript
{
    partial class Program : MyGridProgram
    {
        public Program()
        {
            Echo("DonCall ist der Beste!");
        }
        public void Main()
        {

        }
    }
}

Bau dir in Space Engineers zuerst mal eine Wand. Mach diese so 3 Blöcke hoch und 5 Blöcke breit. Diese Wand muss mit dem Grid, auf dem dein PB steht verbunden sein!

Auf diese Wand setzt du dann auf jeden Block ein Interior Light. Also insgesamt 15 Stück. Gehe ins K-Menü, markiere alle Interior Lights und gruppiere diese unter dem Namen „Funky„.

Jetzt gehst du zurück ins Visual Studio zu deinem Script.

Wie bekommen wir nun die Interior Lights in dein Script? Easy Peasy!
Wir brauchen eine Liste, in der die Interior Lights gespeichert werden können und eine Funktion um die Gruppe einzulesen.

namespace IngameScript
{
    partial class Program : MyGridProgram
    {
        List<IMyInteriorLight> funkyLights = new List<IMyInteriorLight>();
        public Program()
        {
            Echo("DonCall ist der Beste!");
            IMyBlockGroup group = GridTerminalSystem.GetBlockGroupWithName("Funky");
            if (group == null)
            {
                Echo("Funky not found");
                return;
            }
            group.GetBlocksOfType(funkyLights);
        }
        public void Main()
        {

        }
    }
}

Wir lernen:

List<IMyInteriorLight> funkyLights = new List<IMyInteriorLight>();

Hiermit erzeugen wir eine leere, neue Liste und sagen dem Script direkt, dass in dieser Liste nur Blöcke des Typs IMyInteriorLight vorkommen dürfen. Die Liste erzeugen wir übrigens außerhalb der Funktion Program()! Damit haben alle Funktionen später zugriff auf diese Liste. Denn sie ist global gültig. Innerhalb einer Funktion erzeugt, hätte nur diese Funktion zugriff darauf!

IMyBlockGroup group = GridTerminalSystem.GetBlockGroupWithName("Funky");

Hiermit erzeugen wir ein Gruppenelement IMyBlockGroup mit dem Namen „group“ und füllen diesen direkt mit unserer InGame-Gruppe „Funky“!
Das schöne an Space Engineers ist, dass (fast) alle internen Funktionen spechende Namen haben.

if (group == null)            
{
     Echo("Funky not found");
     return;
}

Damit keine Fehlermeldungen kommen, sondern eine lesbare Fehlerausgabe, falls die Gruppe doch nicht existiert, oder falsch geschrieben wurde, fragen wir noch ab: Wenn group leer ist, dann sage „Funky not found“ und beende das Script.

group.GetBlocksOfType(funkyLights);

Nun füllen wir unsere Liste funkyLights mit den Interior Lights aus der Gruppe group. Wir müssen dem Script hier nicht sagen, dass wir nur IMyInteriorLight haben wollen, da wir diese Info schon bei der Erzeugung der Liste mitgegeben haben. Das Script erkennt das und macht es richtig. Wäre in der InGame-Gruppe „Funky“ noch ein Spotlight, würde dies ignoriert. Spotlights heißen übrigens IMyReflectorLight.

Nun hat unser Script also alle Interior Lights aus der InGame-Gruppe Funky. Mehr hat es nicht. Mehr kann es nicht! Denn wir sagen ja noch nicht, was es damit machen soll. Dann machen wir das mal. Wir erweitern unser Script wie folgt:

namespace IngameScript
{
    partial class Program : MyGridProgram
    {
        List<IMyInteriorLight> funkyLights = new List<IMyInteriorLight>();
        public Program()
        {
            Echo("DonCall ist der Beste!");
            IMyBlockGroup group = GridTerminalSystem.GetBlockGroupWithName("Funky");
            if (group == null)
            {
                Echo("Funky not found");
                return;
            }
            group.GetBlocksOfType(funkyLights);
        }
        public void Main()
        {
            Random zufall = new Random();
            Color color = new Color(zufall.Next(0, 256), zufall.Next(0, 256), zufall.Next(0, 256));
            foreach(var light in funkyLights)
            {
                  light.SetValue<Color>("Color", color);
            }
        }
    }
}

Nun haben wir auch die Funktion Main() gefüllt. Ziel ist es, allen Interior Lights der InGame-Gruppe „Funky“ bei jedem Scriptaufruf eine neue, zufällige Farbe zu geben.


Wir lernen:

Random zufall = new Random();

Wir erstellen einen neuen Zufallszahlengenerator mit dem Namen „zufall“. Diesmal direkt in der Funktion Main(), da wir den Wert nur hier brauchen und nicht global, wie die Liste funkyLights!

Color color = new Color(zufall.Next(0, 256), zufall.Next(0, 256), zufall.Next(0, 256));

Wir erstellen uns eine neue Farbe. Farben haben intern immer 3 Werte. Der erste für Rot, der zweite für Gelb, der dritte für Blau. RGB! Bestimmt schon mal gehört. Die Werte haben einen Bereich von 0 bis 255. Wir vergeben die Werte für Rot, Gelb und Blau zufällig im Wertebereich von 0-255 mit unserem erstellten Zufallszahlengenerator mittels zufall.Next(0, 256). 256? Wir wollen doch nur bis 255! … ja … Der Minimalwert 0 ist in der Funktion inklusive, der Maximalwert 256 ist exklusive. Also er geht nur bis 255. Willst du beispielsweise Zufallszahlen zwischen 1 und 10, müsstest du die Funktion mit zufall.Next(1, 11) aufrufen. Muss man sich einfach merken.

foreach(var light in funkyLights)
{
     light.SetValue<Color>("Color", color);
}

Jetzt wird es nochmal lustig für die, die NOCH NIE irgendwas in irgendeiner Sprache programmiert haben. Wir benutzen eine Schleife um auf die Elemente in unserer Liste funkyLights nacheinander zuzugreifen. Wir benutzen dafür eine foreach-Schleife. Es gibt noch mehr Schleifenarten wie while(), do() oder for(), … Kopf- , Fuß- oder Zählergesteuert, …. Aber das erkläre ich hier nicht (schau hier und hier). Die Foreach-Schleife macht folgendes: Für jedes Element in funkyLights erzeugt es ein Element mit dem Namen light und gibt es in die Schleife. Dabei fängt es mit dem ersten Element in der Liste an und hört beim letzten auf.

Innerhalb der Schleife können wir nun mit dem Element light weiterarbeiten. Dieses Element ist übrigens automatisch vom Typ IMyInteriorLight. Und dieser Typ versteht es, wenn wir ihm sagen light.SetValue(„Color“, color). Er soll also den Wert „Color“ des Interior Lights InGame auf den von uns per Zufall erzeugten Wert color setzen.

Es macht Sinn, dass Spiel auf Englisch zu spielen. Denn man kann auch andere Felder als „Color“ ansprechen und deren Wert ändern. Spielt man SE auf Deutsch, sieht man den Feldnamen „Farbe“ und muss erst recherchieren, wie das Feld exakt auf Englisch heißt um es im Script anzusprechen.

Don’s Tipp

Mache jetzt den Deploy MDK Script wie in Teil 2 beschrieben und packe dein Script in den PB. Bei jedem Click auf „Run“ ändern sich nun die Farben der Lichter. Du kannst den Run des PBs auch per Timer Block auslösen. Jede 2 Sekunden zum Beispiel und so deinem Partyraum etwas Pimpen.


Ich weiß nicht, wie es dir geht. Aber ich bekomme schon einen feuchten Schlüpfer, wenn ich an Teil 4 denke.

Wenn du spezielle Themen behandelt haben möchtest, dann schreibe dies in die Kommentare!


DonCall

Moin! Ich bin der Don. Baujahr 1985 und der Überzeugung, dass es nichts gibt, was man nicht lernen kann. Ich bin in keinem Gebiet ein Profi, aber kann mich überall zurechtfinden. Hier auf fhq-gaming.de schreibe ich über Performance und InGame-Scripting zu Space Engineers.