ZweiDe

Übersicht Sonstiges Smalltalk

Gehe zu Seite Zurück  1, 2, 3 ... 10, 11, 12 ... 18, 19, 20  Weiter

Neue Antwort erstellen

Fetze

BeitragMo, Feb 08, 2010 18:15
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich steige gerade auf OpenAL um. Dabei sind mir drei Dinge aufgefallen:

1. Man sollte auch OpenAL nicht mit State-Changes überfluten.
2. OpenAL stellt - auf meinem System, das eine relativ gute Soundkarte hat - maximal 32 simultane SoundSources zur Verfügung, d.h. maximal 32 gleichzeitig spielende Sounds
3. Im derzeitigen Prototypen werden viel zu viele verbraucht.

Ein Beispiel: Ein EquipSlot kann einen Sound erzeugen, wenn ein Projektil abgefeuert wird. Ein Schiff hat im Test drei EquipSlots, die simultan Feuern. Vier Schiffe feuern mit einer Feuerrate von zwei Projektilen pro Sekunde. Ein Abschusssound benötigt 2 Sekunden, bis er wieder freigegeben werden kann.

Ein EquipSlot benötigt also im Dauerfeuer hier bereits vier bis fünf SoundSources. EIn Schiff benötigt also zwölf bis fünfzehn. Vier Schiffe brauchen damit 48 bis 60 SoundSources - und dabei sind so Sachen wie Antriebsgeräusche noch gar nicht mitgerechnet. Ich muss also drastisch kürzen.


Der Plan sieht wie folgt aus:
1. Implementierung eines Pools aus SoundSources, die (a) wiederverwendet werden (Macht alles etwas schneller) und (b) nur in endlicher Menge zur Verfügung stehen. Soll ein Sound gespielt werden und es steht keine SoundSource zur Verfügung, muss die mit der niedrigsten Priorität dran glauben. Die Priorität berechnet sich aus der aktuellen Hörbarkeit.

2. Bei Programmstart wird die Zahl der zur Verfügung stehenden SoundSources ermittelt. 3D Sounds (Ingame, Space) und 2D Sounds (UI, Musik) bekommen getrennte Prioritätslisten, die 3D Sounds erhalten 3/4 aller SoundSources, die 2D Sounds den Rest. Wären bei mir also 24 contra 8 SoundSources.

3. Bevor ein Sound gespielt wird, muss zunächst ermittelt werden, ob ähnliche Sounds derzeit spielen und ob sich diese Sounds zusammenfassen lassen. Drei nebeneinander liegende Abschussgeräusche eines Projektils kann man getrost zu einem einzigen zusammenfassen und dieses eine etwas lauter abspielen.

4. Contentseitig sollten Sounds eventuell etwas gekürzt werden, also FadeOuts beschneiden, etc., insbesondere bei Sounds, die sehr oft gespielt werden.

5. Wenn das alles drin ist und super rennt, müssen Sachen wie Doppler und DistanceModel neu gebalanced werden

6. Ganz zum Schluss muss Streaming Support rein - für Hintergrundmusik später dann.



Es ist eine lange ToDo und die nächsten Tage werde ich definitiv mit Lernen für kommende Klausuren verbringen müssen. Ich bin auch nicht ganz sicher, ob das Resultat am Ende zufriedenstellend sein wird. Sicherheitshalber habe ich den irrKlang-Branch abgezweigt, sodass ich jederzeit alle mit OpenAL verbundenen Änderungen rückgängig machen kann.

Hat jemand Erfahrungen mit OpenAL und Soundpriorisierung?

Fetze

BeitragFr, Feb 19, 2010 13:25
Antworten mit Zitat
Benutzer-Profile anzeigen
OpenAL ist drin und läuft, inklusive Streaming für größere Dateien, Budget-based Musik / Ambient, 3D-Kram wie Doppler und Co.

Danach habe ich ein wenig am Schadenssystem gearbeitet. Folgendermaßen siehts intern aus:

