Erstellen von reibungslosen Lichtübergängen mithilfe von Kacheln im HTML5 / JavaScript-Spiel


7

Ich versuche, einen Lichteffekt in einem HTML5 / JavaScript-Spiel mithilfe des Kachelersatzes zu implementieren. Was ich jetzt habe, ist eine Art Arbeit, aber die Übergänge sehen nicht glatt / natürlich genug aus, wenn sich die Lichtquelle bewegt. Hier bin ich jetzt:

  1. Im Moment habe ich eine Hintergrundkarte, auf die ein PNG-Kachelblatt mit Licht- / Schattenspektrum angewendet wurde - von der dunkelsten Kachel zur vollständig transparenten. Standardmäßig wird die dunkelste Kachel beim Start über das gesamte Level gezogen und deckt alle anderen Ebenen usw. ab.
  2. Ich verwende meine vorgegebenen Kachelgrößen (40 x 40 Pixel), um die Position jeder Kachel zu berechnen und ihre x- und y-Koordinaten in einem Array zu speichern.
  3. Ich spawne dann an jeder Position im Array eine transparente 40 x 40 Pixel große "Gitterblock" -Entität
  4. Mit der von mir verwendeten Engine (ImpactJS) kann ich dann die Entfernung von meiner Lichtquellenentität zu jeder Instanz dieser Gitterblockentität berechnen.
  5. Ich kann dann die Kachel unter jeder dieser Gitterblockkacheln durch eine Kachel mit der entsprechenden Transparenz ersetzen.

Derzeit führe ich die Berechnung wie folgt in jeder Instanz der Rasterblockentität durch, die auf der Karte erzeugt wird:

var dist = this.distanceTo( ig.game.player );
var percentage = 100 * dist / 960;

if (percentage < 2) {
    // Spawns tile 64 of the shadow spectrum tilesheet at the specified position
    ig.game.backgroundMaps[2].setTile( this.pos.x, this.pos.y, 64 ); 
}       
else if (percentage < 4) {
    ig.game.backgroundMaps[2].setTile( this.pos.x, this.pos.y, 63 );
}
else if (percentage < 6) {
    ig.game.backgroundMaps[2].setTile( this.pos.x, this.pos.y, 62 );
}       
// etc...

Das Problem ist, dass, wie gesagt, diese Art der Berechnung die Lichtquelle nicht sehr natürlich aussehen lässt. Das Wechseln von Kacheln sieht zu scharf aus, während sie im Idealfall mithilfe des Spektrum-Kachelblatts reibungslos ein- und ausgeblendet werden (ich habe das Kachelblatt aus einem anderen Spiel kopiert, das dies schafft, daher weiß ich, dass es kein Problem mit den Kachelschattierungen ist. Ich bin mir nur nicht sicher wie das andere Spiel es macht). Ich denke, dass meine Methode, Prozentsätze zum Austauschen von Kacheln zu verwenden, möglicherweise durch ein besseres / dynamischeres Proximity-Forum ersetzt werden könnte, das reibungslosere Übergänge ermöglicht. Könnte jemand Ideen haben, was ich tun kann, um die Grafik hier zu verbessern, oder eine bessere Methode, um die Nähe zu den Informationen zu berechnen, die ich über jede Kachel sammle?

(PS: Ich reposte dies von Stack Overflow auf Vorschlag von jemandem, entschuldige das Duplikat!)


1
Können Sie Screenshots von dem posten, was Sie haben und was Sie haben möchten?
MichaelHouse

Klar, ich werde heute Abend einen Screenshot posten.
Spectralbat

1
Sie haben vergessen, einen Screenshot hinzuzufügen ...
MichaelHouse

Antworten:


5

Zunächst einmal tut es mir leid, dass ich Ihnen bei Ihrer spezifischen Plattform nicht helfen kann, da ich diese Art von Arbeit in HTML5 noch nie ausgeführt habe. Also werde ich versuchen, dies sprachunabhängig anzugehen.

Ich glaube nicht , Sie in der Lage sein werden glatte Übergänge zu erhalten , wenn Sie auf einem Licht sind die Berechnung Fliese pro Fliese Basis . Dies ist analog zu den Unterschieden zwischen der Verwendung von Flat Shading, Gouraud Shading oder Phong Shading:

Geben Sie hier die Bildbeschreibung ein

Was Sie tun, ähnelt einer flachen Schattierung, dh Sie weisen ein anderes Licht pro Kachel zu, was zu scharfen Übergängen zwischen den Kacheln führt, wie im obigen Bild gezeigt.

Um bessere Ergebnisse zu erzielen, müssen Sie Ihre Lichter pro Scheitelpunkt (dh Gouraud) berechnen. Ich weiß nicht, was die Fähigkeiten Ihres Motors sind, aber der Idealfall wäre, wenn jede Ihrer Kacheln ein Quad wäre und Sie direkten Zugriff auf ihre Eckpunkte hätten. Dann können Sie für jeden Scheitelpunkt den Abstand zum Licht berechnen und Ihre Schattenfarbe direkt im Scheitelpunkt speichern. Schließlich würde die Rendering-Pipeline automatisch dafür sorgen, dass die Schattierungen über die Fliesenoberflächen interpoliert werden, was zu einem glatteren Aussehen führt (auch bekannt als Gouraud-Schattierung ).

