¿Buenas soluciones tecnológicas para construir un mapa ascii y personajes en movimiento en un navegador (como una fortaleza enana)? [cerrado]


10

Me gustaría construir una aplicación web para el sitio web de mi juego que implique el uso de caracteres de texto para representar animales y personas, y que se muevan en cuadrados de mapas con IA independiente (impulsada por el servidor).

Esencialmente, un mapa de fortaleza enana en el navegador: ejemplo de fortaleza enana con criaturas en movimiento, mobs, npcs y pcs. Aunque no es que no esté buscando alcanzar esta escala, probablemente comenzaría a mostrar una cuarta parte de este contenido en cualquier momento.

Probablemente algunos de los mosaicos de fondo / inmóviles podrían cargarse estáticamente. Pero para las criaturas / animales y las cosas que pueden moverse, no estoy seguro de qué soluciones tecnológicas serían más efectivas.

Soy consciente de <canvas>que no sé si sus capacidades se ajustan a este caso de uso. Ciertamente, será necesaria cierta cantidad de JavaScript.

¿Existen bibliotecas javascript o bibliotecas de lienzo que se ajusten a este caso de uso? ¿Otra tecnología que no conozco? ¿Alguien sabe de algún ejemplo de sitios web que hayan hecho algo similar a esto, para que yo pueda sacar ideas de ellos?


1
Echa un vistazo a rot.js ondras.github.com/rot.js/hp
Alayric

Bueno, rot.js puede ser exactamente lo que estaba buscando, pero no lo sabía.
Kzqai

Respuestas:


5

De hecho, he creado una biblioteca de visualización de caracteres para la web, Unicodetiles.js , que no solo he dedicado un tiempo a optimizar, sino que también explora diferentes formas de presentar el texto; tiene tres renderizadores:

  1. DOM, que utiliza una matriz de <div>elementos para representar cada glifo con un primer plano personalizable y colores de fondo.
  2. Lienzo, que dibuja los personajes usando el <canvas>elemento. Esto es mucho más rápido, y hay pruebas de rendimiento que lo respaldan: http://tapiov.net/unicodetiles.js/tests/
  3. WebGL, que utiliza un elemento de lienzo para crear una textura de fuente y luego se representa con WebGL, que es aún más rápido y escalable a grandes tamaños de ventana gráfica, pero no es tan compatible con los navegadores.

Tenga en cuenta que las pruebas de rendimiento vinculadas pueden ser bastante extremas, cambiando cada personaje en cada cuadro. En la práctica, incluso el procesador DOM es lo suficientemente rápido para la mayoría de los propósitos.

Si decides hacer tu propia biblioteca, aún te recomiendo usar el lienzo porque parece funcionar mejor, permitiendo escenas más grandes. El uso de solo WebGL limitará la base de usuarios y su implementación es compleja (Unicodetiles tiene un mecanismo de respaldo automático).


Otra biblioteca, que he oído sugerí mucho recientemente es rot.js . Está específicamente dirigido a roguelikes, ya que viene con, por ejemplo, sistema FOV y generadores de mazmorras. Si desea un paquete completo, este podría ser el camino a seguir.


Agradable. Puedo usar eso. O al menos aprender de la forma en que alguien más lo hizo para informar mi propio enfoque, ya que quiero hacer un roguelike, pero no como un roguelike. : D
Kzqai

@Tapio Estoy tratando de implementar pacman con unicodetiles, el problema es que el jugador siempre está centrado en el mapa, no es deseable para pacman, ¿puedo desactivarlo de alguna manera o puedo moverme sin especificar el jugador?
user3995789

6

Creo que la forma más efectiva sería fingirlo. Renderizando a algún elemento objetivo usando su propia fuente de sprite incorporada como si estuviera renderizando una pantalla 2D normal. Este enfoque garantiza que no ocurran cosas extrañas cuando a las personas les faltan fuentes o utilizan un idioma muy diferente (chino, ruso).

Las fuentes y los textos son una de las cosas más difíciles de conseguir píxeles perfectos en todas las configuraciones regionales en todos los navegadores. Incluso al incrustar una fuente y usar un navegador mágico CSS, la configuración de usabilidad puede anularla y alterarla. Para los sitios web normales, el texto con píxeles perfectos no es un problema, pero en juegos como Dwarf Fortress unos pocos píxeles pueden conducir a una vista extremadamente incoherente. Incluso cuando no se utiliza un navegador, sino una aplicación normal, existen problemas con la representación de texto. Entonces, incluso Dwarf Fortress usa el enfoque que describí.

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

Las visualizaciones en pantalla utilizan la página de códigos ligeramente modificada 437 caracteres en 16 colores diferentes implementados como mapas de bits, renderizados con OpenGL

Editar: porque recibí algunos comentarios, extendí un poco la respuesta


¿No son otros lenguajes extensiones en lugar de reemplazos de ASCII? ¿Por qué los sitios web habituales que contienen texto "lo falsifican"?
Anko

1
La mayoría de los problemas de codificación de caracteres se pueden evitar mediante la codificación UTF-8.
Philipp