Arrow Ein Schiff hat einen Stapel von ArmorTypes - am Anfang die oberste Schicht, zuletzt die unterste. Zwei davon werden mit dem ArmorType der Schiffspanzerung und dem des Standardschildes direkt bei Schiffserstellung hinzugefügt.
Arrow Wird dem Schiff Schaden zugefügt, geschieht das mit einem WarheadType und dem Schadenswert. Jeder ArmorType kann jedem WarheadType einen Schadensmultiplikator zuordnen - beispielsweise kann eine bestimmte Panzerung bestimmte Munitionstypen in ihrem Schaden halbieren. Oder aber ein Schild nimmt nur begrenzten Schaden von Projektilwaffen auf.
Arrow Der Stapel wird nun von oben nach unten durchlaufen. Jede Schicht modifiziert den Schadenswert durch den Faktor.
Arrow Die Schichten, die vom Schiff selbst stammen (Und nicht beispielsweise durch Upgrades hinzu kamen) nehmen eine besondere Rolle ein: Erreicht der zugefügte Schaden eine solche Schicht, wird abgebrochen und der Schaden je nach Typ dem Schild oder der Panzerung zugefügt. Wird eine solche Schicht erreicht, und der assoziierte Wert ist bei 0, wird die Schicht ignoriert, auch ihre Schadensfaktoren werden nicht angewandt (Beispiel: Das Schutzschild ist unten, Schildschicht tut so, als gäbe sie es nicht)

So weit, so gut, aber warum so kompliziert? Nun, zum einen ist es so komfortabel möglich, die Wirkung verschiedener Geschosse auf verschiedene Empfänger (Schild oder Panzerung) abzustimmen. Zum anderen ist so bereits der Weg geebnet, für Schiffsupgrades à la Panzerungsupgrade 1 - 3 in StarTrade: Einfach an der richtigen Stelle eine neue ArmorType-Schicht in den Stapel einfügen und fertig Smile


Übrigens gibts hier jetzt ein Unterforum, in dem ich öfter mal was zum Fortschritt des Projekts schreibe und wo auch viel Platz für Anregungen und Kritik ist Smile

ozzi789

BeitragFr, Feb 19, 2010 20:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Nicht das du denkst niemand liest deine Posts, verfloge den Thread interessiert Smile
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5

Fetze

BeitragFr, Feb 19, 2010 20:52
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke, ich freu mich immer, wenn sich hier mal jemand anderes als ich selbst zu Wort meldet. Smile
So Selbstgespräche sind auf Dauer doch meist recht ermüdend Laughing

Arbeite jetzt, aufbauend auf dem Schadenssystem am Schildeffekt:
user posted image

Einfacher Partikeleffekt, der immer dann zu sehen ist, wenn eine Waffe beliebigen Typs Schildschaden verursacht. Die Intensität wird dem zugefügten Schaden angepasst, für jeden Schifftyp kann man optional auch ein ColShape speziell fürs Schutzschild angeben. Letzteres ist sowohl für die Performance gut (Schild-ColShapes sind in der Regel einfach nur Kreise, bzw. ein Radius, in den das Schiff passt) als auch für den Schildeffekt an sich.

ComNik

BeitragFr, Feb 19, 2010 22:24
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich kann mich nur ozzi anschliessen!
Genialer Effekt. Ich fand schon die Effekte für Schaden am Schiff in Star Trade richtig cool, aber jetzt sieht das ganze noch besser aus.

lg
ComNik
WIP: Vorx.Engine

Fetze

BeitragSa, Feb 20, 2010 16:02
Antworten mit Zitat
Benutzer-Profile anzeigen
Die Game Engine umfasst mittlerweile 45 Dateien und ist vom Quellcode her ein gutes halbes Megabyte groß. Ich vermute, von einem Spiel, noch dazu einen 2D Spaceshooter, dessen Funktionsumfang irgendwo zwischen Techdemo und Pre-Alpha steht, würde man in aller Regel weit weniger erwarten. Zeit, für ein paar Worte an die Technikinteressierten.

