Toon posts:

[C++] Scripting taal voor 3D engine

Pagina: 1
Acties:

Verwijderd

Topicstarter
Vandaag zat ik even na te denken hoe ik een snelle scripting taal zou kunnen maken om bepaalde dingen stukken programmeercode in m'n engine automatisch te laten gebeuren. Commando's als deze zouden worden uitgevoerd:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// script code, geen C++ dus!
// veronderstel dat de klassen "Map" en "Camera" beide
// afgeleid zijn van de abstracte basisklasse "SceneObject"

// maak een map
Map level = LoadMap("test.map");
// maak een camera
Camera myCam;
// voeg ze beide to aan de scene
AddToScene(level);
AddToScene(myCam);
// render de scene
while(active)
{
    RenderScene();
}


Nu zou ik het natuurlijk real-time kunnen analyseren, maar het zou heel traag werken (zelfs met bytecode) als ik telkens het commando "RenderScene()" zou gaan analyseren, elke keer het wordt aangeroepen.

Wat ik zou doen is het volgende:

Elke instructie de de scriptingtaal herkent, zou ik definieren in een klasse(bvb scriptRenderScene(), scriptLoadMap(), ... Elk van deze instructieklassen is afgeleid van een abstracte basisklasse "ScriptInstructie".
Bij het inlezen van het script maak ik een lijst aan van alle specifieke commando's en plaats ik deze in een lijst van "ScriptInstructie". Bij het doorlopen van die lijst worden de instructies aangeroepen:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class ScriptInstructie
{
    public:
        ScriptInstructie();
        virtual ~ScriptInstructie();
        virtual void Run() = 0; // gestart door linked list!
};


class scriptLoadMap : public ScriptInstructie
{
    public:

        scriptLoadMap (string file) // laad de map
        {
             realMap = new RealMapObject;
             realMap->Load(file);
        }

        virtual ~scriptLoadMap ();

        virtual void Run() // gestart door linked list!
        {
             realMap->Render();
        }

    private:

        RealMapObject* realMap;
};

int main()
{
      LinkedList<ScriptInstructie> lijst;
      // bij het inlezen van het script komt men op een zeker moment
      // het commando " LoadMap("test.map");" tegen. Dit wordt dan 
      // als volgt toegevoegt aan de lijst:
      // lijst.Add(new scriptLoadMap("map"));
      Lijst.RunThroughAllItemsAndExecuteThem(); // duidelijk, niet? ;) :P
}


[edit] Natuurlijk is het wel mogelijk dat ik fouten heb getypt, maar de basisidee begrijpen jullie wel ;)

[ Voor 11% gewijzigd door Verwijderd op 04-12-2003 11:24 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:32

.oisyn

Moderator Devschuur®

Demotivational Speaker

Maar wat is nou precies je vraag? Dat staat er verder niet bij. :)

En je zou eens naar lua kunnen kijken... of je moet wachten tot ik Orbb af heb :P

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
De vraag lijkt me duidelijk, is het verstandig om voor een interpreter de parse slag vooraf te doen. Het antwoord is inderdaad ja, en de gesuggereerde methode is redelijk verstandig. De enige vraag is of elke instructie een RealMapObject* nodig heeft. Dat maakt zo'n object onnodig groot; de execution engine kan die pointer gewoon runtime meegeven. Een beetje optimizer laat 'm dan keurig in een register staan.

Overigens is RunThroughAllItemsAndExecuteThem natuurlijk geen zinnige member voor een linked list, dan is veel meer iets voor een free function. De naam is ook een beetje lang; ik zou'm for_each hebben genoemd :)

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Verwijderd

Topicstarter
Hey, sorry, in al m'n typen ben ik vergeten om eigenlijk de vraag de plaatsen. Wat ik eigenlijk wou vragen: is dat een goede manier van werken of zou ik het beter anders doen?

Lua en andere scriptingtalen wens ik niet te gebruiken omdat ik zo niks bijleer ivm scripting talen maken. Zelf heb ik al een basis gemaakt om scripts (in C++ stijl) in te lezen.
Overigens is RunThroughAllItemsAndExecuteThem natuurlijk geen zinnige member voor een linked list, dan is veel meer iets voor een free function. De naam is ook een beetje lang
LOL :D die naam was gewoon maar een voorbeeldje hoor ;) Zulke namen gebruik ik nooit. Ik was gewoon te lui om de beschrijving nog eens in een comment te zetten ;)

