Zeichnen eines Pseudo-3D-Globus

Sep 06 2020

Ich möchte einen kleinen Globus zeichnen, auf dem die Hauptfigur laufen kann, genau wie Sonic & Knukles Bonus Stage. Für diejenigen, die es nicht googeln, ist hier ein Bild .

Ich bin mit Raycasting vertraut, das in Wolfenstein und anderen Spielen verwendet wird, um eine 3D-Perspektive in einer 2D-Karte zu "simulieren".

Aber ich konnte mir nicht vorstellen, wie ich das Globus-Ding programmieren sollte, und ich nehme an, dass es kein echtes 3D-Rendering war, da Sonic ein 16-Bit-Spiel war.

Irgendeine Idee, wie man es ohne eine ausgefeilte 3D-Engine macht?

Antworten

1 Engineer Sep 06 2020 at 15:22

Überblick

  • Richten Sie eine endlose 1D-Spur mit 2x 2D-Ebenen ein. Während Sie vorwärts rennen, kommt das Flugzeug hinter Ihnen nach vorne, um Sie am Laufen zu halten. Dies geschieht immer wieder, unabhängig davon, ob Sie vorwärts oder rückwärts laufen.
  • Machen Sie jetzt dasselbe in 2D, dh mit 2x2 2D-Ebenen. Wohin Sie auch gehen, die Welt geht unter Ihren Füßen weiter.
  • Transformieren Sie die Ebenen in eine perspektivische Ansicht.
  • Erstellen Sie jetzt einen sphärischen Ausbuchtungseffekt durch Transformation des Bildschirmbereichs, indem Sie alle Grundpixel so anpassen, dass sie gekrümmt erscheinen, obwohl die Oberfläche wirklich flach und sich wiederholend ist.
  • Selbst wenn sich der Charakter über einige Frames um 90 Grad dreht , zeigt dies immer noch den gleichen Effekt der gekrümmten Welt.

3D-Ebenen in 2D

Nehmen wir an, Sie haben 2x2 flache Ebenen, die als Quadrate (von oben nach unten betrachtet) auf Ihrem Bildschirm gerendert werden, und Sie können sich wie oben beschrieben auf ihnen bewegen.

Wir müssen diese Ebenen (kollektiv) von oben nach unten in eine Perspektive von schräg zum Boden verwandeln.

Dies erfolgt in 2 Schritten:

  1. Drücken Sie die kombinierte Grundebene so zusammen, dass ihre obere Hälfte auf die Breite des Ansichtsfensters "drückt" und ihre untere Hälfte die Breite des Ansichtsfensters überschreitet. Dies geschieht yRatiowie im folgenden Codeabschnitt berechnet. Je näher wir an der Spitze sind, desto mehr skalieren wir x, um die Oberseite des Quadrats so einzuklemmen, dass es wie ein Kegelstumpf oder ein Dreieck aussieht.
  2. Skalieren Sie es und positionieren Sie es in y neu, sodass seine Unterseite bündig mit der Unterseite des Ansichtsfensters ist und seine Oberseite (sagen wir) in der Mitte des Bildschirms liegt - dies ist Ihr Horizont.

Beide Schritte hängen davon ab, wo sich der Spieler gerade befindet.

Krümmung

Für die Transformation von Pixeln wird eine Halbkreisformel benötigt, die entlang des Bildschirms y verschoben wird, um den Ausbuchtungseffekt zu erzielen. Dieser Teil bleibt Ihrer Forschung überlassen.

semicircleDisplace(xCurrent)
{
    
    //formula to calculate maximal (horizon) yDisplacement from xCurrent
    //...
    
    return yDisplacement;
}

pixels[xCurrent][yCurrent].y += semicircleDisplace(xCurrent);

Das Problem dabei ist, dass wir alle Pixel am unteren Rand des Bildschirms genauso stark ausbeulen wie am oberen Rand, was zu einer Art verkehrten U-Blick auf das Gelände führt, wenn das, was wir wirklich wollen, am unteren Rand des Bildschirms liegt Bildschirm ist eine fast gerade Linie; auf halbem Weg etwas Verschiebung / Ausbuchtung; und am Horizont maximale Verschiebung. Dies erreichen wir mit einem (möglicherweise linearen) interpolierten Faktor:

semicircleDisplace(xCurrent, yCurrent)
{
    
    //formula to calculate maximal (horizon) yDisplacement from xCurrent
    //...

    //linear interpolation based on where we are between bottom of screen and horizon
    yRange  = yMax - yMin
    yRatio  = yCurrent - yMin
    yFactor = yRatio / yRange

    return yDisplacement * yFactor;

}
pixels[xCurrent][yCurrent].y += semicircleDisplace(xCurrent, yCurrent);

yFactorist ein Wert zwischen 0.0und 1.0mit dem Sie multiplizieren yDisplacement. Wenn die lineare Interpolation (die billig ist) nicht besonders gut aussieht, können Sie mit nichtlinearen Interpolationen spielen, um die richtige Art der Grundkrümmung zu erzielen. Aber meine Vermutung ist linear wird gut aussehen.