Grundaufbau / Codestruktur
Die gesamte Game Engine befindet sich in einer .dll-Datei, das Spiel selbst bindet diese ein, leitet die SteApp-Klasse ab, überschreibt einige ihrer virtuellen Funktionen, erstellt eine Instanz davon, übergibt ihr einige Parameter und ruft dort "Run" auf. Im Wesentlichen ist die .exe nur eine Möglichkeit, die Engine wegzukapseln und über die Bedingungen zu bestimmen, unter denen mit dieser ein Spiel gestartet wird: Pfade, Namen, Initialgamestate.

Diese Application-Klasse erstellt, verwaltet und beendet eine Reihe von Tasks. Ein Task ist eine Klasse, die das Interface ITask implementiert, welches eine Update-Funktion bereitstellt und nach Außen einen Wert für die angestrebte Zeit zwischen zwei Updates bereitstellt. Unter den Tasks befinden sich Dinge wie der GameObjectManager, Content- und DataProvider, sowie Klassen für Player und Camera, zumeist Singletons. Alles in allem werden die Tasks also genutzt, um verschiedene Bereiche der Engine zu verwalten. Die Application-Klasse ist somit modular leicht erweiterbar und muss sich selbst um nichts kümmern.

ContentProvider
Hachja, der ContentProvider. Eine der ersten Entscheidungen, die ich getroffen habe: Dem ContentProvider werden Suchpfade übergeben, welche Rekursiv nach verwertbarem Content (Grafiken, Soundeffekte, Shader, etc.) durchsucht werden. Die gefundenen Rohdaten werden als "Content Atoms" registriert, mit Pfad, Typ und Name. Ein solches Atom speichert - sobald angefordert - Daten wie die Pixmap einer Grafik, die Pcm-Daten eines Sounds, den Quellcode eines Shaders, kurzum: Daten, die im RAM verweilen und bereit zur Weiternutzung gehalten werden.
Wird nun eine Grafik als Textur Ingame gebraucht, wird ein sogenanntes "Content Molecule" angefordert: Ein Content Molecule hat einen bestimmten Typ und kann sich aus mehreren Atomen zusammensetzen, so kann ein angeforderter Shader beispielsweise aus Fragment- und Vertex-Quellcode bestehen und ein Sound aus Pcm-Daten und Daten aus einer Infodatei. Das tolle an der Sache: Mehrfach verwendete Daten werden aufgrund der darunterliegenden Atomarebene nur einfach referenziert, also niemals doppelt geladen. Auch werden niemals Dateiendungen angegeben, sondern nur Namen - was darunter liegt, ist ContentProvider-Intern und irrelevant für alles darüber.
Ein angefordertes Molekül bleibt jedoch trotz allem eine leere Hülle, eine bloße Referenz; erst, wenn es auch verwendet wird - sprich: Auf die zB. Textur selbst wird zugegriffen wird - wird dieses Molekül "gecached": Es fordert all seine Atome auf, ihre Daten zu cachen (Verwenden mehrere Moleküle diese Atome, sind die Daten bereits da!) und erstellt auf Basis dieser Daten (zB. einer Pixmap) dann seinen eigenen Inhalt (zB. eine Textur). Wird dasselbe Molekül mehrfach angefordert, wird immer eine Referenz auf dieselbe Molekülinstanz zurückgeliefert.
Um den Speicher zu schonen, besitzt jedes Molekül und jedes Atom einen Timeout: Bleibt es zu lange ungenutzt, wird der Cache geleert. Bei Wiederverwendung, wird er erneut angefordert, die Referenzen bleiben aber die ganze zeit über dieselben.

Ein möglicher nächster Schritt wäre, das Caching von Atomen und Molekülen in einen separaten Thread zu verlagern.. aber ich denke nicht, dass das nötig sein wird, wenigstens vorerst nicht. In einem Ladevorgang ließen sich sofort nötige Daten pre-Cachen, sollte Ingame dann nochwas fehlen (zB. durch später hinzugekommene Objekte, etc.), kann das schnell nachgeladen werden. Werden andere Daten nicht mehr benötigt, werden diese automatisch freigegeben, nachdem ihr Timeout abgelaufen ist. Der Speicherbedarf wird also auf dem nötigen Minimum gehalten.


