Du könntest eine Art Diff der Objekte im Speicher halten - sprich: Wenn du die Map verläßt werden die Daten gesichert, die gegenüber den Standarddaten verändert wurden. Damit würdest du den Speicherbedarf reduzieren können.
Das könnte man so realisieren, daß du einen Queue von Pointern auf Structs mit Diffs hast, wobei jeder Diff angibt, zu welchem Objekt er gehört. Beim Laden der Map wird dann der Queue durchlaufen und die Objekte werden initialisiert. Die einzelnen Queues sind in einem Baum organisiert oder liegen als Member der Mapobjekte vor.
Falls das zu viel Aufwand auf einmal ist und die Maps hinreichend groß sind könnte man auch die Map partitionieren und die Objekte erst nach und nach initialisieren (alternativ könnte man auch Precaching betreiben und alle Objekte aus anliegenden Maps/Partitionen initialisieren, bevor der Spieler sie betritt; das braucht aber natürlich mehr Ressourcen). Allerdings muß man beachten, daß einige Events nur dann Sinn machen, wenn sie gleich aktiv sind.
Das mit den Timern könnte man dadurch lösen, daß man eine globale Liste (vermutlich Multimap) mit ausstehenden Events macht, in der sich die Events mit einem Zeitstempel (bspw. time()+300 für "in fünf Minuten") eintragen. Wann immer ein Stempel niedriger als time() ist wird die zugehörige Funktion ausgeführt. So muß man nur über eine Liste iterieren, anstatt 1000 Warteschleifen laufen zu haben. (Hmm, gibt's da nicht eine effizientere Wartemethode? Threads können ziemlich efffizient warten...)
Die Markierung, daß das Event durch ist, könnte man so machen: Wenn das Event in der Zeitliste gestartet wird wird es aus selbiger entfernt - wenn es wieder was getimert haben will muß es sich neu eintragen (oder man benutzt einen Befehl, um den Timer explizit zu beenden). Damit das Ding beim Betreten der Map nicht neu ausgelöst wird macht es im entsprechenden diff einen Eintrag, daß es bereits gelaufen ist.
Ich weiß nicht, ob dich diese Ideen weiterbringen, aber hey, du hast darum gebeten...
Das mit den Timern könnte man dadurch lösen, daß man eine globale Liste (vermutlich Multimap) mit ausstehenden Events macht, in der sich die Events mit einem Zeitstempel (bspw. time()+300 für "in fünf Minuten") eintragen. Wann immer ein Stempel niedriger als time() ist wird die zugehörige Funktion ausgeführt. So muß man nur über eine Liste iterieren, anstatt 1000 Warteschleifen laufen zu haben. (Hmm, gibt's da nicht eine effizientere Wartemethode? Threads können ziemlich efffizient warten...)
...
Timestamps könnte allerdings beim Speichern ziemliche Probleme machen, nicht? Wenn man z.B. (habe ja keine Ahnung, was das für ein Spiel ist) einen Schalter betätigt, und dann innerhalb von 5 Minuten aus dem Gebäude fliehen muss (Pfeil- und Kugelfallen optional), und man während dem Countdown speichert, wäre er automatisch abgelaufen, wenn man nach mehr als 5 Minuten wieder lädt. :-/
Man müsste dann beim Abspeichern die aktiven Timer mit timestamp - time () abspeichern, und beim Laden dann wieder die aktuelle Zeit dazuaddieren.
Sorry, dass ich nicht mehr beitragen kann, kenne mich da nicht wirklich aus.
Timestamps könnte allerdings beim Speichern ziemliche Probleme machen, nicht? Wenn man z.B. (habe ja keine Ahnung, was das für ein Spiel ist) einen Schalter betätigt, und dann innerhalb von 5 Minuten aus dem Gebäude fliehen muss (Pfeil- und Kugelfallen optional), und man während dem Countdown speichert, wäre er automatisch abgelaufen, wenn man nach mehr als 5 Minuten wieder lädt. :-/
Man müsste dann beim Abspeichern die aktiven Timer mit timestamp - time () abspeichern, und beim Laden dann wieder die aktuelle Zeit dazuaddieren.
...
Natürlich muß man den Kram schon auf eine sinnvolle Art speichern. Esv kann auch gut andere Methoden geben, die gut funktionieren; das mit time() ist nur eine simple Mathode, den Kram umzusetzen.
Man könnte sich auch die ganzen Aufrufe sparen, indem man eine globale Variable nimmt und die irgendwo inkrementiert (sich also seine eigenen Zeitscheiben definiert), aber da muß man aufpassen, daß die Zeitscheiben auch wirklich eine konstante, bekannte Länge haben.
Hm, okay, ich werd's mal so mit einer art Differenz der geladenen Daten zu den veränderten Daten probieren. Reduzieren würde man den Speicheraufwand jedenfalls schonmal. Hoffe dass es auch im Effektiven Bereich ist.
----
Ich hab dann noch eine andere Frage bezüglich C / C++. Ich würde gerne eine Funktion vervielfältigen, dass ich sie per Funktionsname[3] einzeln aufrufen kann. Diese Funktionen sollen natürlich einzeln definiert werden können.
Ein Pointer-Array auf verschiedene Funktionen (die dann zwar mit einem Pointer aus dem Array ansprechbar, aber mit verschiedene Namen definiert werden) hilft mir also nicht weiter.
Also die eigentliche Definition der Funktionen soll in etwa so aussehen können:
Ansprechbar dann über funktion[2]() oder einen ähnlichen Ausdruck.
Gibt's da eine Möglichkeit, das irgendwie zu machen?
Also ich wuerde das Problem wahrscheinlich so angehen ..
Ich denke, dass es das beste waere, alle Objekte die ganze Zeit im Speicher zu haben. Bei den heutigen Systemen spielt das auch keine allzugrosse Rolle. Sollte es dabei viel Redundanz geben (z.B. bei Schaltern) koennte man gruppenbasierte Metaobjekte erzeugen und Einzelobjekte simulieren. Wird ein Objekt nicht mehr benötigt, wird es einfach als Speicher freigegeben. Wird ein Objekt noch fuer spaeter benoetigt, wird es im Speicher gehalten.
Was die Sache mit den Scripts angeht, so ist dies eventuell auch recht einfach. Jedes Objekt bekommt eine Eigenschaft, auf welcher Map (oder welchen Maps) es verankert ist. Ist es auf keiner Map verankert, so gibt es dafuer eine spezielle ID. Zudem gibt es eine Messagequeue zum Senden von Botschaften an alle eingetragenen Funktionen. Beim ersten Initialisieren eines Objektes hat das Objekt nun die Moeglichkeit 2 Call-Back-Funktionen als Handler in den Queues einzutragen. So ist es bei den meisten Objekten sinnvoll, dass in die All-Object-Queue ein Handler fuer ein Enter_Map_Event und ein Leave_Map_Event eingetragen wird. Diese Handler pruefen dann die aktuelle Map_ID und registrieren bzw. entfernen weitere Messagehandler in der Queue. Somit brauchen die Scripte nur genau dann Rechenleistung, wenn man sich auf einer Map befindet, auf der sie die Messages ueberhaupt abfragen muessen. Dass dennoch fuer fast jedes Objekt eine CallBack Funktion durchlaufen wird, wenn die Map verlassen oder betreten wird, sollte verschmerzbar sein, da hierbei ohnehin externe Resourcen geladen werden muessen. Die Geschwindigkeit der Messagequeue kann zudem optimiert werden, wenn die Message nicht in den Handlern auf den korrekten Typ ueberprueft wird, was der Fall waere, wuerde die Queue aus Funktionspointern bestehen, sondern wenn stattdessen Structs aus Funktionspointer und einer Liste/einem Array akzeptierter Messages gespeichert wuerden. So lassen sich unnoetige Funktionsspruenge vermeiden. Nicht die IFs, sondern die Calls fressen Resourcen, da damit der Instructioncache des Prozessors unbrauchbar wird.
Was dein anderes Problem angeht, hab ich keine Ahnung, was du genau machen willst. Laut deiner Beschreibung iist doch ein Array von Funktionspointern auf verschiedene Funktionen ganz genau das, was du haben willst. Wieso nutzt dir das nichts ? Oder willst du etwa zur Laufzeit neue Funktionen schreiben und dann deinem Array hinzufuegen ? Dann musst du wohl oder uebel auf dynamisches Linken zurueckgreifen und mit Dlls bzw .so arbeiten. Gib uns am besten mal ein konkretes Beispiel, wofuer du das brauchst. Sicherlich gibt es fuer dich eine elegantere Loesung, z.B. Arrays von Funktionspointern oder Templates ...