Gute technologische Lösungen zum Erstellen einer ASCII-Karte und zum Bewegen von Charakteren in einem Browser (wie einer Zwergenfestung)? [geschlossen]

10

Ich möchte eine Webanwendung für meine Spielwebsite erstellen, bei der Textzeichen zur Darstellung von Tieren und Menschen verwendet werden und diese sich auf Kartenfeldern mit unabhängiger (servergesteuerter) KI bewegen.

Also im Wesentlichen eine Zwergenfestungskarte im Browser: Zwergenfestung-Beispiel Mit sich bewegenden Kreaturen, Mobs, NPCs und PCs. Obwohl ich nicht darauf aus bin, diese Skala zu erreichen, würde ich wahrscheinlich jederzeit damit beginnen, ein Viertel dieses Inhalts oder so zu zeigen.

Wahrscheinlich könnten einige der Hintergrund- / unbeweglichen Kacheln statisch geladen werden. Aber für Kreaturen / Tiere und Dinge, die sich bewegen können, bin ich mir nicht sicher, welche Technologielösungen am effektivsten wären.

Ich bin mir bewusst, <canvas>obwohl ich nicht weiß, ob seine Funktionen zu diesem Anwendungsfall passen. Sicherlich wird eine gewisse Menge Javascript notwendig sein.

Gibt es Javascript-Bibliotheken oder Canvas-Bibliotheken, die zu diesem Anwendungsfall passen? Eine andere Technologie, die mir nicht bekannt ist? Kennt jemand Beispiele für Websites, die etwas Ähnliches getan haben, damit ich Ideen daraus ableiten kann?

Kzqai
quelle
1
Werfen Sie einen Blick auf rot.js ondras.github.com/rot.js/hp
Alayric
Nun, rot.js ist vielleicht genau das, wonach ich gesucht habe, wusste es aber nicht.
Kzqai

Antworten:

5

Ich habe tatsächlich eine Zeichenanzeigebibliothek für das Web erstellt, Unicodetiles.js , die ich nicht nur optimiert, sondern auch verschiedene Arten der Darstellung des Textes untersucht habe. Es hat drei Renderer:

  1. DOM, das eine Matrix von <div>Elementen verwendet, um jede Glyphe mit anpassbaren Vordergrund- und Hintergrundfarben zu rendern.
  2. Leinwand, die die Zeichen mit dem <canvas>Element zeichnet . Dies ist viel schneller und es gibt Leistungstests, um dies zu belegen : http://tapiov.net/unicodetiles.js/tests/
  3. WebGL, das ein Canvas-Element zum Erstellen einer Schrifttextur verwendet und dann mit WebGL rendert, das noch schneller und sehr skalierbar auf große Ansichtsfenstergrößen ist, in Browsern jedoch nicht so gut unterstützt wird.

Beachten Sie, dass die verknüpften Leistungstests ziemlich extrem sein können und jedes Zeichen in jedem Frame ändern. In der Praxis ist sogar der DOM-Renderer für die meisten Zwecke schnell genug.

Wenn Sie sich entscheiden, eine eigene Bibliothek zu erstellen, würde ich dennoch die Verwendung von Canvas empfehlen, da diese eine bessere Leistung zu erzielen scheint und größere Szenen zulässt. Die Verwendung von nur WebGL schränkt die Benutzerbasis ein und ist komplex zu implementieren (Unicodetiles verfügt über einen automatischen Fallback-Mechanismus).


Eine andere Bibliothek, die ich habe eine Menge vor kurzem vorgeschlagen , zu hören ist rot.js . Es ist speziell auf Roguelikes ausgerichtet, da es beispielsweise mit einem FOV-System und Dungeon-Generatoren ausgestattet ist. Wenn Sie ein Komplettpaket wünschen, ist dies möglicherweise der richtige Weg.

Tapio
quelle
Nett. Ich kann das benutzen. Oder lerne zumindest aus der Art und Weise, wie es jemand anderes getan hat, um meinen eigenen Ansatz zu informieren, da ich ein Roguelike machen möchte, aber nicht so wie ein Roguelike. : D
Kzqai
@Tapio Ich versuche, Pacman mit Unicodetiles zu implementieren. Das Problem ist, dass der Player immer in der Karte zentriert ist. Für Pacman ist dies unerwünscht. Kann ich es irgendwie deaktivieren oder ohne Angabe des Players umgehen.
user3995789
6