So, das wars erstmal. Wenns wen interessiert, kann ich auch gerne von Zeit zu Zeit noch auf andere Dinge zu sprechen kommen, beispielsweise den DataProvider, der sich um reinen Datencontent (.ini Wink ) kümmert.

coolo

BeitragSa, Feb 20, 2010 18:15
Antworten mit Zitat
Benutzer-Profile anzeigen
Sehr interessant! Freue mich auf mehr.

Btw. wird es eine offene Spielwelt geben (like ST1) oder mehr so Missionen? Ich würde ersteres mehr begrüßen. Im Forum steht leider nichts Eindeutiges...
http://programming-with-design.at/ <-- Der Preis ist heiß!
That's no bug, that's my project!
"Eigenzitate sind nur was für Deppen" -Eigenzitat

ComNik

BeitragSa, Feb 20, 2010 20:56
Antworten mit Zitat
Benutzer-Profile anzeigen
Unbedingt mehr von solchen Erläuterungen. Immer interessant zu lesen.

lg
ComNik
WIP: Vorx.Engine

Fetze

BeitragSo, Feb 21, 2010 0:46
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:
Btw. wird es eine offene Spielwelt geben (like ST1) oder mehr so Missionen? Ich würde ersteres mehr begrüßen. Im Forum steht leider nichts Eindeutiges...


In dem Forum, das ich vor einiges Posts verlinkt habe, sollte das eigentlich irgendwo stehen Smile
Die Antwort nochmal für diesen Thread: Es wird keine freie Spielwelt geben, der Arbeitstitel StarTrade2 bedeutet lediglich so viel wie "Space game halt, noch kein richtiger Titel, das erste, was mir eingefallen ist".

Während StarTrade sich an Spielen wie X, Freelancer oder Privateer orientierte, soll zu den Vorbildern für StarTrade2 eher "Conflict: FreeSpace" zählen: Eine packende Storyline mit gescripteten Missionen und festgelegter Kampagne. Ich habe mittlerweile einiges an Engines und Simulationen geschrieben, aber noch nie eine Geschichte erzählt. Das möchte ich gerne nachholen.
Ich denke jedoch über einige Dinge nach, das ganze noch etwas aufzupeppen, beispielsweise ein Ausrüstungssystem à la StarTrade, das sich über die Missionen hin fortsetzt. Der Spieler könnte zum Beispiel ein eigenes Schiff haben und dieses zwischen den Missionen aus- und aufrüsten, mit Geld, das er nach jeder Mission in Abhängigkeit seiner Leistung erhält. Nur so als Idee, damit ihr ne Vorstellung kriegt. Smile

Ein Name, der im verlinkten Forum aufgekommen ist, war "Nullpunkt". Der Titel passt auch zum Setting, das ich mir ausgedacht habe: Anders als in so vielen Space Games wäre der Spieler mal nicht Teil der Glorreichen Flotte XY oder Teil einer Raumübergreifenden Verschwörung; ich dachte da etwa an ein Volk der Menschheit auf einem Generationenschiff. Zur Besiedelung anderer Sternensysteme hat die Erde eine Flotte von Kolonisations- und Forschungsschiffen entsandt, Generationenschiffe. Der Hauptcharakter könnte ein Raumfahrer zweiter oder dritter Generation sein, die erde lange außer Kommunikationsreichweite - eine einsame Flotte auf dem Weg durch die Unendlichkeit des Raums. Mehr dazu hier. Natürlich geht nicht alles glatt, natürlich passiert irgendwas und natürlich sollte sich aus diesem Setting heraus dann noch eine coole Story entfalten, aber so weit bin ich da noch nicht Wink

