[C++] Spieleengine - Scriptsystem erstellen
-
Hey,
ich entwickle momentan eine 2D Spieleengine (just for fun), die aktuell nur Grafik(bis jetzt nur Sprites, Tiles und Text), Eingabe und einer "automatischen Game-Loop" verwaltet. Jedoch möchte ich auch weitere Module wie etwas Physik, Sound, etc.. einfügen und man soll die Engine in einem Editor(Sandbox?) verwalten können, wie zum Beispiel bei der Unity Engine.
Jetzt zu meinem Problem:
Ich möchte auch ein kleines "Scripting Sytem" einbauen, die etwa so funktionieren soll wie bei der Unity Engine. Das heißt, dass ich zum Besipiel ein neues Objekt erstelle(Sprite,etc.), das ich mit einem Skript(nur für dieses Objekt erstellt) verändern kann, also Position usw. Dabei möchte ich keine neue Sprache entwickeln, sondern es soll einfach möglich sein LIMITIERT mit C++ weiterzuschreiben.
Allgemein hätte ich mir das folgendermaßen überlegt:Ich erstelle eine Klasse, die ich zum Besipiel GameObject nenne, die dann ein Spielobjekt(Sprite,etc.) enthält und außerdem zwei Funktionszeiger, welche dann beim Start und bei jedem Frame(Durchgang der Game-Loop) einmal aufgerufen werden:
class cGameObject{ public: cGameObject(); //Konstruktor soll die Klasse (this) in "GameObject" Array einfügen void SetUpdateFunction( void (*Func)() ); void SetStartFunction( void (*Func)() ); private: void* pObject; //Der Zeiger auf das Objekt jeglicher Art void (*pStartFunc)(); //Funktion, die beim erstellen des Objekts aufgerufen wird void (*pUpdateFunc)(); //Funktion, die bei jedem Frame aufgerufen wird };
Ich weiß noch nicht, wie genau ich mir das gedacht hatte aber falls ich dann ein neues Script für ien Objekt erstelle, sollte das Script erstmal so ausschauen(Das Script ist einfach nur eine .cpp Datei):
#include "engine.h" cGameObject Object; void Start(){ //edit here... } void Update(){ //edit here... } Object.SetStartFunction( &Start );Object.SetUpdateFunction( &Update );
Dieses File sollte geöffnet werden, falls man ein neues Script erstellt. Damit kann man dann die Update - und die Startfunktion beliebig verändern.
Jedoch gibt es da einige Probleme.
1.) Die untere Zeile schaut nicht schön aus und zeigt dem User etwas "innenleben" der Engine2.) Das größte Problem jedoch ist, dass man die Engine somit immer neu kompilieren muss, wenn man einige Änderungen am Script vornimmt.
Das hat dann zur Folge, dass es einerseits zeitaufwendiger ist, es unschön ist und der Editor/Sandbox damit auch nicht weiterlaufen kann, da sie ja mit der Engine läuft.Also...habt ihr einige Ideen wie man dieses Problem lösen kann ohne einen ganzen Compiler oder soetwas für die Engine zu programmieren oder ist das nicht möglich?
Danke schonmal!
-
Ich hab zwar keine Erfahrung in der Spieleentwicklung. Denke aber du solltest eher in die Richtung eines Scriptinterpreters gehen, der das Script ausführt. Wie du das am geschicktesten Anstellst kann ich so nicht sagen, aber bei der Google suche findet man soweit ich das eben gesehen habe einige viele Beispiele für einen Scriptparser / interpreter.
-
Funktionszeiger ist schon mal uncool, nimm std::function. Wenn überhaupt. void* schaut erstmal auch irgendwie verdächtig aus... Ich hab mich jetzt nicht so genau in das Problem reingedacht, aber du solltest dir gut überlegen, ob du wirklich ein void* brauchst.
Fürs Scripting von Spielen verwendet man oft Lua. Das lässt sich auch recht einfach in C++ integrieren (hab ich jetzt aber zugegebenermaßen nie gemacht, nur in C#). Schau dir mal an, wie das funktioniert, vielleicht kannst du deine Scripting Schnittstelle dann entsprechend designen.
Wenn du Lua nicht magst, nimm vielleicht Python. Eine eigene Scriptsprache würde ich auf keinen Fall schreiben, schon gar nicht C++ (und das willst du ja offensichtlich, weil du keine neue "Sprache" willst, aber einen C++ Interpreter wirst du wohl selber schreiben müssen). Und das sag ich dir aus eigener Erfahrung, weil wir haben eine eigene Scriptsprache in der Firma, die wir auch ständig pflegen müssen. Die gibts wahrscheinlich schon seit 15 Jahren und wir können nicht mehr ohne weiteres davon weg und wir können uns das auch leisten, weil die mittlerweile auch gut funktioniert und wir genügend Mitarbeiter haben. Aber für einen Einzelkämpfer wär das zu viel Aufwand, nebenbei einen vernünftigen Interpreter zu schreiben.
-
Hallo Tomsen1410,
du könntest dir auch mal die an C++ angelehnte Scriptsprache AngelScript anschauen: AngelScript Homepage
Und du solltest deine Engine am besten als Library (DLL) entwickeln, so daß der Source-Code unabhängig von dem eigentlichen Gamecode ist.
-
Hi,
ich hab in der Vergangenheit mit LUA gearbeitet.
LUA(http://www.lua.org/) ist javascript sehr aehnlich und ziemlich flott. Mit luajit gibt es neben Interpretation sogar einen JIT der es noch schneller macht.Das interfacing mit C++ kann man entweder selber schreiben oder z.B. mit Hilfe von SWIG (http://www.swig.org/) bekommen.
Gibt ein paar Regeln zu beachten, aber im Prinzip kann man seine gesamte API von SWIG einfach parsen und den Wrapping code erstellen lassen.
Mit etwas Bastelei waren sogar Callbacks von LUA nach C++ und umgekehrt moeglich.
Ziemlich cool.
-
Ich kann ebenfalls Lua empfehlen, auch wenn ich die Sprache bisher hauptsächlich für statische Konfigurations-/Gameplaydaten verwendet habe. Zum Einbinden in C++ hatte ich früher LuaBind verwendet. Inzwischen bin ich auf LuaBridge umgestiegen, ist um einiges leichtgewichtiger und kommt ohne Boost aus. Von der Schnittstelle her sind beide Bibliotheken ähnlich. Von SWIG oder der C-Schnittstelle von Lua würde ich abraten, ausser du stehst auf Low-Level-Basteleien. Ansonsten kannst du mittels LuaBridge sehr einfach mit Lua interagieren.
Funktionszeiger und
void*
sind Relikte aus C, in C++ würde ich versuchen, sie wegzukapseln. Moderne C++-APIs arbeiten stattdessen mit Funktoren.