Für noch bessere Ergebnisse, wenn auch etwas teurer, können Sie das Licht pro Pixel (dh Phong) im Fragment-Shader berechnen . Der grundlegende Ansatz funktioniert gut, wenn Sie nur ein paar Lichter zum Abtasten haben, wie es aus Ihrem Beispiel hervorgeht.

Eine andere Alternative, die sehr gut funktionieren könnte, besteht darin, alle Ihre Lichter (und nur Ihre Lichter) zuerst in ein separates Renderziel zu rendern, optional das Ergebnis zu verwischen und es am Ende mit dem Rest der Szene zu mischen. Überprüfen Sie diese Frage für ein paar Ideen dazu.


Die letzte Alternative scheint gut zu HTML5 Canvas zu passen. Ihre anderen sind Canvas nicht ausgesetzt, es sei denn, ImpactJS implementiert speziell Shader und Vertices, was ich sehr bezweifle.
DMan

@DMan Sie haben Recht, wenn es Canvas-basiert ist, werden diese Änderungen wahrscheinlich nicht unterstützt. Ich dachte, es könnte sich um eine WebGL-Engine handeln. In diesem Fall wäre es einfach.
David Gouveia

Vielen Dank für Ihre ausführliche Antwort. Ich werde heute Abend Ihren letzten Vorschlag zusammen mit einigen anderen Ideen untersuchen, die ich versuche.
Spectralbat

4

Sie scheinen mit einer linearen Dämpfung zu leuchten (Ihre Lichtintensität fällt linear ab). Möglicherweise möchten Sie versuchen, das inverse Quadratgesetz zu verwenden . Oder ein einfacher exponentieller Abfall.

float maxLightDistance = 64;
float fallOff = 1.4f;
float intensity = Math.pow(distanceFromSource / maxLightDistance, fallOff);
int tileToUse = (int)intensity;
ig.game.backgroundMaps[2].setTile( this.pos.x, this.pos.y, tileToUse);

Der obige Code hilft Ihnen auch dabei, das Grausame loszuwerden, das if else ifSie haben.

Ich verwende nur einen einfachen exponentiellen Abfall und erhalte solche Ergebnisse (ich kann später ein besseres Bild einer einzelnen Lichtquelle veröffentlichen, ich habe momentan nur keine):

Licht von Lava

Ich sollte auch erwähnen, dass ein Programm wie Excel für solche Dinge großartig ist. Sie können Formeländerungen ziemlich schnell testen und entweder grafisch darstellen oder bedingte Regeln zum Ändern der Farbe einer Zelle verwenden.


Ich möchte darauf hinweisen, dass durch Ändern der Dämpfungsformel das Licht nicht reibungslos über die Oberfläche der Fliesen interpoliert wird. Jede Kachel hat immer noch eine einzelne Farbe, die sich beim Erreichen der nächsten Kachel plötzlich ändert. Die Verwendung sehr kleiner Helligkeitsschwankungen kann helfen, das Problem zu verbergen und es gut aussehen zu lassen, aber es ist immer noch kein reibungsloser Übergang. Ich argumentiere auch, dass die Wahl der Dämpfung viel mit der Ästhetik zu tun hat, da ich Projekte hatte, bei denen ich das Aussehen einer linearen Dämpfung (mit maximalem und minimalem Wirkungsradius) dem umgekehrten Quadratgesetz vorgezogen habe.
David Gouveia

Mein Vorschlag basiert auf dem, was das OP bereits hat. Es soll eine einfache Lösung sein, ohne das Rendering-System neu erstellen zu müssen. Und es kann einen Unterschied machen, wenn die OP-Methode Kacheln nebeneinander platziert, die mehr als einen Farbtonunterschied aufweisen.
MichaelHouse

@spectralbat Aber ich bin definitiv damit einverstanden, diese if else ifKette loszuwerden . setTileErstellen Sie eine Methode, die den Prozentsatz dem Kachelindex zuordnet, und ersetzen Sie alle Zweige durch einen einzigen Aufruf, wie im Beispiel von Byte56.
David Gouveia

Sicher, es ist gut, dass Sie darauf hingewiesen haben, besonders wenn man bedenkt, wie einfach eine Änderung ist. Es könnte besser aussehen als das, was das OP derzeit hat. :) Ich möchte nur darauf hinweisen, dass ich nicht denke, dass es etwas mit dem eigentlichen Problem der reibungslosen Übergänge zwischen Kacheln zu tun hat . Aber vielleicht hat das OP genau darum gebeten, und ich war derjenige, der das falsch verstanden hat. ;-)
David Gouveia

Vielen Dank! Auch wenn dies mein ursprüngliches Problem nicht löst, werde ich alles versuchen, damit es besser aussieht. Ich werde diese und einige andere Optionen angeben, die ich heute Abend ausprobiert habe.
Spectralbat
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.