Und mehr Gedanken sollte ich mir da jetzt wohl auch noch nicht machen, ich stecke noch bis zum Hals in der Engine. Im Moment bastele ich auch ein wenig am Content, z.B. am Standard-Hiteffekt für Waffeneinschläge an der Raumschiffhülle. Werde vermutlich von mir hören lassen, wenns dazu was interessantes gibt Wink

Fetze

BeitragMi, Feb 24, 2010 12:20
Antworten mit Zitat
Benutzer-Profile anzeigen
Arbeite derzeit an BgSpriteLayers, das sind Hintergrund- oder Vordergrundebenen, die (sich bewegende, auf Wunsch beleuchtete, ...) BgSprites enthalten und sich in XY-Richtung unendlich fortsetzen. Später möchte ich noch einbauen, dass man auch einen Radius angeben kann und bei Entfernung vom Mittelpunkt nach und nach Sprites auf unsichtbar geschaltet werden, wenn sie gerade nicht im Blickfeld liegen.

Hier ist das Ergebnis eines kleinen Performancetests:
user posted image

3500 gerenderte Sprites mit Layertechnik (20 Sprites à Layer) bei 60 FPS contra maximal ~800 Sprites ohne Layertechnik.

Natürlich werden BgSpriteLayer die BgSprites nicht ersetzen - ein BgSprite wird immer dann Anwendung finden, wenn es um räumlich festgelegte, einmalig oder seltener auftretende Dekorationen geht: Planeten, extrem unregelmäßig auftretende Hintergrundobjekte sowie alles, was der Mapdesigner später an einer exakten Stelle haben will. BgSpriteLayer sind für Dinge wie Level in Asteroidenfeldern, Raumnebeln o.Ä. gedacht. Im Anwendungsfall werden das niemals so viele Sprites werden, aber ich wollte mal wissen, was meine Optimierungen gebracht haben Wink

Was wahrscheinlich auch auffällt: Im Screenshot wird an BgSprites nichts beleuchtet. Vermutlich wird das auch in der Finalversion in den meisten Fällen nicht anders sein: Im Hintergrund liegenden Objekten wird gerade in Massen ohnehin weniger Beachtung geschenkt, da rentiert sich die teure dynamische Beleuchtung nur noch bedingt. Besondere Objekte wie Planeten o.Ä. werden da natürlich Ausnahmen sein.

ozzi789

BeitragDo, Feb 25, 2010 0:03
Antworten mit Zitat
Benutzer-Profile anzeigen
Hmm das sind einige Sprites und es läuft flott, gefällt mir! Wink
Jedoch find ich die Textur für die (wie heisst das Wort dafür..) Steine die rumfliegen, nicht so ansprechend wie der Rest Very Happy


mfg
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5

Fetze

BeitragDo, Feb 25, 2010 1:52
Antworten mit Zitat
Benutzer-Profile anzeigen
Ist nur ne Test-Textur, da ich momentan definitiv zu wenig Grafiker (== 0) habe, so direkt aus StarTrade entnommen. Natürlich würde ein späteres Asteroidenfeld auf keinen Fall aus einer hohen Anzahl einheitlicher Sprites bestehen sondern aus mehreren, ihrer jeweiligen Tiefe angepassten Lagen: Je weiter hinten, desto größere Asteroidenzahlen werden durch ein einziges Sprite dargestellt und je weiter vorne, desto detaillierter sind die Weltraumsteine. Ich will versuchen, die Zahl gerenderter Sprites so gering wie möglich zu halten.

Ich arbeite gerade contentseitig an einer BgSpriteLayer-Version der StarTrade-Asteroienfelder. Zum einen um das System mal im Anwendungsfall auszutesten und zum anderen, damit mich nicht dauernd nur der blöde langweilig-blaue Sternenhintergrund anstarrt.

