Meine Werkzeuge
Namensräume
Varianten

Scripten mit Lua: Einstieg

Aus indiedev
Version vom 6. Dezember 2012, 09:30 Uhr von Glatzemann (Diskussion | Beiträge)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Wechseln zu: Navigation, Suche
Scripten mit Lua
Einstieg
Autor Glatzemann
Programmier­sprache C++
Kategorie C++-Tutorials
Diskussion Thread im Forum
Lizenz indiedev article license


Die Verwendung einer Script Engine um das eigene Spiel dynamisch durch Scripte zu erweitern ist eine gängige Aufgabe bei der Spieleprogrammierung. Nicht nur der Entwickler eines Spieles bekommt dadurch einige neue Möglichkeiten. Auch das Spiel selbst ist einfacher zu "modden" (nachträgliches Verändern des Spieles durch den Spieler) und der Game Designer ist ebenfalls viel flexibler in seiner Arbeit. Durch eine striktere Trennung der Zuständigkeiten innerhalb des Programmes kann einfacher an einzelnen Teilen des Spiels gearbeitet werden.

Die Vorteile liegen also auf der Hand. Die Aufgabe ist allerdings grundsätzlich erstmal skeptisch zu sehen, da das entwickeln einer Scriptsprache keine triviale Aufgabe ist. Der Compilerbau ist ein eigener, sehr umfangreicher und sehr wissenschaftlicher Teilbereich der Informatik und die Eigenentwicklung kann schnell viele Monate oder gar Jahre verschlingen. Glücklicherweise gibt es eine Reihe von fertigen Scriptsprachen. Dieses Einstiegstutorial dreht sich um den Quasistandard LUA. Ich möchte euch dabei im ersten Teil zeigen, wie ihr Lua in euer Programm einbinden könnt und wie ihr ein Lua-Programm ausführen könnt. Dieses wird noch nichts besonderes machen, lediglich ein einfaches "Hallo Welt von Lua" auf dem Bildschirm ausgeben, es wird nicht mit unserem Hauptprogramm interagieren und es werden auch keine Daten zwischen dem Script und dem Hauptprogramm ausgetauscht. Diese Themen werde ich mir für spätere Tutorials aufheben, es geht hier schliesslich um den Einstieg.

Als Programmiersprache wähle ich in diesem Fall, wie unschwer an der Kategorie zu erkennen ist C++. Als Entwicklungsumgebung setze ich das neue Visual Studio 2012 von Microsoft ein. Die Version "Express für Windows Desktop" eignet sich dafür hervorragend. Diese enthält - anders als es früher war - direkt mehrere Programmiersprachen: C++, C# und Visual Basic. Entwickeln kann man damit unter Windows Vista, Windows 7 und Windows 8. ModernUI oder solche für die Windows Phones oder die WinRT-Tablets können damit jedoch nicht entwickelt werden. Dafür gibt es gesonderte Express-Editions. Das Tutorial kann natürlich mit jeder ähnlichen C++-IDE durchgeführt werden, allerdings unterscheiden sich dann natürlich die einzelnen Schritte zur Erzeugung des Projektes und zur Kompilierung. Der eigentliche Code wird jedoch davon nicht tangiert und ist universell einsetzbar.

Inhaltsverzeichnis

Die Entwicklungsumgebung

Wir starten Visual Studio und klicken auf "Neues Projekt". Dieser Menüpunkt befindet sich entweder im linken Bereich auf der Startseite oder im Datei-Menü. Dort wählen wir in der Kategorie Vorlagen/Visual C++ das Leere Projekt aus.

LuaScriptingEinstieg01.JPG

Wir erhalten nach der Vergabe eines Projektnamens und Klick auf OK eine leere Projektmappe mit einem noch leeren Projekt.

Durch einen Rechtsklick auf Quelldateien, gefolgt von Hinzufügen/Neues Element und der anschliessenden Auswahl von C++-Datei können wir eine neue Quellcodedatei zu unserem Projekt hinzufügen. Diese nennen wir main.cpp. In dieser leeren Datei fügen wir sofort die Main-Funktion ein, die als Startpunkt für unser Programm dient.


int main(int argc, const char* argv[])
{

  return 0;
}

Drücken wir nun F5, so wird das Projekt kompiliert und gestartet. Es passiert noch nicht viel: Wir sehen lediglich kurz ein Konsolenfenster, welches aber sofort wieder verschwindet.

Als nächstes besorgen wir uns die aktuellen LUA-Bibliotheken und -Header, die wir im weiteren Verlauf des Tutorials verwenden wollen. Dieses Tutorial verwendet die Version 5.2.1 von LUA. Die aktuellen Binaries können wir unter [1] laden. Ich habe die statische 32Bit-Library aus dem Paket lua-5.2.1_Win32_vc10_lib.zip verwendet. Den Inhalt entpacken wir in ein Verzeichnis. Das darin enthaltene Include-Verzeichnis, sowie das Verzeichnis mit der .lib-Datei müssen wir nun noch in Visual Studio bekannt machen. Dazu klicken wir mit der rechten Maustaste auf das Projekt in der Projektmappe und wählen Eigenschaften.

Das Include-Verzeichnis fügen wir nun unter Konfigurationseigenschaften / C/C++ / Zusätzliche Includeverzeichnisse hinzu. Das Lib-Verzeichnis (das mit der Datei lua52.ib) wird unter Konfigurationseigenschaften / Linker / Zusätzliche Bibliotheksverzeichnisse hinzugefügt. Danach können wir den Einstellungsdialog mit OK schliessen.