El ruso tiene una fuente diferente que el ASCII, y el chino es aún más diferente. El sitio web habitual se preocupa por la estética, que incluye cosas como glifos de tamaño variable, interletraje, buen "flujo" de texto, etc.
Liosan

1
@Liosan seguro que puede. Simplemente use la declaración CSS font-family:monospace;y el navegador web usará la fuente monoespacio predeterminada.
Philipp

No estoy realmente seguro de cómo esto sería beneficioso frente a una fuente web css monospace-family incrustada? Quiero decir, se necesitaría más renderizado, ¿tal vez podría permitir que los problemas de espacio se resuelvan de manera más confiable, pero con una fuente css incrustada no importaría si a las personas les falta la fuente o usan un idioma diferente? Aunque supongo que eso restringiría las operaciones solo al conjunto de caracteres de la fuente web incorporada, hmmm.
Kzqai

3

Para averiguar el número de líneas y columnas que necesita generar, debe verificar el ancho y alto de la ventana y cambiarlo en consecuencia. Recuerde escuchar los eventos onResize y modificar el ancho y la altura en consecuencia.

Cuando desee hacer esto de forma textual , puede hacerlo utilizando texto con una fuente monoespaciada y una tabla donde cada celda contenga un carácter.

Para abordar caracteres individuales, puede crear un <table>con el número correcto de filas y columnas, donde cada uno <td>tiene una ID que consiste en sus coordenadas x e y. De esa manera, puede direccionar celdas individuales por ID y cambiar su innerHTML para cambiar la letra y cambiar su clase css para cambiar su color.

Sin embargo, el uso de un lienzo puede ser más rápido porque no tiene que manipular un árbol DOM grande para cada personaje que tiene que reemplazar. La Fortaleza Enana está haciendo algo similar, por cierto. Los caracteres que se utilizan para representar objetos son en realidad mapas de bits, no salida de texto verdadero, y se dibujan con API gráficas 2D. El lienzo HTML5 está bien equipado para esto. Tiene el método context.fillText que le permite dibujar texto en el lienzo. Esto se puede usar para dibujar personajes individuales. Puede cambiar el tamaño y la cara de la fuente manipulando las variables context.font y el color de cada letra llamando a context.fillStyle .

Tenga en cuenta que llamar a fillText cientos de veces por fotograma podría ser lento, porque rasterizar las fuentes es costoso y ningún navegador que conozca utiliza el almacenamiento en caché. Eso significa que cuando representa la misma letra con la misma configuración cien veces, se volverá a rasterizar cien veces. Para aumentar el rendimiento, puede almacenar en caché la apariencia rasterizada de cada letra con cada color en un lienzo oculto y luego dibujar estos lienzos ocultos usando context.drawImage . Copiar de un lienzo a otro suele ser mucho más rápido que la rasterización de fuentes.

Actualmente estoy desarrollando un juego en 2D con lienzo, y noté que el mayor comedor de FPS era el dibujo de la fuente. Cuando agregué un caché para texto rasterizado, mejoró mucho el rendimiento.


¡Las fuentes de mapa de bits también son verdaderas salidas de texto! Los uso en una terminal todo el tiempo. Además, si un lienzo es más rápido, ¿por qué el texto de StackExchange no se basa en el lienzo?
Anko

maldición, ahora quiero escribir una biblioteca para eso.
Philipp

@Anko terminal! = Navegador web. ¿A qué representación de texto te refieres exactamente?
Philipp

1
Anko dice que como las fuentes de mapa de bits son texto verdadero, puede usarlas en su terminal, y esa es su prueba de que las fuentes de mapa de bits son texto verdadero.
Polar

0

OK, esto es solo una puñalada en la oscuridad y no sé cómo se presenta.

Básicamente usas las mismas consolas de trucos (también conocido como terminal) que solían hacer en los viejos tiempos. Primero comienzas con una fuente monoespacial. Tienes M líneas con N caracteres. Entonces, simplemente volcar el texto en un div que sea lo suficientemente ancho (ancho: ¿N em?) Y poner a cada N caracteres un salto de línea; en este caso a en <br/>lugar de a \n.

El truco es reemplazar el búfer, ya sea char por char o todo el contenido a la vez con script java.

Si quieres ser realmente específico, puedes usar @ font-face para asegurarte de tener la misma fuente monoespacio en todas partes.


También pensé en hacer eso, pero luego me di cuenta de que no sería una buena arquitectura cuando se desea controlar el color y el color de fondo de cada personaje individual.
Philipp

0

Piensa en términos de glifos. Desacoplar la visualización del texto del significado detrás de él. Por ejemplo:

(pseudocódigo)

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

display(glyph);

Y luego, en su código subyacente para definir el atlas de glifos, simplemente haga algo como:

Glyph.Asterisk = "*";

De hecho, el atlas de glifos puede ser una búsqueda en una tabla ASCII con varias codificaciones. El punto aquí es simplemente separar cuándo mostrar, con lo que se debe mostrar. Recomendaría hacer un marco desde cero. Te daría más libertad.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.