Comment la flamme a été implémentée dans Doom sur la Playstation


Un chapitre entier de mon livre noir Game Engine: DOOM traite des ports de console DOOM et des défis rencontrés par leurs développeurs. Vous pouvez parler longtemps de l'échec complet de 3DO, des difficultés de Saturne dues à la cartographie affine des textures et de l'incroyable «reverse engineering from scratch», créé par Randy Linden pour Super Nintendo.

Dans un premier temps, dans la direction de la catastrophe [1] , les développeurs du port pour Playstation 1 (PSX) ont par la suite pu changer de cap et créer un port qui a fait ses preuves auprès des critiques et du marché. Final DOOM était le premier vrai port comparable à la version PC. Les secteurs de couleurs avec mélange alpha ont non seulement amélioré la qualité visuelle, mais aussi amélioré le gameplay en indiquant la clé de la couleur souhaitée. Grâce également aux effets de réverbération de l'unité de traitement audio de la console PSX, le son a été amélioré.

L'équipe de développement a effectué un travail d'une telle qualité qu'elle avait encore quelques cycles CPU gratuits qu'elle a décidé d'utiliser pour générer du feu animé dans l' intro et le gameplay . Cela m'a tellement émerveillé que j'ai décidé de comprendre comment l'effet s'est produit. Lorsque les premières recherches n'ont pas donné de réponse, je me préparais à souffler la poussière d'un livre MIPS pour casser le fichier exécutable, mais Samuel Villarreal a répondu à temps à Twitter qu'il avait déjà terminé le développement inverse de la version pour Nintendo 64 [2] . Il me suffisait juste de nettoyer un peu, de simplifier et d'optimiser.

Il était intéressant de retrouver cet effet démoscène classique; l'idée sous-jacente est similaire à la première ondulation de l'eau , qui était incluse dans l'ensemble obligatoire de programmes de nombreux développeurs des années 90. L'effet du feu est devenu un témoin vivant de l'époque où la combinaison d'une palette de couleurs soigneusement sélectionnée et d'une astuce simple était le seul moyen d'obtenir le résultat souhaité.

Idée de base




À la base, l'effet de feu utilise une simple carte d'élévation. Un tableau de la taille de l'écran est rempli de 37 valeurs comprises entre 0 et 36. Chaque valeur est associée à une couleur allant du blanc au noir et capture le jaune, l'orange et le rouge le long de la route qui les sépare. L'idée est de simuler la température d'une particule de flamme qui monte et se refroidit progressivement.


Le tampon d'image est initialisé complètement en noir (rempli de zéros) avec une seule ligne blanche de pixels blancs en bas (36), qui est la «source» de la flamme.


Chaque fois que l'écran est mis à jour, la «chaleur» augmente. Pour chaque pixel du tampon d'image, une nouvelle valeur est calculée. Chaque pixel est mis à jour en tenant compte de la valeur située juste en dessous. Dans le code, le coin inférieur gauche est l'indice zéro du tableau et le coin supérieur droit a l'index FIRE_HEIGHT * FIRE_WIDTH - 1.

function doFire() { for(x=0 ; x < FIRE_WIDTH; x++) { for (y = 1; y < FIRE_HEIGHT; y++) { spreadFire(y * FIRE_WIDTH + x); } } } function spreadFire(src) { firePixels[src - FIRE_WIDTH] = firePixels[src] - 1; } 

Notez que la ligne 0 n'est jamais mise à jour (l'itération sur y commence non par 0, mais par 1). Cette ligne remplie de zéro est le "générateur" de feu. Une version simple avec refroidissement linéaire (- = 1) nous donne un rendement uniforme ennuyeux.


Nous pouvons légèrement modifier la fonction spreadFire () et modifier le taux de décroissance des valeurs de chaleur. L'ajout de caractère aléatoire est un bon choix.

  function spreadFire(src) { var rand = Math.round(Math.random() * 3.0) & 3; firePixels[src - FIRE_WIDTH ] = pixel - (rand & 1); } 


C’est déjà mieux. Pour parfaire l'illusion, on peut répartir aléatoirement non seulement vers le haut, mais aussi à gauche et à droite.

  function spreadFire(src) { var rand = Math.round(Math.random() * 3.0) & 3; var dst = src - rand + 1; firePixels[dst - FIRE_WIDTH ] = firePixels[src] - (rand & 1); } 


[Remarque voie: Youtube pince terriblement la vidéo, il vaut mieux regarder la démo sur Javascript dans l' article d'origine ou ouvrir le GIF sous le spoiler.]

Animation de flamme GIF (23 mégaoctets)
image

Voila! Notez qu'en modifiant le processus de propagation de la flamme, le vent peut également être simulé. Je vais laisser cela comme un exercice pour les lecteurs qui ont réussi à lire l'article.

Code source complet




La version de Samuel ressemblait (logiquement) à une version assembleur. Si vous voulez le regarder, il existe une version nettoyée et simplifiée.

Les références




[1] Source: Article complet détaillé dans Game Engine Black Book: DOOM

[2] Source: publication Twitter du 25 mars 2018.

Source: https://habr.com/ru/post/fr435122/


All Articles