Paar Fragen



  • Tach,

    es gibt bzgl. Spieleprogrammierung ein paar Dinge die mich interessieren würden:

    1. Wie funktioniert Rendern tatsächlich? Verfügt jedes Objekt über eine eigene Render-Methode welche aufgerufen wird oder gibt es nur ein "Renderer"-Objekt an welches die zu zeichnenden Elemente übergeben werden?

    2. Wie werden einzelne Szenen programmmäßig aufgeteilt? Das heißt: ich starte das Spiel und sehe ein Intro. Nach dem Intro kommt das Hauptmenu. Danach habe ich verschiede Möglichkeiten (Spiel starten, Optionen, ...). Wie funktioniert der Wechsel zwischen den Szenen und wie sehen diese programmmäßig eigentlich aus (also gibt es für jede Szene ein eigenes Objekt, oder wie ist das)?
    Dazu kommen noch die anfallenden "Popup" Menus (zb ein Inventar), welche ja auch irgendwie angezeigt werden müssen.

    3. Wie wird Logik "ordentlich" von der Grafik getrennt? Soweit ich weiß, wird im GameLoop bei jedem Durchlauf zuerst die Logik geupdatet und dann die zu zeichnenden Elemente. Aber wie funktioniert hier eigentlich dieses "UpdateAll"-Prinzip vom Renderer (ausgehend davon, dass jedes Objekt selbst eine Render-Methode besitzt müsste diese UpdateAll-Methode ja sämtliche Render-Methoden aufrufen, was ja alles andere als hübsch ist)

    Jo, mehr fällt mir spontan nicht ein. Kennt vielleicht noch wer ein gutes Buch für OpenGL?


  • Mod

    Nestex schrieb:

    1. Wie funktioniert Rendern tatsächlich? Verfügt jedes Objekt über eine eigene Render-Methode welche aufgerufen wird oder gibt es nur ein "Renderer"-Objekt an welches die zu zeichnenden Elemente übergeben werden?

    gibt beide arten von implementierungen.

    2. Wie werden einzelne Szenen programmmäßig aufgeteilt? Das heißt: ich starte das Spiel und sehe ein Intro. Nach dem Intro kommt das Hauptmenu. Danach habe ich verschiede Möglichkeiten (Spiel starten, Optionen, ...). Wie funktioniert der Wechsel zwischen den Szenen und wie sehen diese programmmäßig eigentlich aus (also gibt es für jede Szene ein eigenes Objekt, oder wie ist das)?
    Dazu kommen noch die anfallenden "Popup" Menus (zb ein Inventar), welche ja auch irgendwie angezeigt werden müssen.

    ich habe das genau so implementiert, das interface ist bei mir:

    class CGameLayer
    {
    	std::string					m_Name;
    protected:
    								CGameLayer(const std::string& rName):
    								m_Name(rName)
    								{
    									m_Name.ToLower();
    								}
    public:
    	virtual	void				Init()			=	0;
    	virtual	void				ReInit()		=	0;
    	virtual	void				Render()		=	0;
    	virtual	void				Logic()			=	0;
    	virtual	void				Suspend()		=	0;
    	virtual	void				Release()		=	0;
    	virtual	const SNextModule	NextModule()	=	0;
    
    	bool						Is(const std::string& rName)const
    							{
    								return rName==m_Name;
    							}
    };
    

    relativ pragmatisch, das management basiert wie du schon sagtest, auf einer art stack, SNextModule enthaelt den string vom naechsten layer (optional) und immer ob push/pop/switch.

    3. Wie wird Logik "ordentlich" von der Grafik getrennt? Soweit ich weiß, wird im GameLoop bei jedem Durchlauf zuerst die Logik geupdatet und dann die zu zeichnenden Elemente. Aber wie funktioniert hier eigentlich dieses "UpdateAll"-Prinzip vom Renderer (ausgehend davon, dass jedes Objekt selbst eine Render-Methode besitzt müsste diese UpdateAll-Methode ja sämtliche Render-Methoden aufrufen, was ja alles andere als hübsch ist)

    logik laeuft durch ohne auf graphik daten zuzugreifen, die meisten logik programmierer haben auch eigene darstellungen, manche geben sich bitmaps aus (z.b. riesige TGAs), manche per webbrowser tabellen, manche mit winapi echtzeit 2d renderings und manche nutzen sowas wie glVertex um ueber das eigentliche spiel noch ihre daten auszugeben. wenn daten graphik abhaengig sind z.b. collision, dann werden die immer offline aufgearbeitet z.b. hab ich vor ewigkeiten mal die 3d modelle voxelisiert damit dann die logik mit simplen ray casts testen kann ob etwas zusehen ist bzw getroffen wurde.
    die graphik auf der anderen seite weiss nicht viel von der logik, sondern bekommt ein "state" anhand dessen die sich rendert. viele daten der graphik sind deswegen shared und falls sie fehlen z.b. eine textur, kannst du einfach eine "fix me" textur anzeigen ohne dass das spiel (bis auf optisch) irgendwie beeinflusst wird.

    Jo, mehr fällt mir spontan nicht ein. Kennt vielleicht noch wer ein gutes Buch für OpenGL?

    http://www.opengl.org/documentation/books/ 🙂



  • Erstmal danke für die Antwort.

    Ich hab mich jetzt gerade mal bisschen rumgespielt und mich in erster Linie mit den verschiedenen Szenen/Layern/Wieauchimmer befasst. Gelöst hab ichs wie folgt:

    Es gibt eine Klasse "SceneRenderer", die über eine map<string, scene*> verfügt. Die einzelnen Szenen übergeb ich dann einfach einer addScene()-Methode, welche mir die Szene (mit Namen) in die Map schreibt.
    Die Szenen selbst sind alle von "Scene" abgeleitet (verfügt im Moment lediglich über eine virtuelle render()-Methode).

    Funktioniert alles wunderbar im Moment. Was ich aber nicht weiß: wenn man eine neue Szene rendern lässt, soll die vorherige automatisch gelöscht werden. Auch keine große Kunst, aber: wenn der Inhalt der Map ein Pointer ist, wird dieser via "erase" gelöscht oder bleibt der Pointer bestehen? Wäre eher nicht so toll wenn er das tun würde.



  • Die map kann ja nicht wissen, ob sie dafür zuständig sein soll oder nicht. Wenn Du hier aber statt Scene* unique_ptr<Scene> verwendest, sind die Fronten geklärt.

    Ich habe gerade gedankliche Probleme mit rapsos Ansatz, den Programmablauf "von innen heraus" zu steuern. Ich meine, der Ablauf ist klar: "Zeige Szene A, Zeige/ Wechsle zu Szene B, füge Szene C hinzu". Nun würde doch aber jede Szene immer von ihre Folgeszene wissen müssen. Der grundlegende äußere Skript wird nach dem genannten Muster ja komplett in die Skriptbestandteile verteilt. Wie verwendet man denn so eine Szene mehrfach in unterschiedlichem Kontext, wenn sie selbst ihre Folgeszene definiert? Wie behält man da die Übersicht?



  • Okay, danke.

    Und ja, diesbzgl. hab ich auch schon festgestellt: mein Intro soll nur wenige Sekunden angezeigt werden, danach soll das Menu angezeigt werden.
    Es ist bedingt schwierig innerhalb des Intro-Objekts die Dauer festzulegen, weil das "Drumherum" keine Ahnung davon hat.
    Und - obwohl ich noch nicht dort bin - auch beim Menu selbst stell ichs mir schwierig vor. Je nach Auswahl soll eine andere Szene geladen werden - das aber kann ich nur relativ unschön lösen indem ich dem Menu-Objekt selbst einige Eigenschaften gebe und diese außerhalb dann überprüfe... nicht gerade schön.



  • rapso: Hm, schon interessant. Wie viele Layer hat man denn da so? Ich habe bei mir z.B. momentan einfach nur die 3D-Welt und nen Interface-Overlay. Gibt es einen Grund dafür, dass du das nicht so gemacht hast? Es scheint mir zumindest intuitiver. Stößt man mit einem so einfachen Model da an irgendeiner Stelle an "natürliche" Grenzen?


  • Mod

    Decimad schrieb:

    Die map kann ja nicht wissen, ob sie dafür zuständig sein soll oder nicht. Wenn Du hier aber statt Scene* unique_ptr<Scene> verwendest, sind die Fronten geklärt.

    Ich habe gerade gedankliche Probleme mit rapsos Ansatz, den Programmablauf "von innen heraus" zu steuern.

    mir ist nicht ganz klar was du damit meinst

    Ich meine, der Ablauf ist klar: "Zeige Szene A, Zeige/ Wechsle zu Szene B, füge Szene C hinzu". Nun würde doch aber jede Szene immer von ihre Folgeszene wissen müssen. Der grundlegende äußere Skript wird nach dem genannten Muster ja komplett in die Skriptbestandteile verteilt. Wie verwendet man denn so eine Szene mehrfach in unterschiedlichem Kontext, wenn sie selbst ihre Folgeszene definiert? Wie behält man da die Übersicht?

    ich habe z.b. einen editor, dieser ruft einen dialog auf zur eingabe von namen z.b. objekt name, material name, scene name.. topic, frage sowie der schlussendliche return value wird dabei in einer globalen 'state machine' abgelegt.
    die screens haben dabei bei mir meist nur funktionellen wert, daten die persistent sind, werden in einem globaln state gehalten z.b. highscore oder playerXP oder momentanes level oder...
    deswegen kann der 'manager' davon fuer jeden 'game layer' entscheiden ob er diesen z.b. suspended bevor der neue drankommt. im level editor mach ich das nicht, im spiel mach ich das, da wird das main-menue suspended wenn das level geladen wird. ist das level fertig (weil man tod ist oder es besiegt hat), wird das level released und das main menue reinitialisiert.

    wie gesagt, ist relativ trivial, aber es laeuft gut, und dadurch dass alles ueber den globalen state laeuft, was ja eigentlich wie ein haesslicher hack ausschaut, ist jeder screen fuer sich load/save sicher, und damit haben viele viele spiele probleme, weil sowas erst 'irgendwann' dran kommt oder weil es jede woche einmal kaputt ist, denn die die implementieren, die arbeiten nie mit save/load. wie gesagt, ist entscheidener bestandteil meines kleinen systems.

    ich hoffe das beantwortet die frage (bin nicht 100% sicher ob ich die verstanden hatte, notfalls nochmal fragen :D)


  • Mod

    cooky451 schrieb:

    rapso: Hm, schon interessant. Wie viele Layer hat man denn da so? Ich habe bei mir z.B. momentan einfach nur die 3D-Welt und nen Interface-Overlay. Gibt es einen Grund dafür, dass du das nicht so gemacht hast? Es scheint mir zumindest intuitiver. Stößt man mit einem so einfachen Model da an irgendeiner Stelle an "natürliche" Grenzen?

    im editor hab ich unmengen 'layer' weil es halt modale menues gibt. im spiel sind es nicht soviele, hast halt
    intro [switch] mainmenue [push] game [push] options/save/load menue

    dabei kann game halt spezialisiert sein, da gibt es z.b. tutorial, bossfight etc.

    ich weiss nicht recht wie du das mit der 3d welt meinst, ist dein main menue in der selben welt wie das intro und outtro und credits und das eigentliche spiel?

    ich habe das so gemacht, weil ich meine engine leicht nutzebar machen wollte und zugleich modular. jemand der ein modul schreibt, macht seinen layer und kuemmert sich nicht darum was noch laeuft, ob er jetzt out of memory ist weil zufaellig ein multiplayer 'overlay' noch an ist waehrend jemand seinen singleplayer startete, oder desgleichen. es ist so aenlich wie ein java applet und meine erste implementierung war auch auf lua bassierend (man hat also in lua diese callbacks bekommen, deswegen ist das switching immer noch string basierend, man kann ein "foo.lua" als ziel setzen und dann wird ein 'layer' gestartet der nur ein script wrapper ist und lua startet.

    ich bin bei sowas pragmatisch, nehme das was mir am einfachsten erscheint und witme mich dann den schoenen/spassigen dingen 🙂



  • rapso schrieb:

    im editor hab ich unmengen 'layer' weil es halt modale menues gibt. im spiel sind es nicht soviele, hast halt

    Hm, okay. Meine Spiel-Klasse hält halt einfach ein interface_overlay Objekt das wiederrum ein "desktop" Objekt hält. Wenn jetzt z.B. die Linke Mausstaste gedrückt wird, wird das zu erst gecheckt ob das overlay etwas damit anfangen kann (also ob ich z.B. ein UI-Objekt treffe), und wenn nicht, wird es weiter an die "Welt" gereicht. Passiert dann mit Tastendrücken genau so. z.B. könnte ein Eingabefeld gerade den Fokus haben, dann "fängt" das overlay eben das "w", und sonst wird es an die Welt weitergegeben. (Und der Charakter bewegt sich nach vorne - das ist zumindest der Plan. 🤡 )

    rapso schrieb:

    ich weiss nicht recht wie du das mit der 3d welt meinst, ist dein main menue in der selben welt wie das intro und outtro und credits und das eigentliche spiel?

    Das ist bei mir relativ strikt gerennt. Die 3D-Objekte leben in einem anderen Objekt als das Interface, das hat aber Zugriff auf diese. (z.B. zum Anzeigen von Lebenspunkten etc.)

    Ich bin mir allerdings noch nicht wirklich sicher ob das alles so optimal ist, deswegen höre ich gerne mal von anderen wie sie das machen. 🙂


  • Mod

    cooky451 schrieb:

    rapso schrieb:

    im editor hab ich unmengen 'layer' weil es halt modale menues gibt. im spiel sind es nicht soviele, hast halt

    Hm, okay. Meine Spiel-Klasse hält halt einfach ein interface_overlay Objekt das wiederrum ein "desktop" Objekt hält. Wenn jetzt z.B. die Linke Mausstaste gedrückt wird, wird das zu erst gecheckt ob das overlay etwas damit anfangen kann (also ob ich z.B. ein UI-Objekt treffe), und wenn nicht, wird es weiter an die "Welt" gereicht. Passiert dann mit Tastendrücken genau so. z.B. könnte ein Eingabefeld gerade den Fokus haben, dann "fängt" das overlay eben das "w", und sonst wird es an die Welt weitergegeben. (Und der Charakter bewegt sich nach vorne - das ist zumindest der Plan. 🤡 )

    das ist bei mir ein teil von der UI, das ist fuer kleineren scope. die einzelnen grossen state objekte werden erst richtig in z.b. "manager" spielen ausgereizt. du hast dann unmengen von screen, von denen jeder seine logik hat, vielleicht von unterschiedlichen menschen programmiert wird, wo vieles auch wiederbenutzt werden soll soweit es geht (z.b. ein modaler dialog in den man auf eine frage hin etwas eintippen kann). was da funzt, funzt natuerlich auch bei menue->spiel->optionen->..

    rapso schrieb:

    ich weiss nicht recht wie du das mit der 3d welt meinst, ist dein main menue in der selben welt wie das intro und outtro und credits und das eigentliche spiel?

    Das ist bei mir relativ strikt gerennt. Die 3D-Objekte leben in einem anderen Objekt als das Interface, das hat aber Zugriff auf diese. (z.B. zum Anzeigen von Lebenspunkten etc.)

    Ich bin mir allerdings noch nicht wirklich sicher ob das alles so optimal ist, deswegen höre ich gerne mal von anderen wie sie das machen. 🙂

    ich spreche nicht von logik und graphik trennung, sondern frage mich (oder eher dich 🙂 ) wie du mehrere teile vom spiel trennst, z.b. eben hauptmenue und spiel, wenn du z.b. ein weltraumhandelsspiel haettest, hast du einen teil wo der spieler rumfliegt, kaempft etc. du hast auch einen wo der spieler in einer werft ist und sein schiff bearbeitet, du hast auch einen im handelsmenue. wie trennst du das? wie haelst du das flexibel sodass mal eine zweite person mit dir dran arbeiten koennte weil sie z.b. "planetare missionen" implementieren moechte. bei mir waere das halt jedesmal so ein layer, du tritst in die atmosphere ein und switch zum layer der planeten rendert, gravitationsphysik hat etc.



  • Handelsmenü: Das ist relativ simpel. Das Interface hat ja Zugriff auf die Welt, nur nicht umgekehrt. Heißt man könnte problemlos ein Fenster schreiben das die entsprechenden Informationen ausliest und anzeigt. Das pusht man dann bei irgendeinem Tasten/Button-Druck auf den Desktop, tadaa. 🙂 Ich frage mich gerade eher, ob es neben der "Objektwelt" auch noch eine "Logikwelt" geben sollte. Solche Dinge wie Spielerlisten oder Allianzen sind ja keine Objekte im Raum..

    Und ja, dieses Fenster sollte auch eine andere Person schreiben können denke ich. Bleibt noch das mit der Werft. Hier gibt es ja wieder zwei Möglichkeiten: Die Werft "existiert" wirklich. Dann findet das ganze ja eher in der Objektwelt statt, heißt der Spieler wird an den entsprechenden Ort gewarped. Oder das ganze öffnet einfach ein "Fullscreen" Fenster, das sollte auch kein Problem sein. Interessant wird es vielleicht bei einer Mischung: Man wird gewarped und trotzdem tauchen neue UI Objekte auf. Das ist zwar sicher möglich, aber vielleicht nicht so hübsch, weil die UI dann quasi checken muss "hey, ist der Spieler in der Werft?". Hier wäre es uU schon interessant, die UI aus der Welt heraus verändern zu können. Hm..


Anmelden zum Antworten