Da das Projekt Missionsbasiert ist, d.h. ingame in separate Level zerteilt, wird auch eine größere Vielfalt an Umgebung möglich sein: Im freien Raum mit allen erdenklichen Hintergründen, im Asteroidenfeld, im dichten Raumnebel, in der Atmosphäre eines Planeten, dicht über der Planetenoberfläche, im Warpstrudel, etc.
Für all das werden später die drei Objekte BgSpriteLayer, BgSprite und BgLayer herhalten müssen - dafür sollten sie gerüstet sein.

ozzi789

BeitragDo, Feb 25, 2010 2:41
Antworten mit Zitat
Benutzer-Profile anzeigen
Achso Very Happy
na dann wünsch ich dir viel Glück zur Suche von Grafikern Smile

mfg
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5

Fetze

BeitragDo, Feb 25, 2010 13:49
Antworten mit Zitat
Benutzer-Profile anzeigen
user posted image

Soo, "Asteroidenfeldtest" abgeschlossen: Ein weitaus besserer Asteroidenfeldeffekt (Kommt leider als Standbild nicht ganz so gut rüber wie in Bewegung) mit gerademal rund 100 gerenderten Sprites. Smile

Wenn hier jemand Lust hat, mir grafisch ein wenig unter die Arme zu greifen, gerne. Das Jobangebot steht ja schon irgendwo im Stellenmarkt Smile

Fetze

BeitragFr, Feb 26, 2010 0:51
Antworten mit Zitat
Benutzer-Profile anzeigen
Sounds! Partikel! Effekte! Explosionen!

user posted image

Treffereffekte, Schildeffekte und Explosionen sind drin. Mit den Explosionen bin ich noch nicht 100% zufrieden.. da sie aus überlagerten Partikelanimationen bestehen, fehlt ihnen ein wenig die Dynamik und Trümmer fliegen auch noch nicht durch die Gegend. Trotzdem: Mittlerweile machts echt Spaß.

Fetze

BeitragFr, Feb 26, 2010 11:14
Antworten mit Zitat
Benutzer-Profile anzeigen
Wenn Codedesign gegen "Ich mach das jetzt so" antritt, siegt in meinem Kopf meist das Codedesign. Aber nicht immer ist das auch gut so: Während ich die BgSpriteLayer entwarf, kam mir die glorreiche Idee, die Zeichenfunktionalität eines BgSprites in eine separate Funktion zu kapseln - so hätte ich den Code zum Zeichnen eines BgSprites an einer Stelle konzentriert und würde diese Funktion einfach von BgSprite und BgSpriteLayer aus aufrufen. Gesagt, getan: Es funktionierte wunderbar, aber letztendlich verspielte ich so den großen Vorteil der BgSpriteLayer: Da alle BgSprites auf einem Layer den exakt gleichen Z-Wert haben, muss ich sie beim Zeichnen nicht danach sortieren - ich kann sie stattdessen nach Spritetyp sortieren und alle BgSprites eines Typs singlesurface rendern. Ich nahm also, als mir das klar wurde, die einheitliche Funktion schneller raus, als sie mir in den Sinn gekommen war und fügte den Code wieder in BgSprite und BgSpriteLayer ein. Im BgSpriteLayer nahm ich ihn nun auseinander und optimierte so gut es ging, et voila: Effektive Vervierfachung der SpriteKapazität durch Layer. Manchmal sollte einfach nicht das Codedesign siegen. Codedesign spielt sich nur auf der Programmiererseite ab, vor dem Compiler. Es spielt keine Rolle für das Programm selbst; ich denke, manchmal sollte man seinen Luxus als Programmierer doch lieber zugunsten der Performance aufgeben.

Wie dem auch sei; ich hatte angeboten, hier und da mal ein paar Worte zur Technik hören zu lassen. Zuletzt sagte ich etwas zum Projektaufbau, Tasks und dem ContentProvider. Bleiben wir noch einen Moment im Ladevorgang:

