Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Kaum komm ich von der Beerdigung des Strategiespiels schon hab ich wieder Nachschub *hust*.
Also, an dem hier arbeite ich schon eine ganze Weile, zwischenzeitlich dann mal aufgrund eines fehlinterpretierten Bugs komplett neu geschrieben, aber egal .
Es geht um einen Editor für ein Spiel, und zwar, wie der Titel schon erahnen lässt, geht es um die X-Reihe, konkreter um X³ - Reunion (wobei auch X³ - Terran Conflict keine Probleme machen sollte, aber hier fehlt mir Testmaterial).
» Warum? Es gibt schon einen Editor für X³, der sogar direkt im Spiel integriert ist. Aber genau das ist das Problem. Dieser Editor benutzt die Oberfläche des Spiels, wie man sie auch Ingame hat. Das macht es schwierig, vernünftig damit zu arbeiten. Außerdem hat er gewisse Einschränkungen, gerade, was das erstellen eigener Universen betrifft (man kann Sektoren nicht umbenennen und keine hinzufügen, die es nicht schon im Originalspiel oder in der aktivierten Mod gibt). Weiterhin gibt es einen Editor von Doubleshadow, der aber unter Linux nur dürftig läuft und meines Erachtens nicht gerade intuitiv ist. Außerdem liegt hier der Schwerpunkt auf der Moderstellung, während ich primär einen Universumseditor suche und daher auch entwickle.
» Ziele
Oberfläche
Flexibel
Mächtig
Möglichst einfach und intuitiv zu Bedienen
Erweiterbarkeit durch Plugins (eventuell)
Schwerpunkt auf Universumserstellung
Keine Hardcoded-Daten. Alles aus den X³-Dateien auslesen
Im-/Export von X³ Universen
Vernünftige Defaultwerte, die aber einfach und jederzeit durch eigene ersetzt werden können, um das schnelle Erstellen von Content zu erleichtern
Lesen und Schreiben von X³ Modpaketen (sodass das manuelle Entpacken für die Benutzung des Editors nicht notwendig ist)
Last but not least: Plattformunabhängigkeit, sodass es sowohl eine Windows- als auch eine Linuxversion gibt. X³ läuft in Wine nämlich hervorragend, nebenbei erwähnt
» Wie? Ich arbeite hierbei ganz viel mit Vererbung und abstrakten Klassen, Factories, Observern und anderen Späßen. Vorallem die Observer sind krass, was da an Events teilweise bei einem Klick durch die Gegend geschossen wird, um die Anzeige aktuell zu halten ist schon nicht mehr schön. Ich denk mir auch immer, wenn ich da jetzt ein Fitzelchen ändere, fliegt mir das ganze wie eine überspannte Federkonstruktion in Phun um die Ohren, aber bisher liefs . Also, wie man sich vielleicht denken kann, setzt das ganze auf Lazarus auf. Entwickelt wird unter Linux, ich teste aber regelmäßig auf Windows-Kompatibilität (sowohl Compile- als auch Runtime).
› gametoolset Die Struktur sieht ungefähr so aus: Ganz unten liegen die GT-Klassen (GT = GameToolset), welche ziemlich Abstrakt sind (nicht nur im progammiertechnischen Sinne des Wortes) und noch nichts mit X zu tun haben. Dort gibt es zum Beispiel eine Klasse, die schon Methoden zum Speichern und Laden zu bzw von XML bietet. XML ist nebenbei gesagt das Format in dem alle Arbeitsdaten gespeichert werden. Diese Methoden lesen mittels RTTI-Informationen aus, welche Properties es gibt und speichern / laden dann deren Werte. Nur, wenn eine Klasse Properties hat, die nicht von einer bestimmten Basisklasse ableiten oder Werte speichern muss, die nicht als Property abbildbar sind oder einfach nicht als Property abgebildet werden sollen, müssen diese Methoden überschrieben werden und es müssen eigene XML-Nodes erstellt werden. Dann habe ich noch eine Basisklasse für Editoren. Editoren sind in diesem Kontext (visuelle) Komponenten, die ein bestimmtes Funktionsset bieten. Dort gibt es dann Methoden, die vom Frontend aufgerufen werden, wie z.B. QueryMenuAppends, wo der Editor eigene Menüeinträge oder ähnliches hinzufügen kann. So kann jeder Editor die Oberfläche etwas durch neue Elemente anpassen. Außerdem gibt jeder Editor über sich Informationen, wie z.B. ob er Copy/Paste kann, sodass sich die Oberfläche auch darauf einstellen kann ((de-)aktivieren von Menuitems). Diese Editoren registrieren sich bei Programmstart in einer Registry, zusammen mit den Klassentypen, die sie editieren können. Wenn nun ein Objekt editiert werden soll (und nicht nur inspiziert, dazu später noch was), dann fragt die Oberfläche bei der Registry nach einer Editorklasse, die dieses Objekt editieren kann. Die wird dann gegebenenfalls instanziert und aktiviert. Weiterhin bietet das GT noch eine Session-Klasse, in der ein Editor seinen Zustand abbildet und wo Lade- und Speicherroutinen für die komplette Datenumgebung implementiert werden.
› x3toolset Das ist das zweite Paket, welches auf dem ersten aufbaut. Viel gibts nach der Vorrede nicht mehr zu sagen. Für den Im-/Export von echten Spieldaten werden eigene Methoden benutzt, da das XML-Format des GT selbstverständlich nicht auf X³ abgestimmt ist. Ist auch besser so, da die Klassen viele Daten enthalten, die später im Spiel nicht zu gebrauchen sind (bspw. Metadaten für den automatischen Universumsausbau) und nicht in den echten Spieldaten gespeichert werden können. Für diese existieren dann separate Im-/Export-Methoden. Fast vergessen zu erwähnen, dass in diesem Paket auch alle Spieldaten geladen und interpretiert werden. Außerdem werden hier die Datenbanken für die Stationen und deren Warenverbrauch/-produktion erzeugt und bereitgehalten. Dazu der ganze Code für die Autopopulation der Sektoren (man sagt, was man ungefähr haben will und der Populator macht den Rest). Hier werden außerdem noch die zusätzlichen PropertyEditor-Ableitungen implementiert und registriert, die dann beim Inspizieren genutzt werden. Um mal exemplarisch eine Verwendung für die Möglichkeiten eines Editors, Komponenten zum Frontend hinzuzufügen zu nennen, empfehle ich mal, auf Screenshot 18 zu schauen. Der Sektoreditor hängt die Tabs mit den Objekten an die Tabcontrol, die das Frontend zur rechten Seite bietet (und die, wenn nicht gebraucht, ausgeblendet wird).
› Das Frontend Das Frontend letztendlich schöpft aus dem vollen der vorhergehenden Pakete. Mithilfe der Abstraktion der Editoren kommt die Hauptunit aktuell noch mit weniger als 1000 Zeilen aus. Später wirds noch mehr, da viele Details in der Oberfläche bisher nicht implementiert sind (Laden/Speicherdialoge z.B.) was einfach aus Faulheit noch nicht geschehen ist. Das hebe ich mir dann für die Phasen auf, wo ich was leichtes brauche . Wie schon angedeutet, gibt es in der Sprache des GT zwei Editiermodi, einmal das echte „editieren“ und einmal das „inspizieren“. Das Inspizieren beschränkt sich auf published properties. Dazu wird die TTIPropertyGrid-Komponente benutzt, die bei Lazarus beiliegt und im Prinzip der Object Inspector der IDE ist. Damit und mit der Flexibilität, die durch TPropertyEditor-Ableitungen entsteht muss ich nicht für jede Klasse eine eigene Editor-Komponente schreiben, sondern kann dem Grid einfach sagen, was gerade zu inspizieren ist. Daher gibt es auch nicht für alles echte Editoren im Sinne des GT sondern nur für spezielle Dinge, wie z.B. die Sektorkarte oder Sektoren (wo man dann Objekte durch die Gegend schieben kann... können sollte).
» Status Wenn nicht anders erwähnt (wie z.B. im letzten Satz) ist das genannte bereits implementiert.
» Fremdlibs
LCL
virtualtreeview-new [SVN] (2. VirtualTreeView-Port für Lazarus) mit 64-bit Patch
Der X2FD war eine gute Grundlage um das Auslesen der Spielpakete zu realisieren.
» Fremdtools
Im Moment keine.
» Screenshots › Von links nach rechts: Universumsübersicht älter - Editieren von WareOverrides für den Populator (exemplarisch für ein Beispiel einer TPropertyEditor-Ableitung) - Ergebnis einer automatisieren Population eines Universums - Universumsübersicht neuer - Sektoreditor Klick zum Vergrößern - das ausgefüllte Universum auf 14, 17 und 18 ist aus X³ importiert - das auf Screenshot 16 ist mit dem Populator gefüllt - alle deutschen Texte sind aus den X³ Dateien zur Laufzeit importiert (übrigens auch der Fenstertitel )
» Download Da das Lesen der Spieldaten nun funktioniert, werde ich bald mal ein halbwegs stabiles, aber dennoch Alpha-Build machen. Die Exportfunktion ins Spiel funktioniert leider noch nicht.
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Ein kleines Update. Zwischenzeitlich habe ich den Populator noch etwas weiter verfeinert und einige Bugs beseitigt, die nicht sofort offensichtlich waren, sondern eher durch Zufall aufgefallen sind. Jetzt werden auch Asteroiden platziert (mit drei möglichen Ausbeuteverteilungsfunktionen) und Funktionsvorlagen für das GOD-Modul erzeugt (das GOD-Modul ist ein Teil von X³, der das Universum dynamisch hält und anhand von Vorgaben Stationen dazubaut bzw entfernt), die in einem separaten Schritt errechnet werden. Die minimal angegebene Versorgungsabdeckung wird mit statischen Stationen erledigt, bis zur maximalen wird dann mit GOD-Stationen aufgefüllt (die ggf. ihrerseits Dependencies mitbringen).
Außerdem gibts jetzt einen Editor, mit dem man sehr einfach die Sprungtorverbindungen zwischen Sektoren erzeugen kann, quasi Drag'n'Drop. Das ist vorallem wichtig, weil der Populator eben diese Verbindungen beim Auflösen von Warenversorgung mitbenutzt. Auße
Nächster Schritt ist im Moment, neben dem weiteren Verfeinern des Populators, das einlesen der Job-Dateien (dazu später mehr) sowie das Verwenden der Spieldaten aus den Archiven (ich bin gerade auf den passenden Sourcecode gestoßen (worden)).
greetings
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Eine ganze Weile nichts mehr zu geschrieben, hauptsächlich, weil ich etwas Abstand brauchte, um einen Bug zu finden. Der ist jetzt auch gefunden und behoben, damit ist es jetzt möglich, das Toolset ohne das vorherige Extrahieren der Spieldaten zu betreiben. Es liest die Daten jetzt selbstständig aus den .cat/.dat-Dateien des Spiels aus. Dabei werden auch die etwas komplexeren Prioritätsreihenfolgen, die teilweise allein auf der Dateiendung basieren, beachtet.
Das Importieren von Jobs aus eben diesen Daten ist ebenfalls möglich. Außerdem habe ich das Populator-System nochmal umgestellt. Jetzt sind die Populatoren unabhängig von den Sektoren und werden einzeln auf die Sektoren aufgeschaltet.
Auf dem nahen Zukunftsplan steht die Erweiterung der Oberfläche um ein mehr oder weniger einheitliches Drag'n'Drop system. Beispielsweise arbeite ich an einer Lösung, um die Werte von Properties aus dem Property-Grid direkt auf ein anderes Objekt im Tree bzw im aktuellen Editor zu ziehen. Das soll gerade beim Setzen von Populatoren bzw deren Ketten helfen. Außerdem braucht es noch eine Funktion, um ein Objekt von einem Sektor in einen anderen zu Draggen.
Weiterhin fehlt bei den Populatoren noch jegliche Kollisionskontrolle, was darauf hinausläuft, dass alle Objekte im moment blind auf 0/0/0 positioniert werden . Dafür hatte ich ja bereits vor einiger Zeit einen Thread aufgemacht, ich muss aber nochmal sehen, ob das der richtige Ansatz ist.
greetings
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Die Kollisionskontrolle für Populatoren ist nun implementiert. Und es ist eine Mischung aus BruteForce und Mathematik. Keine Ahnung, ob es richtig ist, ich konnte auch noch nicht testen, ob alle Kollisionen wirklich aufgelöst werden, aber zumindest in der Theorie sollte es klappen. Die Sektoransicht spricht auch dafür, dass es einigermaßen hinhaut. Es wird eine zufällige Position im entsprechenden Bereich des Sektors gewählt. Dann wird geschaut, ob eine Kollision besteht. Wenn das kollidierende Objekt nicht genau getroffen wurde, wird ein Vektor von der Position des alten Objektes zu der hypothetischen Position des neuen Objektes gezogen und das Objekt wird anhand dieses Vektors aus dem alten Objekt herausgeschoben. Dann geht das Spiel von vorne los. Wenn es doch mal eine punktgenaue Kollision gibt, wird ein zufälliger Vektor erzeugt. Außerdem wird bei beiden Varianten der Vektor noch mit etwas Zufall versalzen, damit es auf jeden Fall irgendwann zu einer Lösung kommt. Wenn ein Objekt genau zwischen zwei Objekten landet (und mit beiden kollidiert), könnte es sonst zu einer Endlosschleife kommen.
Die grafische Oberfläche wurde außerdem noch mit ein paar neuen Feinheiten wie einer Progress bar für aktuelle Operationen (Laden/Speichern, Importieren/Exportieren, Populieren etc.) und einem Abbrechen-Button (bei dem eine Exception ausgelöst wird, um den Prozess abzubrechen). Intern wurden noch ein paar Verbesserungen vorgenommen, die sich eher in Kleinigkeiten äußern.
Das Drag'n'Drop ist mal hinten angestellt. Dafür will ich demnächst ein Modul zum schreiben von .cat/.dat-Dateien bauen, damit die erstellte Mod auch endlich mal ohne hackerei im Spiel getestet werden kann. Dann wirds auch mal ein Release geben .
Das GT wurde übrigens noch ein wenig erweitert. Nun speichere ich auch die Konfiguration über die GT-Klassen. Es passt sich einfach zu gut, dass properties direkt auf XML abgebildet werden können (und umgekehrt). So habe ich jetzt ein Konfigurations-Objekt, deren Properties beim Start aus einer XML-Datei gelesen (oder, wenn diese nicht existiert/nicht vollständig ist etc, bei Defaultwerten belassen) werden und beim Beenden komplett in eben jene Datei zurückgespeichert wird. Und das ohne großen Aufwand. Das Deklarieren einer neuen Property und ggf. das Setzen eines Defaultwertes reicht .
Natürlich auch eine Menge Bugs gefixt, aber das ist witzlos zu berichten, weil es eh noch kein Release gab.
greetings
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Nur was technisches, beim Durchschauen der Logs ist mir aufgefallen, dass meine Bilderlinks kaputt waren. Habe das mal schnell behoben.
greetings
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Mitglieder in diesem Forum: 0 Mitglieder und 55 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.