Datenstrukturen in älteren Spielen

10

Ich bin gespannt auf die Datenstrukturen, die beim Programmieren älterer Spiele wie Super Mario Brothers für NES und Super Mario World für SNES verwendet werden. Mein Verständnis ist, dass Spiele dieser Zeit in der Versammlung geschrieben wurden. Haben die Programmierer Datenstrukturen definiert / verwendet?

Beispiel: Wenn eine Gruppe von Münzen auf dem Bildschirm angezeigt wird, wie werden sie gespeichert? Haben die Programmierer nur Arrays verwendet? Oder hatten sie vielleicht verknüpfte Listen?

Prost!

Edit : Ich interessiere mich für verschiedene Ansätze ... nicht unbedingt einen universellen Ansatz.

Bearbeiten 2 : In einigen meiner Spiele verwende ich einen (möglicherweise schlechten) Ansatz für Sammlungen und möchte wissen, ob eines der älteren Spiele einen ähnlichen Ansatz verwendet. Ich mache gerne folgendes:

// statically allocated arrays (max number of coins is 4)
int coinsXs[4] = {0, 0, 0, 0};
int coinsYs[4] = {0, 0, 0, 0};

// bitset that keeps track of which coins are active
int coinsActive = 0;

// ...

// update the active coins in an update function
for(int i = 0; i < 4; i++){
    if(coinsActive & (1 << i)){
        // update ith coin
    }
 }
MrDatabase
quelle
2
Es gibt keine universelle Antwort; Es kommt darauf an, wie ein bestimmter Programmierer die Lösung für ein bestimmtes Problem implementiert hat.
Ed S.
1
Ich glaube zwar nicht, dass alle diese Spiele in Assembly geschrieben wurden, aber ich werde sagen, dass es für Assembly-Programmierer ziemlich üblich war, ihre kleinen Komponenten für die Wiederverwendung durch Kopieren / Einfügen von Programm zu Programm zu sammeln. Wie oft möchten Sie die Funktion printf () schließlich schreiben? :)
James
Guter Punkt. Ich bin wirklich neugierig auf dynamisch zugewiesene Sammlungen im
Vergleich zu
1
Welches spezifische Problem haben Sie ? Warum interessiert es dich, was alte Spiele tun?
Tetrad
2
Was Sie in Ihrer zweiten Bearbeitung erhalten haben, ist ein Beispiel für ein Layout "Struktur von Arrays", das auch in modernen Spielen üblich bleibt, da es Vorteile für Parallelität und SIMD-Betrieb bietet. Sony hat vor ein paar Jahren eine Präsentation darüber gehalten, wie die traditionelle C ++ - Methode zur Strukturierung von Daten schwerwiegende versteckte Perf-Kosten verursachen kann: research.scee.net/files/presentations/gcapaustralia09/…
Crashworks

Antworten:

13

Selbst in den 16-Bit-Tagen waren Spielekonsolen im Grunde genommen nur kleine, eingebettete Computer, auf denen Echtzeitsoftware ausgeführt wurde, und die Datenstrukturen, die wir verwendeten, sind die gleichen, die Sie überall in der Informatik finden würden: Arrays, Matrizen, Haufen, Bäume. Nicht viele verknüpfte Listen, weil sie so langsam sind (indirekte Suchvorgänge haben eine lange Latenz).

Der Unterschied besteht darin, dass wir vor der STL und bei so kritischer Leistung die Strukturen und Algorithmen normalerweise selbst schreiben mussten!

David Braben hielt 2011 einen lustigen Vortrag in der GDC, in dem er über all die verrückten Tricks sprach, mit denen er Elite 1984 auf ein BBC Micro gebracht hat . Sie können ihn kostenlos im GDC-Tresor ansehen .

Crashworks
quelle
Cool. Haben Sie dynamisch zugewiesene Arrays verwendet? Oder hatten die meisten eine statische Größe? Ich bin neugierig auf Situationen, in denen beispielsweise fünf Münzen auf dem Bildschirm erscheinen und auf dem Bildschirm bleiben, bis der Spieler sie gesammelt hat (oder sie außerhalb des Bildschirms gescrollt haben).
MrDatabase
2
@ MrDatabase - Statische Zuordnungen, wo immer dies möglich ist. In Fällen, wie Sie sie beschreiben, haben wir oft nur eine statisch zugewiesene Anordnung von z. B. 32 möglichen Münzen, die existieren könnten. Wenn Münzen auf die Welt kamen, füllten wir eine Stelle in der Reihe. Wenn sie gingen, würden wir es ausblenden. Die dynamische Zuordnung war nicht nicht verfügbar, wir haben sie nur vermieden, da Sie bei nur 2 MB RAM wirklich sicherstellen müssen, dass Ihr Programm in konstantem Speicher ausgeführt wird!
Crashworks
Cool. Ich mache etwas Ähnliches (siehe Bearbeitung Nr. 2 der Frage). In meiner Update-Funktion überprüfe ich das Bitset "coinActive", if(coinsActive)bevor ich maxNumCoins durchlaufe und aktualisiere. Auf diese Weise vermeide ich die Schleife vollständig, wenn keine Münzen aktiv sind.
MrDatabase
+1 wegen der GDC Vault-Verbindung. Das postmortale Popolous-Gespräch von Peter Molyneux muss das lustigste sein, das ich je gesehen habe.
TravisG
MeDataBase - Sie kopieren das letzte aktive Objekt in den Steckplatz, der von einer Münze belegt wurde, die inaktiv wurde (dh wenn Sie 10 Münzen haben, wird Münze 5 inaktiv, kopieren Sie Münze 10 in Steckplatz 5 und verringern Sie die Anzahl der aktiven Münzen) zu numCoins und aktualisieren Sie alle diese Elemente. Sie würden das "Wenn" nicht brauchen. Dies funktioniert natürlich nur, wenn inaktive Münzen den Status nicht beibehalten müssen und die Reihenfolge der Aktualisierung nicht wichtig ist (der Status kann beibehalten werden, wenn das Array Zeiger auf Münzen und nicht auf tatsächliche Münzen speichert, aber dann ein verstreutes Cache-Verhalten auftritt wahrscheinlich schlimmer als das 'wenn')
Kaj
5

Hier ist eine interessante Diskussion auf GameDev.net für den Super Mario Bros-Quellcode: Super Mario-Quellcode

pek
quelle