DataProvider
Die Aufgabe des DataProviders ist es, Daten zur Verfügung zu stellen, die kein Content sind, sondern bloß Content beschreiben, d.h. keine Grafiken Sounds, etc. sondern .ini-Dateien, die die Spielregeln festlegen und Content referenzieren. Der DataProvider verwendet zum Laden oder Speichern einer .ini-Datei stets einen eigenen Thread - so wäre es möglich, während eines Levels bequem schonmal den nächsten vorzuladen, um nachzusehen, was denn bald so ansteht. Da alle Daten in Textform abgelegt werden, kann es Tests zufolge mitunter etwas länger dauern, sie zu parsen; daher die Idee.
Grundsätzlich sehen Laden und Speichern so aus: Jedes vom DataProvider verwertbare Objekt (und einige mehr) leiten von der Klasse SteObject ab. Ein SteObject darf selbst nur temporäre, für Spielstände irrelevante, Daten enthalten - alle Spielrelevanten Daten sind in einem SteObjectDesc-Objekt enthalten, welches sich innerhalb des SteObjects befindet. Leite ich ein SteObject ab, muss ich also auch SteObjectDesc in einem zweiten Objekt ableiten und die neue abgeleitete Version ins SteObject packen, anstelle der Standardversion.
Der DataProvider extrahiert beim Speichern also die Description-Objekte aus den zu speichernden Objekten und legt diese rekursiv per Reflection vollautomatisch in den entsprechenden Dateien ab - wenn neue Membervariablen hinzu kommen, muss ich nicht dafür sorgen, dass sie auch gespeichert und geladen werden können, das passiert von alleine. Beim Laden initialisiert er Description-Objekte aus den zu ladenden Dateien und initialisiert mit diesen wiederum dann später die richtigen Objekte.
Die ganzen Scherereien mit den Description-Objekte haben aber noch einen weiteren Sinn: Damit man mittels Reflection einfach alle Membervariablen speichern kann ohne Probleme mit Objektreferenzen zu bekommen, dürfen SteObjectDesc-Objekte keine Objektreferenzen enthalten, sondern ledigliche Datentypen, die sich per Reflection eindeutig zerlegen und abspeichern oder laden lassen: Primitive Datentypen (int, float, Vector2D, string, etc.), Structs, SteObjectDescs (geschachtelt) und Container (Array, List<>, Dictionary<>, ...). Wenn ich nun in einem SteObject eine Objektreferenz habe, dann existiert für diese ein gleichnamiges Feld in der Description, das jedoch einen anderen Datentyp hat: String. Jedes SteObject hat nämlich eine eindeutige String-Id. Bei Speichern lade laden speichere oder lade ich also automatisch nur die Ids referenzierter Objekte. Damit die Id in der Description auch immer synchron ist mit dem Referenzierten Objekt sind entsprechende Variablen nur über Properties erreichbar (Das sind sowas wie spezialisierte get/set-Funktionen) und beim Setzen der Referenz setze ich automatisch auch die Id in der Description um.
Wenn nun ein Spielstand oder die SPielregeln geladen werden (Da alles von SteObject ableitet, macht das hier keinen Unterschied) passiert das in mehreren Phasen:
1. DataProvider parst alle Dateien und beachtet dabei eventuelle Include-Befehle innerhalb dieser. Ergebnis: Ansammlung von Description-Objekten.
2. DataProvider übersetzt Description-Objekte in "richtige" SteObjects.
3. Dabei wird in jedem SteObject die virtuelle Methode "InitFromDesc" aufgerufen und in der gesamten Ableitungshierarchie verwendet, um evtl. vorhandene Content-Referenzen aufzulösen (Grafiken, Sounds, etc.) oder von anderen Objekten unabhängige Initialisierungsarbeit durchzuführen (IdR. nicht nötig, dank injizierter Description)
4. Sind alle Objekte auf diese Weise erstellt worden, wird bei allen "ResolveObjectRefs" aufgerufen, wieder virtuell. In diesem Schritt werden die Objektreferenzen von den Id-Strings in der Description in tatsächliche Referenzen aufgelöst; das geht erst jetzt, da wir erst jetzt sicher sein können, dass alle referenzierten Objekte existieren.
5. Im letzten Schritt - er findet während des ersten Update-Zyklus statt - wird für GameObjects und BgObjects im speziellen Init() aufgerufen. Init ist die einzige dieser Methoden, deren Code davon ausgehen darf, dass alle Objekte initialisiert wurden und aufgelöste Referenzen haben. Hier kann theoretisch abschließende Initialisierungsarbeit vorgenommen werden, welche zuvor aufgrund der Vererbungshierarchie o.Ä. nicht möglich war. Bisher aber kaum verwendet.