[ Voor 35% gewijzigd door Verwijderd op 04-12-2003 15:49 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:32

.oisyn

Moderator Devschuur®

Demotivational Speaker

bytecode generatie is wel een veel gebruikte methode hoor... Quake 1 en 3 deden het ook zo, hoewel daar waarschijnlijk nog een vertaalslag van bytecode naar x86 asm tussen zit

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Verwijderd schreef op 04 december 2003 @ 15:47:
LOL :D die naam was gewoon maar een voorbeeldje hoor ;) Zulke namen gebruik ik nooit. Ik was gewoon te lui om de beschrijving nog eens in een comment te zetten ;)
for_each doet geen belletje rinkelen? 't Is namelijk een standaard C++ functie, die een functie aanroept op elk element van een lijst/array/... Het leek alsof je ze zelf wilde schrijven.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Verwijderd

Topicstarter
MSalters schreef op 04 december 2003 @ 16:24:
[...]

for_each doet geen belletje rinkelen? 't Is namelijk een standaard C++ functie, die een functie aanroept op elk element van een lijst/array/... Het leek alsof je ze zelf wilde schrijven.
Het doet wel een belletje rinkelen, maar zelf heb ik het ook nooit echt gebruikt. Ik denk alleen dat het niet toepasbaar is op m'n eigen (templatized) linked list klasse...

@.oisyn:
Bytecode is inderdaad veel gebruikt, maar niet echt nodig voor mijn implementatie: het laden van de scripts mag gerust even duren (nouja, nog geen volle seconde), dus kdenk niet dat het nodig is om het voor mijn toepassing. Tenzij je me een goede reden kan geven waarom wel natuurlijk, ksta altijd open voor suggesties, dat weet je.

[ Voor 28% gewijzigd door Verwijderd op 04-12-2003 18:11 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:32

.oisyn

Moderator Devschuur®

Demotivational Speaker

Euh nou ik zei het omdat je zelf zei dat het met bytecode ook traag zou werken, ik probeer alleen maar aan te geven dat dat niet zo hoeft te zijn :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 22-05 16:53
Verwijderd schreef op 04 december 2003 @ 18:09:
Het doet wel een belletje rinkelen, maar zelf heb ik het ook nooit echt gebruikt. Ik denk alleen dat het niet toepasbaar is op m'n eigen (templatized) linked list klasse...
Als je er een iteraror voor geschreven hebt die de STL snapt wel :)

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • Macros
  • Registratie: Februari 2000
  • Laatst online: 30-04 09:28

Macros

I'm watching...

Je kan natuurlijk een compiler voor je script schrijven die C++ compiled wat je dan in je programma linked. (dan heb je wel vragen, wat is een script en wat niet :))

"Beauty is the ultimate defence against complexity." David Gelernter


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:32

.oisyn

Moderator Devschuur®

Demotivational Speaker

Macros: het idee van een scripttaal in games is dat je niet de hele core opnieuw hoeft te compilen als er wat aan de gamelogic veranderd... iets dat vaak gebeurt, met name in de balancing fase. Dus dat lijkt me niet echt gewenst :)

Een ander idee is wel om gewoon gebruik te maken van shared libraries a la DLLs, maar dat is nou ook niet bepaald ongecompliceerd (mods zijn minder toegankelijk; mensen moeten een compiler hebben, je zit met memory management, etc.).

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Waarom schrijft iemand eigenlijk zelf nog een linked list class?

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Verwijderd

Topicstarter
MSalters schreef op 04 december 2003 @ 22:24:
Waarom schrijft iemand eigenlijk zelf nog een linked list class?
Dat kan verschillende redenen hebben:

1) Om bij te leren (belangrijkste argument)
2) Omdat CTextureManager : public CLinkedList nu eenmaal leuk staat :p
3) Omdat de syntax van een eigen Linked list leesbaarder is
4) Omdat je bepaalde stukken code kan aanpassen aan de behoeften van de implementatie
5) ...

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:32

.oisyn

Moderator Devschuur®

Demotivational Speaker

Mja, ik zie niet in hoe een texture manager een linked list is. Hij heeft intern een linked list ja, maar dat is heel wat anders.

