Structures de données dans les anciens jeux

10

Je suis curieux de connaître les structures de données utilisées lors de la programmation de jeux plus anciens comme Super Mario Brothers pour NES et Super Mario World pour SNES. Ma compréhension est que les jeux de cette période ont été écrits en assemblage. Les programmeurs ont-ils défini / utilisé des structures de données?

Par exemple: lorsqu'un groupe de pièces apparaît à l'écran, comment sont-elles stockées? Les programmeurs ont-ils simplement utilisé des tableaux? Ou peut-être qu'ils avaient des listes de liens?

À votre santé!

Edit : je m'intéresse à différentes approches ... pas forcément une approche universelle.

Edit 2 : Dans certains de mes jeux, j'utilise une approche (potentiellement mauvaise) envers les collections et je veux savoir si l'un des jeux plus anciens utilisait une approche similaire. J'aime faire ce qui suit:

// 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
la source
2
Il n'y a pas de réponse universelle; cela revient à la façon dont un programmeur donné a implémenté la solution pour un problème donné.
Ed S.19
1
Bien que je ne pense pas que tous ces jeux aient été écrits en assembleur, je dirai qu'il était assez courant que les programmeurs d'assemblage collectent leurs petits composants pour les réutiliser copier / coller d'un programme à l'autre. Combien de fois voudriez-vous écrire la fonction printf () après tout? :)
James
Bon point. Je suis vraiment curieux de connaître les collections allouées dynamiquement par rapport aux collections allouées statiquement
MrDatabase
1
Quel problème spécifique avez - vous ? Pourquoi vous souciez-vous de ce que font les anciens jeux?
Tetrad
2
Ce que vous avez dans votre deuxième édition est un exemple de disposition de "structure de tableaux", qui reste courante même dans les jeux modernes car elle présente des avantages pour le parallélisme et le fonctionnement SIMD. Sony a fait une présentation il y a quelques années sur la façon dont la méthode traditionnelle C ++ de structuration des données peut avoir de sérieux coûts cachés de perf: research.scee.net/files/presentations/gcapaustralia09/…
Crashworks

Réponses:

13

Même à l'époque du 16 bits, les consoles de jeu étaient fondamentalement de petits ordinateurs embarqués exécutant des logiciels en temps réel, et les structures de données que nous avons utilisées sont les mêmes que celles que vous trouverez n'importe où en informatique: tableaux, matrices, tas, arbres. Pas beaucoup de listes chaînées car elles sont si lentes (les recherches indirectes ont une longue latence).

La différence est qu'avant la STL, et avec des performances si critiques, nous devions généralement écrire nous-mêmes les structures et les algorithmes!

David Braben a fait une conférence amusante au GDC 2011 où il a parlé de toutes les astuces folles qu'il a utilisées pour monter Elite sur un BBC Micro en 1984. Vous pouvez le regarder gratuitement au GDC Vault .

Crashworks
la source
Cool. Avez-vous utilisé des tableaux alloués dynamiquement? Ou la plupart avaient-ils une taille statique? Je suis curieux de connaître des situations où, disons, cinq pièces de monnaie apparaîtront à l'écran et resteront à l'écran jusqu'à ce que le joueur les récupère (ou qu'elles défilent hors écran).
MrDatabase
2
@MrDatabase - Allocations statiques dans la mesure du possible. Pour les cas comme vous le décrivez, nous aurions souvent juste un tableau alloué statiquement, par exemple 32 pièces possibles qui pourraient exister. Lorsque des pièces de monnaie arrivaient au monde, nous remplissions une place dans le tableau. Quand ils sont partis, nous l'avons effacé. L'allocation dynamique n'était pas indisponible, nous avons juste évité de l'utiliser car lorsque vous n'avez que 2 Mo de RAM, vous devez vraiment garantir que votre programme s'exécute en mémoire constante!
Crashworks
Cool. Je fais quelque chose de similaire (voir la modification n ° 2 de la question). Dans ma fonction de mise à jour, je vérifie le jeu de bits "coinsActive" if(coinsActive)avant de boucler sur maxNumCoins et de mettre à jour. De cette façon, j'évite complètement la boucle si aucune pièce n'est active.
MrDatabase
+1 en raison de la liaison GDC Vault. Le discours post mortem Popolous de Peter Molyneux doit être le discours le plus hilarant que j'aie jamais vu.
TravisG
MeDataBase - vous copiez le dernier objet actif dans l'emplacement qui était occupé par une pièce qui est devenue inactive (c.-à-d., Si vous avez 10 pièces, la pièce 5 devient inactive, copiez la pièce 10 dans l'emplacement 5 et diminuez les pièces numatives), vous pouvez simplement itérer à numCoins et mettre à jour tous ces éléments. Vous n'auriez pas besoin du «si». Bien sûr, cela ne fonctionne que si les pièces inactives n'ont pas besoin de maintenir l'état et si l'ordre de mise à jour n'est pas important (l'état peut être maintenu si le tableau stocke des pointeurs vers des pièces et non des pièces réelles, mais vous obtenez alors un comportement de cache dispersé qui est probablement pire que le «si»)
Kaj
5

Voici une discussion intéressante sur GameDev.net pour le code source de Super Mario Bros: Code source de Super Mario

pek
la source