Ich denke, der effektivste Weg wäre, es nur zu fälschen. Rendern auf ein Zielelement mit Ihrer eigenen integrierten Sprite-Schriftart, als würden Sie einen normalen 2D-Bildschirm rendern. Dieser Ansatz stellt sicher, dass keine seltsamen Dinge passieren, wenn Menschen Schriftarten vermissen oder eine ganz andere Sprache verwenden (Chinesisch, Russisch).

Schriftarten und Texte sind eine der schwierigsten Aufgaben, um Pixel in allen Ländereinstellungen in allen Browsern perfekt zu machen. Selbst wenn Sie eine Schriftart einbetten und einige magische CSS-Browser- und Benutzerfreundlichkeitseinstellungen verwenden, können Sie diese überschreiben und ändern. Für normale Websites ist pixelgenauer Text kein Problem, aber in Spielen wie Dwarf Fortress können einige Pixel zu einer extrem inkohärenten Ansicht führen. Selbst wenn Sie keinen Browser, sondern eine normale Anwendung verwenden, treten Probleme beim Rendern von Text auf. Sogar die Zwergenfestung selbst verwendet den von mir beschriebenen Ansatz.

http://en.wikipedia.org/wiki/Dwarf_Fortress

Bildschirmanzeigen verwenden leicht modifizierte Codepage 437-Zeichen in 16 verschiedenen Farben, die als Bitmaps implementiert und mit OpenGL gerendert werden

Edit: weil ich einige Kommentare bekommen habe habe ich die Antwort etwas erweitert

Roy T.
quelle
Sind andere Sprachen keine Erweiterungen, sondern Ersatz von ASCII? Warum fälschen übliche texthaltige Websites es nicht?
Anko
1
Die meisten Zeichencodierungsprobleme können durch Verwendung der UTF-8-Codierung verhindert werden.
Philipp
Russisch hat eine andere Schriftart als ASCII, und Chinesisch ist noch anders. Die übliche Website kümmert sich um die Ästhetik, einschließlich Glyphen mit variabler Größe, Kerning, netter "Textfluss" usw. Ein DF-ähnliches Spiel würde sich um die regelmäßige Platzierung von Buchstaben kümmern, was in einem Webbrowser nicht zuverlässig möglich ist.
Liosan
1
@Liosan sicher kann es. Verwenden Sie einfach die CSS-Deklaration font-family:monospace;und der Webbrowser verwendet die Standardschriftart Monospace.
Philipp
Ich bin mir nicht sicher, wie dies im Vergleich zu einer eingebetteten Web-Schriftart der CSS-Monospace-Familie von Nutzen sein würde. Ich meine, es würde mehr Rendering erfordern, vielleicht würde es ermöglichen, Abstandsprobleme zuverlässiger zu lösen, aber mit einer eingebetteten CSS-Schriftart wäre es egal, ob die Leute die Schriftart vermissen oder eine andere Sprache verwenden? Obwohl ich denke, dass dies die Operationen nur auf den Zeichensatz der eingebetteten Webschrift beschränken würde, hmmm.
Kzqai
3

Um herauszufinden, wie viele Zeilen und Spalten Sie ausgeben müssen, sollten Sie die Fensterbreite und -höhe überprüfen und entsprechend ändern. Denken Sie daran, onResize-Ereignisse anzuhören und die Breite und Höhe entsprechend zu ändern.

Wenn Sie dies auf textuelle Weise tun möchten , können Sie Text mit einer monospaced Schriftart und einer Tabelle verwenden, in der jede Zelle ein Zeichen enthält.

Um einzelne Zeichen zu adressieren, können Sie eine <table>mit der richtigen Anzahl von Zeilen und Spalten erstellen , wobei jede <td>eine ID hat, die aus ihren x- und y-Koordinaten besteht. Auf diese Weise können Sie einzelne Zellen anhand ihrer ID adressieren und ihre innerHTML ändern, um den Buchstaben zu ändern, und ihre CSS-Klasse ändern, um ihre Farbe zu ändern.