Bovendien lijkt het me zinniger dat ie een hashtable heeft, met de texture bestandsnaam als key. Dan kun je bij het laden van nieuwe texture in 1 keer zien of ie al bestaat of niet, en hoef je dus niet de hele lijst af te gaan (en dat lijkt me toch een van de core doelen van de texture manager, kijken of een texture al geladen is, en zo ja, die retourneren, en anders de texture inladen en retourneren)

[ Voor 20% gewijzigd door .oisyn op 04-12-2003 22:45 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
.oisyn schreef op 04 december 2003 @ 22:44:
Mja, ik zie niet in hoe een texture manager een linked list is. Hij heeft intern een linked list ja, maar dat is heel wat anders.

Bovendien lijkt het me zinniger dat ie een hashtable heeft, met de texture bestandsnaam als key. Dan kun je bij het laden van nieuwe texture in 1 keer zien of ie al bestaat of niet, en hoef je dus niet de hele lijst af te gaan (en dat lijkt me toch een van de core doelen van de texture manager, kijken of een texture al geladen is, en zo ja, die retourneren, en anders de texture inladen en retourneren)
Dat ben ik van plan hoor ;) Zoiets had ik al op gameskool gepost trouwens. Alleen doe ik het iets anders: ik ga per texture een lijst van "owners" (of owner id's) bijhouden, opdat de texture niet 2x wordt geladen en ook niet wordt ontladen als slechts 1 van de "owners" zijn 'registratie' ongedaan maakt.
Het is iets trager dan een algemene hash-table, maar tenslotte doet 1/10s er niet echt toe bij het laden van een texture, want dit gebeurt in mijn geval niet real-time, maar vooraf bij het laden van de map.

Na het laden wordt een pointer weergegeven die wijst naar de juiste texture klasse, dus moet ik niet telkens door heel de lijst gaan, telkens ik de texture nodig heb.

[ Voor 9% gewijzigd door Verwijderd op 05-12-2003 08:22 ]


  • MisterData
  • Registratie: September 2001
  • Laatst online: 27-05 21:51
Wat dacht je van runtime compiled assembly? tis nog gratis ook :) Bovendien heeft de maker ervan ook al een Pixel Shader-emulator gemaakt die dmv runtime compilation je in staat stelt een shader uit een tekstbestand te laden en te testen :)

Verwijderd

Topicstarter
MisterData schreef op 05 december 2003 @ 16:47:
Wat dacht je van runtime compiled assembly? tis nog gratis ook :) Bovendien heeft de maker ervan ook al een Pixel Shader-emulator gemaakt die dmv runtime compilation je in staat stelt een shader uit een tekstbestand te laden en te testen :)
Als ik nou ook nog assembler kon dan was het handig ;) Toch bedankt voor het voorstel.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Verwijderd schreef op 05 december 2003 @ 08:20:
[...]


Dat ben ik van plan hoor ;) Zoiets had ik al op gameskool gepost trouwens. Alleen doe ik het iets anders: ik ga per texture een lijst van "owners" (of owner id's) bijhouden, opdat de texture niet 2x wordt geladen en ook niet wordt ontladen als slechts 1 van de "owners" zijn 'registratie' ongedaan maakt.
Het is iets trager dan een algemene hash-table, maar tenslotte doet 1/10s er niet echt toe bij het laden van een texture, want dit gebeurt in mijn geval niet real-time, maar vooraf bij het laden van de map.

Na het laden wordt een pointer weergegeven die wijst naar de juiste texture klasse, dus moet ik niet telkens door heel de lijst gaan, telkens ik de texture nodig heb.
Je kunt natuurlijk ook smart pointers gebruiken. Hou zelf een weak_ptr<Texture>, stop'm in een std::map met de texture identifier als key en je bent klaar. Niks zelf proggen als het effe kan, je hebt al genoeg werk.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Verwijderd

Topicstarter
MSalters schreef op 05 december 2003 @ 23:57:
[...]

Je kunt natuurlijk ook smart pointers gebruiken. Hou zelf een weak_ptr<Texture>, stop'm in een std::map met de texture identifier als key en je bent klaar. Niks zelf proggen als het effe kan, je hebt al genoeg werk.
Yeah smart pointers rulen :) Maar in deze implementatie wordt bij de destructie van de klasse sowieso al de hele lijst doorlopen en geheugen vrijgemaakt. Ik zou eerder auto_ptr gebruiken, omdat ik dan de boost-library niet nodig heb :)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:32

.oisyn

Moderator Devschuur®

Demotivational Speaker

auto_ptr's kun je alleen niet in containers stoppen

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1