Wie die Flamme in Doom auf der Playstation implementiert wurde


Ein ganzes Kapitel meines Game Engine Black Book: DOOM befasst sich mit den DOOM- Konsolenports und den Herausforderungen, denen ihre Entwickler begegnet sind. Sie können lange über den vollständigen Ausfall von 3DO, über die Schwierigkeiten bei Saturn aufgrund der affinen Texturabbildung und über das erstaunliche „Reverse Engineering von Grund auf neu“ sprechen, das Randy Linden für Super Nintendo entwickelt hat.

Die Entwickler des Ports für Playstation 1 (PSX) bewegten sich zunächst in die Richtung, die zum Absturz führte [1] , und konnten anschließend den Kurs ändern und einen Port erstellen, der bei Kritikern und auf dem Markt erfolgreich war. Final DOOM war der erste echte Port, der mit der PC-Version vergleichbar war. Farbsektoren mit Alpha-Blending verbesserten nicht nur die visuelle Qualität, sondern auch das Gameplay, indem sie den Schlüssel der gewünschten Farbe angaben. Dank der Hall-Effekte der Audio Processing Unit der PSX-Konsole wurde der Sound verbessert.

Das Entwicklerteam leistete eine so hochwertige Arbeit, dass es noch einige freie CPU-Zyklen hatte, mit denen es sich entschied, animiertes Feuer im Intro und im Gameplay zu erzeugen. Dies führte mich zu schrecklicher Ehrfurcht, dass ich mich entschied herauszufinden, wie der Effekt realisiert wurde. Als die ersten Suchanfragen keine Antwort gaben, bereitete ich mich darauf vor, ein MIPS-Buch abzuwischen, um die ausführbare Datei zu knacken, aber Samuel Villarreal antwortete Twitter rechtzeitig, dass er die umgekehrte Entwicklung der Version für Nintendo 64 bereits abgeschlossen hatte [2] . Es war genug für mich, es nur ein bisschen aufzuräumen, zu vereinfachen und zu optimieren.

Es war interessant, diesen klassischen Demoszeneneffekt wiederzuentdecken. Die zugrunde liegende Idee ähnelt der ersten Wasserwelle , die in den obligatorischen Programmen vieler Entwickler der 90er Jahre enthalten war. Die Wirkung des Feuers wurde zu einem lebenden Zeugen der Zeit, als die Kombination einer sorgfältig ausgewählten Farbpalette und eines einfachen Tricks der einzige Weg war, um das gewünschte Ergebnis zu erzielen.

Grundidee




Im Kern verwendet der Feuereffekt eine einfache Höhenkarte. Ein Array von der Größe des Bildschirms ist mit 37 Werten im Bereich von 0 bis 36 gefüllt. Jeder Wert ist einer Farbe von Weiß bis Schwarz zugeordnet und erfasst Gelb, Orange und Rot entlang der Straße zwischen ihnen. Die Idee ist, die Temperatur eines Flammenpartikels zu simulieren, das steigt und allmählich abkühlt.


Der Bildpuffer wird vollständig schwarz (mit Nullen gefüllt) mit einer einzelnen weißen Linie weißer Pixel am unteren Rand (36) initialisiert, die die „Quelle“ der Flamme darstellt.


Jedes Mal, wenn der Bildschirm aktualisiert wird, steigt die „Hitze“. Für jedes Pixel im Bildspeicher wird ein neuer Wert berechnet. Jedes Pixel wird unter Berücksichtigung des direkt darunter liegenden Werts aktualisiert. Im Code ist die untere linke Ecke der Nullindex des Arrays und die obere rechte Ecke hat den 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; } 

Beachten Sie, dass Zeile 0 niemals aktualisiert wird (Iteration über y beginnt nicht mit 0, sondern mit 1). Diese mit Null gefüllte Linie ist der "Generator" des Feuers. Eine einfache Version mit linearer Kühlung (- = 1) liefert eine langweilige, gleichmäßige Leistung.


Wir können die FunktionpreadFire () leicht ändern und die Abklingrate der Wärmewerte ändern. Das Hinzufügen von Zufälligkeit passt gut.

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


Das ist schon besser. Um die Illusion zu perfektionieren, kann man nicht nur nach oben, sondern auch nach links und rechts zufällig verteilen.

  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); } 


[Anmerkung Lane: Youtube kneift das Video furchtbar, es ist besser, die Demo auf Javascript im Originalartikel anzusehen oder das GIF unter dem Spoiler zu öffnen.]

GIF-Flammenanimation (23 Megabyte)
Bild

Voila! Beachten Sie, dass durch Ändern des Flammenausbreitungsprozesses auch Wind simuliert werden kann. Ich werde dies als Übung für Leser belassen, die es geschafft haben, den Artikel zu lesen.

Vollständiger Quellcode




Samuels Version sah (logischerweise) eher wie eine Assembler- Version aus . Wenn Sie es sich ansehen möchten, gibt es eine bereinigte und vereinfachte Version.

Referenzen




[1] Quelle: Vollständige Geschichte im Game Engine Black Book: DOOM

[2] Quelle: Twitter-Beitrag vom 25. März 2018.

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


All Articles