So. Klingt alles nach sehr viel Aufwand (Ist es auch Wink ), aber das Ergebnis empfinde ich persönlich als mehr als lohnenswert: Während ich in StarTrade noch 25% der Arbeit darin investieren musste, Werte speichern und laden zu lassen, sind es hier bereits jetzt weniger als 1%, Tendenz fallend: Durch die klare Trennung von Objekten und deren Dateninhalt sowie die Nutzung von Reflection kann sowohl Datenein- als auch Ausgabe vollautomatisch erfolgen. Im Editor den gesamten Regelsatz speichern? Den ganzen Spielstand? Das Spielerobjekt? Einfach die entsprechenden Descriptions einsammeln und Funktion aufrufen. All das wieder laden? Genauso einfach. Neue Membervariablen? Sobald im Code die Variable steht, kann ich sie in der .ini unter ihrem Namen mit Daten füllen. Automatisch gespeicherte Objekte werden auch automatisch übersichtlich gehalten: Variablen, die den Standardwert tragen, werden nicht mitgespeichert, Verschachtelungen werden eingerückt.

Ich hoffe, ihr habt euch jetzt nicht alle gelangweilt. Ich glaube, ich hätte das sehr interessant gefunden Wink

ComNik

BeitragSa, Feb 27, 2010 20:44
Antworten mit Zitat
Benutzer-Profile anzeigen
Wie auch der Eintrag über den Content Provider äußerst interessant!
Mehr! Da ich ja zurzeit auch mitten in der Entwicklung stecke, ist es spannend mal zu sehen wie die "Profis" das so machen Wink. Beim Content Provider oder DataManager (wie er bei mir heisst...) kann ich da noch gewisse Ähnlichkeiten erkennen, aber auf ein ebenso geniales wie komplexes Lade/Speichern System wäre ich nicht gekommen...

lg
ComNik
WIP: Vorx.Engine

Fetze

BeitragSo, Feb 28, 2010 13:18
Antworten mit Zitat
Benutzer-Profile anzeigen
So Leute, gibt was zu testen:
http://www.fetzenet.de/st2_cur..._build.zip

Spielbare erste Version. Klar, auf Dauer wirds eintönig, aber besser als reine Techdemo Very Happy

Anforderungen ans System:
--> Min. .Net Framework 2.0
--> OpenGL 2.1
--> OpenAL

Steuerung:
W/S: Schneller / Langsamer
Schnell doppelt W/S: Maximalgeschw. / Minimalgeschw.
A/D: Strafen links / rechts
Tab: Nachbrenner
T: Ziel anwählen, erleichtert Verfolgung
Maustaste: Waffen abfeuern

Kleiner Tip: Strafen ist enorm nützlich zum Ausweichen oder für ne schnelle Kehrtwendung.

Meinungen erwünscht!

ComNik

BeitragSo, Feb 28, 2010 14:19
Antworten mit Zitat
Benutzer-Profile anzeigen
Klasse Grafik und Effekte, läuft flüssig.
Aber hängt sich nach der (absolout coolen) Explosion meines Schiffes auf Sad

lg
ComNik
WIP: Vorx.Engine

BladeRunner

Moderator

BeitragSo, Feb 28, 2010 14:20
Antworten mit Zitat
Benutzer-Profile anzeigen
dito.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Gehe zu Seite Zurück  1, 2, 3 ... 10, 11, 12 ... 18, 19, 20  Weiter

Neue Antwort erstellen


Übersicht Sonstiges Smalltalk

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group