Die Verwendung einer Zeichenfläche kann jedoch schneller sein, da Sie nicht für jedes zu ersetzende Zeichen einen großen DOM-Baum bearbeiten müssen. Die Zwergenfestung macht übrigens etwas Ähnliches. Die Zeichen, die zur Darstellung von Objekten verwendet werden, sind Bitmaps und keine echte Textausgabe. Sie werden mithilfe von 2D-Grafik-APIs gezeichnet. Die HTML5-Zeichenfläche ist dafür gut ausgestattet. Es verfügt über die context.fillText- Methode, mit der Sie Text auf die Zeichenfläche zeichnen können. Dies kann verwendet werden, um einzelne Zeichen zu zeichnen. Sie können die Größe und Schriftart ändern, indem Sie die Variablen context.font und die Farbe jedes Buchstabens bearbeiten, indem Sie context.fillStyle aufrufen .

Beachten Sie, dass das hunderte Mal das Aufrufen von fillText pro Frame langsam sein kann, da das Rastern von Schriftarten teuer ist und kein mir bekannter Browser das Caching verwendet. Das heißt, wenn Sie denselben Buchstaben hundertmal mit denselben Einstellungen rendern, wird er hundertmal neu gerastert. Um die Leistung zu steigern, können Sie das gerasterte Erscheinungsbild jedes Buchstabens mit jeder Farbe auf einer versteckten Leinwand zwischenspeichern und diese versteckten Leinwände dann mit context.drawImage zeichnen . Das Kopieren von einer Leinwand auf eine andere ist normalerweise viel schneller als das Rastern von Schriftarten.

Ich entwickle derzeit ein 2D-Spiel mit Leinwand und habe festgestellt, dass der größte FPS-Esser die Schriftzeichnung war. Als ich einen Cache für gerasterten Text hinzufügte, verbesserte sich die Leistung erheblich.

Philipp
quelle
Bitmap-Schriftarten sind auch echte Textausgabe! Ich benutze sie die ganze Zeit in einem Terminal. Wenn eine Zeichenfläche schneller ist, warum basiert das Text-Rendering von StackExchange nicht auf der Zeichenfläche?
Anko
Verdammt, jetzt möchte ich eine Bibliothek dafür schreiben.
Philipp
@ Anko Terminal! = Webbrowser. Auf welche Textwiedergabe beziehen Sie sich genau?
Philipp
1
Ankos Aussage, dass Bitmap-Schriftarten True-Text sind, kann er in seinem Terminal verwenden - und das ist sein Beweis dafür, dass Bitmap-Schriftarten True-Text sind.
Polar
0

OK, das ist nur ein Stich in die Dunkelheit und ich weiß nicht, wie das aussieht.

Grundsätzlich verwenden Sie die gleichen Trickkonsolen (auch bekannt als Terminal), die Sie früher verwendet haben. Zuerst beginnen Sie mit einer Monospace-Schriftart. Sie haben M Zeilen mit N Zeichen. Sie geben den Text einfach in ein Div ein, das breit genug ist (Breite: N em?) Und setzen alle N Zeichen in einen Zeilenumbruch. in diesem Fall a <br/>statt a \n.

Der Trick besteht darin, den Puffer, entweder char durch char oder den gesamten Inhalt auf einmal, durch ein Java-Skript zu ersetzen.

Wenn Sie wirklich spezifisch werden möchten, können Sie das @ font-face verwenden, um sicherzustellen, dass Sie überall dieselbe Monospace-Schriftart haben.

Rioki
quelle
Ich habe auch darüber nachgedacht, aber dann wurde mir klar, dass es keine gute Architektur sein würde, wenn man die Farbe und Hintergrundfarbe jedes einzelnen Charakters steuern möchte.
Philipp
0

Denken Sie in Glyphen. Entkoppeln Sie die Anzeige des Textes von der Bedeutung dahinter. Zum Beispiel:

(Pseudocode)

if (display.hitGlyph)
    glyph = Glyph.Asterisk;

display(glyph);

Und dann tun Sie in Ihrem zugrunde liegenden Code zum Definieren des Glyphenatlas einfach Folgendes:

Glyph.Asterisk = "*";

Der Glyphenatlas kann in der Tat eine Suche in einer ASCII-Tabelle mit verschiedenen Codierungen sein. Hier geht es lediglich darum, zu trennen, wann angezeigt werden soll und was angezeigt werden soll. Ich würde empfehlen, ein Framework von Grund auf neu zu erstellen. Es würde dir mehr Freiheit geben.

Jason Coombes
quelle