Mit Microsoft-Compilern können wir den Linker ganz einfach mit einer Preprocessor-Direktive anweisen, daß eine statische Library zu unserem Programm hinzugefügt werden soll. Dies erfolgt mit der Direktive #pragma comment. Danach binden wir noch zwei Include-Dateien ein. Einmal die Standard-Library IO ("stdio.h") und dann noch lua.hpp, welches die LUA-Symbole in der statischen Library definiert. Der Code sieht danach wie folgt aus:


#pragma comment(lib, "lua52")

#include <stdio.h>
#include "lua.hpp"

int main(int argc, const char* argv[])
{
	printf("Hallo Welt von C++\n");

	getchar();

	return 0;
}

Wenn wir das Programm nun starten, dann wird der Text aus Zeile 8 ausgegeben und es wird in Zeile 10 auf einen Tastendruck gewartet. Dies können wir mit F5 direkt überprüfen.

Laden eines Script

Der erste Schritt zur Verwendung von LUA ist die Erzeugung eines State-Objektes. Dieses enthält alle Informationen zum LUA-Interpreter und dieses Objekt muss an jede Funktion als Parameter übergeben werden. Sollte Multi-Threading eingesetzt werden, ist es eine gute Idee, für jeden Thread ein eigenes State-Objekt zu haben. Das State-Objekt muss explizit geschlossen werden, wenn es nicht mehr benötigt wird. Dies erfolgt mit zwei einfachen Befehlen: luaL_newstate und lua_close. Der Sourcecode ist nicht weiter kompiliziert und sieht nach dieser Änderung wie folgt aus:


#pragma comment(lib, "lua52")

#include <stdio.h>
#include "lua.hpp"

int main(int argc, const char* argv[])
{
	printf("Hallo Welt von C++\n");

	lua_State* L = luaL_newstate();



	lua_close(L);

	getchar();

	return 0;
}

Jetzt müssen wir natürlich noch unser LUA-Programm laden und ausführen. Dazu gibt es ein handliches Makro luaL_dofile. Evtl. Fehler dabei werden auf dem LUA-Stack abgelegt, aber nur dann, wenn der Aufruf TRUE als Ergebnis liefert. Was dies genau ist, und wie dieser verwendet wird, werde ich erst im Teil über die Parameterübergabe erklären. Wir können den Fehler aber einfach mit lua_tostring abholen. Der vollständige C++-Code dieses Tutorials sieht nun wie folgt aus:


#pragma comment(lib, "lua52")

#include <stdio.h>
#include "lua.hpp"

int main(int argc, const char* argv[])
{
	printf("Hallo Welt von C++\n");

	lua_State* L = luaL_newstate();

	luaopen_base(L);

	if (luaL_dofile(L, "test01.lua"))
	{
		printf("%s\n", lua_tostring(L, -1));
	}

	lua_close(L);

	getchar();

	return 0;
}

Sehr einfach und übersichtlich bisher. In Zeile 14 versuchen wir das Script test01.lua aus dem aktuellen Verzeichnis zu laden und auszuführen. Wenn wir das Programm jetzt starten, stellen wir fest, daß dieser Aufruf TRUE als Ergebnis liefert. Das bedeutet, daß ein Fehler aufgetreten ist. Was dies für ein Fehler ist, steht im Stack und diese Information geben wir in Zeile 16 auch auf der Konsole aus. Aktuell wird natürlich das LUA-Script nicht gefunden, da wir dieses noch nicht erstellt haben.

Eine weiterer Befehl hat sich in Zeile 12 eingeschlichen. Dieser Befehl öffnet eine Standard-Erweiterungsbibliothek von LUA und zwar die mit dem Namen base. Diese enthält einige Basisfunktionalitäten für LUA-Scripte, wie den print-Befehl den wir gleich verwenden werden. Es gibt noch eine Reihe weiterer Bibliotheken und wir können sogar eigene entwickeln. Dies ist aber nicht Thema dieses Einstiegstutorials.

LuaScriptingEinstieg02.JPG

Ein einfaches LUA-Script

Ein einfaches LUA-Script zu erzeugen ist nicht weiter schwer. Wir klicken mit der rechten Maustaste auf Ressourcendateien, wählen Visual C++ / Dienstprogramm / Textdatei aus und vergeben den Namen test01.lua. Wir erzeugen die Datei durch einen Klick auf Hinzufügen. Der Inhalt der Scriptdatei ist dabei nicht weiter spektakulär:


print("Hallo Welt von LUA\n")

Wenn wir unser Programm nun starten, dann ist die Fehlermeldung von vorhin verschwunden und die Ausgabe aus unserem Script erscheint, so wie wir es wollten und damit sind wir bereits am Ende dieses Einstiegstutorials angelangt.

Zusammenfassung und Ausblick

Wir haben in diesem Tutorial gelernt, wie wir den LUA-Interpreter in ein eigenes Programm integrieren und wie wir ein Script laden und ausführen können. Dies ist nicht besonders schwer und in wenigen Zeilen Code geschafft. Dieses Script kann natürlich noch nicht viel machen und ist daher wenig sinnvoll. Vor allem die Interaktion mit unserem Programm ist noch nicht möglich. Auch die Übergabe von Parametern von unserem Programm an das Script haben wir noch nicht kennengelernt. Diese Themen werden ich in den nächsten Teilen dieser Tutorialreihe behandeln. Wir werden dann in die Lage versetzt immer komplexere Scripte zu entwickeln. Damit kommen wir dann in die glückliche Situation unser Programm durch ein Script "fernsteuern" zu können und somit das Verhalten und die Möglichkeiten unseres Programms zu erweitern und/oder zu verändern.

Navigation
Tutorials und Artikel
Community Project
Werkzeuge