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:
- 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.
- 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.
- Ich spawne dann an jeder Position im Array eine transparente 40 x 40 Pixel große "Gitterblock" -Entität
- Mit der von mir verwendeten Engine (ImpactJS) kann ich dann die Entfernung von meiner Lichtquellenentität zu jeder Instanz dieser Gitterblockentität berechnen.
- 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!)
quelle
Antworten:
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:
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.
quelle
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.
Der obige Code hilft Ihnen auch dabei, das Grausame loszuwerden, das
if
else if
Sie 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):
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.
quelle
if else if
Kette loszuwerden .setTile
Erstellen Sie eine Methode, die den Prozentsatz dem Kachelindex zuordnet, und ersetzen Sie alle Zweige durch einen einzigen Aufruf, wie im Beispiel von Byte56.