Beiträge von EFJ_Baron

    Also ich hatte das damals mit meiner Idee mithilfe eines Plugins umgesetzt, welches sich Soundtrack Manager nennt. Hier mal der Link dazu: https://heroicjay.itch.io/soun…-manager-for-rpg-maker-mv


    Dieses Plugin habe ich dann mit meinem eigenen Plugin kombiniert, was es mir erlaubt, mehrere Layer an Region ID's zu verwenden. Für die Erstellung der Region Layers habe ich damals Tiled verwendet. Damit war es mir möglich, die Musik über diesen zweiten Layer von Region ID's so zu steuern, dass die Musik je nach ID wechselt.


    Adaptive Musik_Trim.zip


    Hier mal ein kurzes Video von dem Prozess, wenn anhand der ID die Musik wechselt.


    Ist jetzt ehrlich gesagt schon ein Weilchen her, hatte aber echt Spaß gemacht, das zu implementieren.^^

    Teil 3.1: Optimierung des SaveSystems durch einen Serializer

    Dank der Hinweise von Lihinel habe ich mich nochmals mit dem SaveSystem auseinandergesetzt. Statt der json-Speichermethode nutze ich nun wieder die store_var Variante. Damit wird es auch möglich, Vector2 und ähnliche Godot-Klassen effektiv abzuspeichern. Da blieben nur noch ein paar Probleme bestehen: Die Umwandlung von Objekten in speicherbare Daten und die Umwandlung dieser Daten wieder zurück in verwendbare Objekte. Hierzu habe ich eine Hilfsklasse Serializer angelegt.


    Diese Klasse hat die zentralen Funktion serialize und deserialize. Dabei bleiben die Daten unverändert, sofern sie z.B. nur ints oder strings sind. Sind sie Arrays oder Dictionaries, so werden die einzelnen Einträge mit der selben Funktion untersucht und umgewandelt. Objekte werden in spezielle Dictionaries umgewandelt. Zusätzlich werden sie noch mit dem Attribut REF versehen. Sodass beim Deserialisieren Objekte mit selber REF id nicht doppelt erzeugt werden.


    Beim Deserialisieren wird ein ähnliches Prinzip nur umgekehrt angewendet.

    Oh, mir ist gerade aufgefallen, dass ich gar nicht die JSON Variante genutzt habe.^^ Stattdessen habe ich vorher store_var und get_var genutzt. Die scheinen aber Probleme beim Speichern von eigenen Klassen-Typen zu haben. Ich habe das Skript jetzt nochmal auf JSON umgestellt. Jetzt funktioniert es so wie mit dem ResourceSaver aber halt als JSON. Damit wäre das Problem gelöst und ich bin froh, dass ich damit das Sicherheitsrisiko umgehen kann. Danke auf jeden Fall nochmal für den Hinweis. Ich kannte das Problem mit Resourcen nur grob, aber in dem von dir verlinkten GitHub-Issue konnte ich nochmal etwas genauer nachlesen.:)


    EDIT: Ja, es scheint doch nicht so gut zu funktionieren, da beim Laden aus den Dictionaries keine Objekte mehr werden, sofern sie in tieferen Ebenen liegen, also Objekte in Objekten

    Teil 3: SaveNode, SaveFile, SaveSystem - Wie man den Spielstand speichert

    Mittlerweile kann man von Szene zu Szene wechseln und der Spieler kann sich auch bewegen. Toll! Gehen wir jetzt mal davon aus, dass man in einer Variable gold festhält, wie viele Münzen man im Spiel gesammelt hat. Man sammelt also fleißig Münzen ein während des Spielens und dann schaltet man nach einer ordentlichen Spiele-Session das Spiel aus. Später schaltet man es ja wieder ein... ... WAS, 0 Münzen!!! WIE KANN DAS SEIN?!


    Tja, da wurde wohl nicht richtig abgespeichert. Wenn das Spiel aus geht, gehen auch alle Werte in Variablen verloren und werden beim erneuten Starten auf die ursprünglichen Werte zurückgesetzt. Damit man seinen Fortschritt also nicht verliert, brauchen wir eine Lösung, veränderte Werte (wie die variable gold) auf der Festplatte zu speichern. Godot bietet hierbei viele Möglichkeiten, soetwas zu bewerkstelligen. Die alle aufzuzählen, wäre aber hier zuviel des Guten. Eine Möglichkeit werde ich aber hier verlinken zu Godot-Dokumentation: https://docs.godotengine.org/d…ials/io/saving_games.html


    So, das war es grundsätzlich mit den Erklärungen. Falls ihr irgendwelche Fragen, Anmerkungen oder Kritik habt, könnt ihr sie gerne äußern.

    Hallo,


    die Idee klang schon mal ziemlich interessant und ich war kurz auf Telegram. Da hab ich kurz das Video angesehen. Allerdings wurde mir das Story-Konzept noch nicht so ganz klar. Ihr hattet von einem Umkehrungsritual gesprochen und das es mit Vergessen zu tun haben soll, doch was beinhaltet das alles? Was passiert mit der Welt? Welche Auswirkungen hat es genau und warum geschieht es? Ich stelle diese Fragen, denn mit klareren Konzept kommen mir bessere Ideen.:)

    Das macht für mich nur bedingt Sinn. Wenn das Pausemenü nicht geöffnet ist, sollte es ja die Möglichkeit geben sich zu bewegen und gleichzeitig aber auch das Menü öffnen zu können. Das heißt, es ist auf jedenfall notwendig zwei InputMappinghintereinander zu verarbeiten, wenn du nicht sehr wilde Veränderungen an den Mappings selber vornehmen willst.

    Wie wäre es denn zum Beispiel mit einer Stack-Struktur in welches die Nodes ihr InputMapping hinterlegen können? Dann könntest du immer den Stack durcharbeiten bis du zu einem Mapping triffst, welches das Event nicht durchlassen will.

    Ja, über eine Stack-Struktur habe ich auch schon nachgedacht. Das wäre durchaus eine Änderung, die gut umsetzbar wäre und gleichzeitig die InputHandler-Struktur bewahren kann. Danke auf jeden Fall für den Vorschlag mit dem Stack.:)


    Ja, der InputHandler ist im Übrigen ein Singleton, sodass global ein Zugriff erfolgen kann.^^

    Das sind ja einige Fragen, die da aufkommen, Grandro .


    Ich versuche, sie alle so gut es geht, zu beantworten.


    Mir ist nicht ganz klar, wie das so mit mehreren Instanzen funktionieren soll, die auf Input reagieren wollen, da dein InputHandler ja nur ein InputMapping gleichzeitig behandeln kann.

    Das ist grundsätzlich korrekt. Ein InputHandler kann momentan nur ein InputMapping behandeln, was aktuell in der Variable current_input_map lagert. Dies soll ja genau dazu dienen, dass Inputs nicht parallel irgendwelche anderen Aktionen hervorrufen, die gar nicht erwünscht sind. In der Regel will man mit Eingaben ja auch nur eine Sache kontrollieren, sei es eine Spielfigur, die Navigation im Menü oder das Weiterklicken in einem Dialog. Sofern man mehrere Figuren kontrollieren möchte, könnte man dann zum Beispiel ein Manager-Skript erstellen, welches die Input-Map umstellt, sodass diese Funktion dann alles nach Wunsch kontrollieren kann.


    Hättest du noch eine TestMap, bzw. was spielerisch vielleicht mehr Sinn ergibt, noch ein Pausemenü oder ähnliches welches sich öffnen und schließen können lassen sollte, würden die current_input_map jeweils gegenseitig überschreiben.

    Ja, momentan würde ich das so lösen, dass das Pausenmenü dies tatsächlich umschreiben würde. Da gäbe es dann die Lösung, dass ein Menü das vorherige Mapping zwischenspeichert und beim Schließen des Menüs wiederum das zwischengespeicherte Mapping wieder in den InputHandler einlagert.


    Ist da der Plan immer genau eine Instanz zu haben, die auf Input reagieren soll?

    Dies ist mein Plan, ja. Ich wollte es so konzipieren, um die Komplexität zu verringern. Ich denke, zum Teil ist mir das auch gelungen. Natürlich gibt es aber immer Raum zur Nachbesserung.

    Wie ist es mit Logik, falls es einmal keine Instanz gibt, die auf Input reagieren will?

    Im Normalfall wird es immer ein Mapping geben, aber das ist ein sehr guter Einwand. In dem Fall muss eine if-Anweisung herhalten, die bei keinem angegebenen Mapping einfach keinerlei Reaktion mehr zeigt, also einfach alle Inputs abfängt, damit keine unvorgesehenen Nebenwirkungen auftreten.


    Wie ist es mit den anderen _input Funktionen, falls das momentane InputMapping das Event nicht weiterlassen will, soll das Event wirklich als handled gesetzt werden nur weil eine Instanz vielleicht darauf reagiert hat?

    Ich habe es gerade nochmal geprüft. Es scheint so, dass die Funktion input in den anderen Nodes immer noch funktioniert. Man könnte also auch parallele Reaktionen umsetzen, allerdings sollte man das eher vermeiden, wenn man das InputHandler-System benutzt, um die Übersicht zu behalten. Ein Event kann man grundsätzlich auch vorbeilassen mit event_can_pass. Damit wird es nicht auf gehandled gesetzt und kann weitergehen, z.B. zum GUI


    Wer soll neben InputHandler noch auf Input reagieren?

    Generell habe ich geplant, dass der InputHandler alle Inputs managed, also alle Reaktionen steuert. Daneben gibt es an für sich nur noch die Godot-Standard-Reaktionen des GUI, also Buttons, die man anklicken kann oder ähnliches.


    Ich hoffe, ich konnte die vielen Fragen gut genug beantworten. Es war einiges, aber hat mir nochmal geholfen, ein wenig über meine Umsetzung zu reflektieren.^^

    Teil 2: InputMapping und InputHandler - Umgang mit Eingaben des Nutzers

    Im letzten Teil habe ich bereits kurz über die Modul-Mechanik gesprochen und wie man darüber die angezeigten Szenen relativ bequem wechseln kann. Damit sieht man dann im besten Fall eine nette World-Map mit einem Spieler-Sprite darauf... .... Hm, nett, man sieht einen Spieler, aber es wäre schon irgendwie nett, wenn der Spieler sich bewegen könnte. Dafür bieten sich Maus und Tastatur doch an, wie man es von klassischer RPG-Maker-Manier kennt. Doch wie kommen diese ganzen Eingaben auch bei der Spielfigur an?

    Godot bietet hierbei für die meisten Objekte die Funktion _input(event) an. Diese Funktion stets dann aufgerufen, wenn eine Eingabe wie Mausbewegung oder Tastendruck erfolgen. Das heißt, man könnte Eingaben auch unterscheiden und so Aktionen bedingt der Eingabe auslösen.

    Man kann diese Funktion also theoretisch bei dem Skript des Spielers einfügen, um Standard-Bewegung zu erzeugen:

    func input(event):

       if event.is_pressed("move"): # Bewege den Spieler mit etwas CodeDamit ist es dann in der Theorie möglich, den Spieler zu bewegen. Doch es gibt ein Problem. Wenn zum Beispiel eine Dialog-Box erscheint, kann der Spieler sich noch immer bewegen, obwohl ein Dialog durchläuft. Man möchte nicht unbedingt, dass sowas in wichtigen Cutscenes passiert. Die Lösung wäre also, die Behandlung von Eingaben so zu verändern, sodass solche Dinge nicht mehr möglich sind.

    Hier kommt der InputHandler ins Spiel. Es handelt sich um eine eigene Klasse, die als System aufgefasst wird. Es wird also global eine einzige Version von diesem InputHandler erzeugt, der von überall beeinflusst werden kann.

    Hierbei besitzt der InputHandler eine Variable vom Typ InputMapping. Über den Typ InputMapping werde ich gleich noch mehr erklären.

    Mit dieser Variable wird also gesteuert, wie einkommende Eingaben behandelt werden sollen. Um solche Eingaben zu erhalten, wird hier ganz praktisch die von Godot bereitgestellte Funktion _input(event) verwendet. Hierbei wird das ankommende Event im InputMapping hinterlegt und die Input-Behandlung wird aufgerufen, was durch das call() passiert.

    Danach kommt es zur einer if-Abfrage. Hierbei kann eine Eingabe entweder passieren, also von der restlichen Engine für andere Dinge weiterverwertet werden, oder aber wird durch den Aufruf get_viewport().set_input_as_handled() als abgeschlossen markiert und nicht weiterverwendet.


    Doch wie kann man all dies sinnvoll mit dem Typ InputMapping umsetzen?

    Hierzu definieren wir einen neuen Typ InputMapping.

    Hierbei haben wir drei Variablen. handle_input_event speichert, wie auf ein Eingabe-Event reagiert werden soll.

    current_input_event wird durch den InputHandler wie bereits beschrieben auf das gerade ankommende Eingabe-Event gesetzt, also hält es einfach zeitweise dieses Eingabe-Event, um es zu verwenden.

    event_can_pass sagt aus, ob ein Event über die normale Behandlung noch weiter wandern darf.


    Damit lässt sich dann gut das Verhalten überschreiben und abhängig von angezeigter Szene definieren.

    Als Beispiel hätte ich ein Skript für eine TestMap:


    Hierbei wird die Eingabe direkt gesetzt, sobald diese Szene den Szenenbaum von Godot betritt. Man sieht hier deutlich, dass für handle_input_event eine Funktion angegeben wird, wo auf die Aktion "menu" und "left_click" reagiert wird. Auf die genauen Reaktionen auf diese beiden Eingaben gehe ich jetzt nicht ein, da das nicht wichtig für die heutige Thematik ist und eher Testzwecken dient.


    Das soll erstmal reichen. Es ist ein etwas abstrakteres Thema diesmal gewesen. Kritik und Fragen sind gern gesehen.^^ Manchmal ist es schwer, etwas genau zu erklären.

    Hallo, vielen Dank für das Feedback. Ja, eine Umbenennung von Menus zu UI ist natürlich möglich. Dieses Menus Modul sollte solche Module wie den Titelbildschirm, Optionen-Fenster und Organisations-Screens (Items, Characters, Skills, usw), wie man es vom Maker ähnlich kennt. Da das alle solche typischen Menüs sind, wollte ich das alles unter diesem Module zusammenfassen. Es sind also alles eigenständige Fenster, die nicht wirklich mit World-Modulen arbeiten. Andere UI's, die mehr mit der Umgebung in der Spielwelt zu tun haben, sind dann im World-Module zu finden. Deshalb kam es zu dieser Benennung letztenendlich.


    Mit Grandro hatte ich mich bezüglich Godot noch nicht ausgetauscht. Könnte ich vielleicht irgendwann mal machen.:)

    Hallo, alle miteinander.


    Nach langer Zeit habe ich mich mal wieder dazu aufgerafft, einen Beitrag hier im Forum zu erstellen. Da habe ich direkt auch etwas Nettes vorbereitet.:)


    Wie ich zu Godot gekommen bin?

    Durch mein Studium sollte ich in einer Gruppe ein Lernspiel erstellen. Dies sollten wir mit der Game Engine Godot machen. Schnell merkte ich, dass ich diese Engine sehr mag und ich zumindest sehr intuitiv finde. Vor allem mag ich die Skriptsprache GDScript, die einem etwas mehr Sicherheit bietet als JavaScript. Da bin ich zu dem Entschluss gekommen, mit Godot mehr zu entwickeln. Da ich aber viele Umsetzungen des RPG Makers sehr gut finde, vor allem aber das Event-System auf der Map und so weiter, wollte ich einige Mechaniken des Makers in die Godot-Engine übertragen. Ich will also eine gewisse Programm-Architektur entwickeln, die es mir erlaubt, relativ einfach ein RPG nach meinen Vorstellungen zu erstellen.

    Wer weiß, vielleicht gibt es ja ein paar Interessenten, die meinen Prozess hier ebenfalls anschauen wollen oder vielleicht selbst Inspiration erhalten, etwas in Godot umzusetzen.


    Was will ich hier dann eigentlich präsentieren?

    Ich will über die Zeit hinweg einige Ansätze vorstellen, die ich angedacht habe, um die Entwicklung eines RPG's in Godot zu ermöglichen. Ich habe natürlich viel vor mir, aber das bin ich gewohnt.^^


    Teil 1: Der Aufbau und Wechsel von Szenen durch Module

    Damit man überhaupt etwas sieht, braucht man in Godot ja nicht viel. Man legt eine Szene an und startet das Spiel...Ach wenn es so einfach wäre, würde ich hier nicht schreiben. Es gibt da nämlich ein Problem: Wie kommt von einer Szene zu nächsten? Darüber hatte ich mir Gedanken gemacht. Im RPG-Maker werden ja Szenen auf einen Szenenstack gelegt, um auch so etwas wie Menüs oder Untermenüs zu erstellen. Dieser Ansatz ist sehr nett, doch ich wollte etwas anderes probieren. Ich wollte nämlich die Baumstruktur nutzen, die einen Godot mit dem Szenenbaum bietet. Dafür habe ich dann das Konzept der Module erarbeitet.



    Was ist ein Modul?

    Ein Modul ist hierbei eine Art Objekt, welches eine Szene darstellt und den bequemen Wechsel zwischen diesen Szenen erlaubt. Dabei kann ein Modul Kinder-Module haben, die sich ebenfalls abwechseln können. Damit kann man eine gewisse Ordnung aufbauen, die die Organisation des gesamten Spiels helfen kann. Nun werde ich euch am besten den Code mal zeigen.


    Da haben wir einen einleitenden Teil. Hierbei erweitert die Module-Klasse die Basisklasse Node. Weiterhin wird der Klassenname Module im Projekt global sichtbar gemacht, um Untertypen dieser Klasse entwickeln zu können. Am Ende haben wir hier eine exportierte Variable, in der die Kind-Module eingetragen werden können. Das ermöglicht uns folgende Hilfestellung in der Engine selbst:


    Wie ihr sehen könnt, kann man damit Kind-Module mit eigenen Namen versehen und den Pfad angeben, der zu diesem Modul führt. Die kann man dann einfach in seinem Datei-System aufrufen.


    Eine wichtige andere Funktion ist dann hierbei noch die Funktion activate_child()

    Sie erlaubt es, dass ein Modul das aktive Kind gegen ein anderes tauschen kann. Zunächst wird das neue Kind aktiviert und falls es ein vorheriges aktives Kind gab, so wird es zerstört.

    Wie würde so ein Prozess dann aber visuell aussehen.

    Ich habe mir diese Struktur überlegt. Hierbei startet Main alles. Hierbei hat Main die Kinder SplashScreen und Window, die es frei verwalten kann. In meinem Fall wird zuerst der SplashScreen aktiviert und dann kommt es zu einem Wechsel zu Window, worin das eigentliche Hauptspiel stattfindet. Hierbei wird der SplashScreen wieder zerstört. Gleich darauf wird das Menu aktiviert, wodurch auch das Menu sichtbar wird. Geht man dann auf New Game, folgt der Wechsel zur World, wo dann Spielinhalt wäre wie Maps usw.


    Hier nochmal das Ergebnis. Ist jetzt visuell nicht sehr ansprechend, demonstriert aber sehr gut den Ablauf.


    Naja, ich hoffe mal, dass ich meinen Ansatz einigermaßen erklären konnte. Hat echt eine Weile gedauert, sich das Ganze auszudenken. Was sagt ihr dazu? Wünscht ihr euch mehr Teile, wo ich erkläre, wie ich weitere Dinge umsetze, z.B. Aufbau von Charakterprofilen und Battlerprofilen ähnlich der RPG-Maker-Datenbank? Schreibt es gerne hier rein.:)

    Ich habe jetzt auch mal Zeit gefunden, reinzuhören. Da sind einige interessante Tracks mit dabei. Ich finde es immer toll, von anderen Leuten die Musik zu hören. Das gibt mir selber manchmal auch neue Denkanstöße, neue Lieder zu erstellen. ^^

    Mir hat besonders Track 6 gefallen wegen dem leichten Barock-Feeling. Da habe ich sogar die Midi in FL Studio in ein Cembalo Instrument gesteckt und es hört sich echt gut darauf an. War jetzt aber nur mal zum Ausprobieren.

    Die Kitsune-Grafiken sind alle ziemlich schön. Super!^^


    P.S.: Bin jetzt erst dazu gekommen, mir den diesjährigen Kalender anzuschauen bzw. ist mir erst heute eingefallen, dass es ja noch diesen Kalender gibt.

    Hallo Anna,


    willkommen im Forum. Ich wünsche dir viel Spaß hier. Ich bin schon gespannt auf deine Musik und deine Bilder. Vielleicht stoße ich ja irgendwann auf eines deiner Werke.:)

    Hallo, auch ich habe wieder vor, am Recollab teilzunehmen und habe auch schon ein erstes Lied parat:


    Temple of Beginning.zip


    Das Lied und die Nutzungsbedingungen sind in der zip-Datei zu finden.

    Damit die Bedingungen direkt hier zu finden sind, habe ich sie schnell mal auch in die Nachricht gepackt:


    Es ist erlaubt, diese Ressourcen für freie und kommerzielle Zwecke zu verwenden unter der Bedingung, mich mit dem Namen "Eric the Funny Baron"

    oder auch "EFJ_Baron" in den Credits anzugeben.


    Wie gefällt euch das Lied? Habt ihr Ideen, zu welchen Thematiken ich noch Songs erstellen soll? Schreibt einfach hier und ich werde die Ideen und Anregungen gut verwenden.


    LG vom Baron^^