Escribir un motor de aventuras de texto multijugador en Node.js (Parte 1)

 

 

 

  • Implemente rápidamente. Implementar inteligentemente
  • Patrones de diseño de interfaces inteligentes, vídeo de 10h + formación UX

  • Índice
    1. Nuestra meta
    2. Fase de diseño
      1. El motor
      2. El servidor de chat
      3. El cliente
      4. El juego: archivos JSON

    ¿Has oído hablar alguna vez de una aventura de texto? En esta serie de artículos, Fernando Doglio explica el proceso de cómo crear un motor completo que sea capaz de permitirte jugar cualquier aventura de texto que tú y tus amigos disfruten. Así es, ¡le daremos un poco de sabor agregando el modo multijugador al género de aventuras de texto!

     

    Las aventuras de texto fueron una de las primeras formas de juegos de rol digitales que existieron, cuando los juegos no tenían gráficos y todo lo que tenías era tu propia imaginación y la descripción que leías en la pantalla negra de tu monitor CRT.

    Si queremos ponernos nostálgicos, quizá el nombre Colossal Cave Adventure (o simplemente Aventura, como se llamaba originalmente) nos suene. Ese fue el primer juego de aventuras de texto jamás creado.

    Una imagen de una aventura de texto real de antaño. ( Vista previa grande )

    La imagen de arriba es cómo verías realmente el juego, muy lejos de nuestros mejores juegos de aventuras AAA actuales. Dicho esto, era divertido jugarlos y te robaban cientos de horas de tu tiempo, mientras te sentabas frente a ese texto, solo, tratando de descubrir cómo superarlo.

    Es comprensible que las aventuras de texto hayan sido reemplazadas a lo largo de los años por juegos que presentan mejores imágenes (aunque se podría argumentar que muchos de ellos han sacrificado la historia por los gráficos) y, especialmente en los últimos años, la creciente capacidad de colaborar con otros. amigos y jugar juntos. Esta característica particular es una que carecían las aventuras de texto originales y que quiero recuperar en este artículo.

    Otras partes de esta serie

    • Parte 2 : Diseño del servidor Game Engine
    • Parte 3 : Creación del cliente terminal
    • Parte 4 : Agregar chat a nuestro juego

    Nuestra meta

    El objetivo de este esfuerzo, como probablemente ya habrás adivinado por el título de este artículo, es crear un motor de aventuras de texto que te permita compartir la aventura con amigos, permitiéndote colaborar con ellos de manera similar a como lo harías durante un juego de Dungeons Dragons (en el que, al igual que en las buenas aventuras de texto, no hay gráficos para mirar).

    Crear el motor, el servidor de chat y el cliente requiere bastante trabajo. En este artículo, te mostraré la fase de diseño, explicando cosas como la arquitectura detrás del motor, cómo interactuará el cliente con los servidores y cuáles serán las reglas de este juego.

    Sólo para brindarles una ayuda visual de cómo se verá esto, este es mi objetivo:

    Estructura alámbrica general para la interfaz de usuario final del cliente del juego ( vista previa grande )

    Ese es nuestro objetivo. Una vez que lleguemos allí, tendrás capturas de pantalla en lugar de maquetas rápidas y sucias. Entonces, comencemos con el proceso. Lo primero que cubriremos es el diseño de todo. Luego, cubriremos las herramientas más relevantes que usaré para codificar esto. Finalmente, te mostraré algunos de los fragmentos de código más relevantes (con un enlace al repositorio completo, por supuesto).

    ¡Con suerte, al final te encontrarás creando nuevas aventuras de texto para probarlas con amigos!

    Fase de diseño

    Para la fase de diseño, cubriré nuestro plano general. Haré todo lo posible para no aburrirte hasta la muerte, pero al mismo tiempo, creo que es importante mostrar algunas de las cosas detrás de escena que deben suceder antes de establecer la primera línea de código.

    Los cuatro componentes que quiero cubrir aquí con bastante detalle son:

    • El motor
      Este será el servidor principal del juego. Las reglas del juego se implementarán aquí y proporcionarán una interfaz tecnológicamente independiente para que la consuma cualquier tipo de cliente. Implementaremos un cliente de terminal, pero usted podría hacer lo mismo con un cliente de navegador web o cualquier otro tipo que desee.
    • El servidor de chat
      Debido a que es lo suficientemente complejo como para tener su propio artículo, este servicio también tendrá su propio módulo. El servidor de chat se encargará de permitir que los jugadores se comuniquen entre sí durante el juego.
    • El cliente
      Como se indicó anteriormente, este será un cliente terminal, uno que, idealmente, se verá similar a la maqueta anterior. Hará uso de los servicios proporcionados tanto por el motor como por el servidor de chat.
    • Juegos (archivos JSON)
      Finalmente, repasaré la definición de los juegos reales. El objetivo de esto es crear un motor que pueda ejecutar cualquier juego, siempre que el archivo del juego cumpla con los requisitos del motor. Entonces, aunque esto no requerirá codificación, explicaré cómo estructuraré los archivos de aventuras para poder escribir nuestras propias aventuras en el futuro.

    El motor

    El motor del juego, o servidor del juego, será una API REST y proporcionará toda la funcionalidad requerida.

    Opté por una API REST simplemente porque, para este tipo de juego, el retraso agregado por HTTP y su naturaleza asincrónica no causarán ningún problema. Sin embargo, tendremos que tomar una ruta diferente para el servidor de chat. Pero antes de comenzar a definir puntos finales para nuestra API, debemos definir de qué será capaz el motor. Vamos a por ello.

     

    Característica Descripción
    Únete a un juego Un jugador podrá unirse a un juego especificando el ID del juego.
    Crea un nuevo juego Un jugador también puede crear una nueva instancia de juego. El motor debe devolver una identificación para que otros puedan usarla para unirse.
    escena de regreso Esta característica debería devolver la escena actual donde se encuentra la fiesta. Básicamente, devolverá la descripción, con toda la información asociada (posibles acciones, objetos que contiene, etc.).
    Interactuar con la escena Este será uno de los más complejos, porque tomará un comando del cliente y realizará esa acción: cosas como mover, empujar, tomar, mirar, leer, por nombrar solo algunas.
    comprobar inventario Aunque esta es una forma de interactuar con el juego, no se relaciona directamente con la escena. Por lo tanto, consultar el inventario de cada jugador se considerará una acción diferente.

    Unas palabras sobre el movimiento

    Necesitamos una forma de medir distancias en el juego porque moverse a través de la aventura es una de las acciones principales que puede realizar un jugador. Usaremos este número como medida de tiempo, solo para simplificar el juego. Medir el tiempo con un reloj real puede no ser lo mejor, considerando que este tipo de juegos tienen acciones por turnos, como el combate. En su lugar, usaremos la distancia para medir el tiempo (lo que significa que una distancia de 8 requerirá más tiempo para recorrerla que una de 2, lo que nos permitirá hacer cosas como agregar efectos a los jugadores que duren una cantidad determinada de "puntos de distancia" ).

    Otro aspecto importante a considerar sobre el movimiento es que no estamos jugando solos. En aras de la simplicidad, el motor no permitirá que los jugadores dividan el grupo (aunque eso podría ser una mejora interesante para el futuro). La versión inicial de este módulo solo permitirá que todos se muevan hacia donde decida la mayoría del partido. Por lo tanto, el movimiento tendrá que realizarse por consenso, lo que significa que cada movimiento esperará a que la mayoría del partido lo solicite antes de llevarse a cabo.

    Combate

    El combate es otro aspecto muy importante de este tipo de juegos, y que tendremos que considerar agregar a nuestro motor; de lo contrario, acabaremos perdiéndonos parte de la diversión.

    Para ser honesto, esto no es algo que deba reinventarse. El combate en grupo por turnos existe desde hace décadas, por lo que simplemente implementaremos una versión de esa mecánica. Lo mezclaremos con el concepto de “iniciativa” de Dungeons Dragons, obteniendo un número aleatorio para mantener el combate un poco más dinámico.

    En otras palabras, el orden en el que todos los involucrados en una pelea podrán elegir su acción será aleatorio, y eso incluye a los enemigos.

     

    Finalmente (aunque hablaré de esto con más detalle a continuación), tendrás elementos que podrás recoger con un número de “daño” establecido. Estos son los elementos que podrás utilizar durante el combate; cualquier cosa que no tenga esa propiedad causará 0 daño a tus enemigos. Probablemente agregaremos un mensaje cuando intentes usar esos objetos para luchar, para que sepas que lo que intentas hacer no tiene sentido.

    Interacción cliente-servidor

    Veamos ahora cómo un cliente determinado interactuaría con nuestro servidor usando la funcionalidad previamente definida (aún no pensamos en los puntos finales, pero llegaremos allí en un segundo):

    ( Vista previa grande )

    La interacción inicial entre el cliente y el servidor (desde el punto de vista del servidor) es el comienzo de un nuevo juego, y los pasos para ello son los siguientes:

    1. Crea un nuevo juego .
      El cliente solicita la creación de un nuevo juego al servidor.
    2. Crear sala de chat .
      Aunque el nombre no lo especifica, el servidor no solo crea una sala de chat en el servidor de chat, sino que también configura todo lo necesario para permitir que un grupo de jugadores juegue una aventura.
    3. Devolver los metadatos del juego .
      Una vez que el servidor haya creado el juego y la sala de chat esté habilitada para los jugadores, el cliente necesitará esa información para solicitudes posteriores. En su mayoría, será un conjunto de ID que los clientes pueden usar para identificarse a sí mismos y al juego actual al que desean unirse (más sobre esto en un segundo).
    4. Compartir manualmente el ID del juego .
      Este paso lo tendrán que realizar los propios jugadores. Podríamos idear algún tipo de mecanismo para compartir, pero lo dejaré en la lista de deseos para futuras mejoras.
    5. Unirse al juego .
      Éste es bastante sencillo. Una vez que todos tengan el ID del juego, se unirán a la aventura utilizando sus aplicaciones cliente.
    6. Únase a su sala de chat .
      Finalmente, las aplicaciones cliente de los jugadores utilizarán los metadatos del juego para unirse a la sala de chat de su aventura. Este es el último paso requerido antes del juego. Una vez hecho todo esto, ¡los jugadores estarán listos para comenzar la aventura!

    Orden de acción para un juego existente ( vista previa grande )

    Una vez que se hayan cumplido todos los requisitos previos, los jugadores pueden comenzar a jugar la aventura, compartir sus pensamientos a través del chat grupal y avanzar en la historia. El diagrama de arriba muestra los cuatro pasos necesarios para ello.

    Los siguientes pasos se ejecutarán como parte del ciclo del juego, lo que significa que se repetirán constantemente hasta que finalice el juego.

    1. Solicitar escena .
      La aplicación cliente solicitará los metadatos de la escena actual. Este es el primer paso en cada iteración del ciclo.
    2. Devuelve los metadatos .
      El servidor, a su vez, enviará los metadatos de la escena actual. Esta información incluirá cosas como una descripción general, los objetos que se encuentran en su interior y cómo se relacionan entre sí.
    3. Enviar comando .
      Aquí es donde comienza la diversión. Esta es la principal aportación del jugador. Contendrá la acción que quieren realizar y, opcionalmente, el objetivo de esa acción (por ejemplo, soplar una vela, agarrar una piedra, etc.).
    4. Devuelve la reacción al comando enviado .
      Este podría ser simplemente el paso dos, pero para mayor claridad, lo agregué como un paso adicional. La principal diferencia es que el paso dos podría considerarse el comienzo de este bucle, mientras que este tiene en cuenta que ya estás jugando y, por lo tanto, el servidor necesita entender a quién afectará esta acción (ya sea a un solo jugador o todos los jugadores).

    Como paso adicional, aunque en realidad no forma parte del flujo, el servidor notificará a los clientes sobre las actualizaciones de estado que sean relevantes para ellos.

     

    El motivo de este paso adicional recurrente se debe a las actualizaciones que un jugador puede recibir de las acciones de otros jugadores. Recordar la exigencia de trasladarse de un lugar a otro; Como dije antes, una vez que la mayoría de los jugadores hayan elegido una dirección, todos los jugadores se moverán (no se requiere la participación de todos los jugadores).

    Lo interesante aquí es que HTTP (ya hemos mencionado que el servidor será una API REST) ​​no permite este tipo de comportamiento. Entonces, nuestras opciones son:

    1. realizar un sondeo cada X cantidad de segundos desde el cliente,
    2. utilice algún tipo de sistema de notificación que funcione en paralelo con la conexión cliente-servidor.

    En mi experiencia, tiendo a preferir la opción 2. De hecho, usaría (y usaré en este artículo) Redis para este tipo de comportamiento.

    El siguiente diagrama demuestra las dependencias entre servicios.

    Interacciones entre una aplicación cliente y el motor del juego ( vista previa grande )

    El servidor de chat

    Dejaré los detalles del diseño de este módulo para la fase de desarrollo (que no forma parte de este artículo). Dicho esto, hay cosas que podemos decidir.

    Una cosa que podemos definir es el conjunto de restricciones para el servidor, lo que simplificará nuestro trabajo en el futuro. Y si jugamos bien nuestras cartas, podríamos terminar con un servicio que proporcione una interfaz robusta, lo que nos permitirá, eventualmente, ampliar o incluso cambiar la implementación para proporcionar menos restricciones sin afectar el juego en absoluto. Todo subre leds e iluminacion

    • Sólo habrá una sala por fiesta.
      No dejaremos que se creen subgrupos. Esto va de la mano con no permitir que el partido se divida. Quizás una vez que implementemos esa mejora, sería una buena idea permitir la creación de subgrupos y salas de chat personalizadas.
    • No habrá mensajes privados.
      Esto es puramente para simplificar, pero tener un chat grupal ya es suficiente; No necesitamos mensajes privados en este momento. Recuerde que siempre que esté trabajando en su producto mínimo viable, trate de evitar caer en la madriguera de características innecesarias; Es un camino peligroso y del que es difícil salir.
    • No persistiremos en los mensajes.
      En otras palabras, si abandonas la fiesta, perderás los mensajes. Esto simplificará enormemente nuestra tarea, ya que no tendremos que lidiar con ningún tipo de almacenamiento de datos, ni perder tiempo decidiendo cuál es la mejor estructura de datos para almacenar y recuperar mensajes antiguos. Todo vivirá en la memoria y permanecerá allí mientras la sala de chat esté activa. Una vez cerrado, ¡simplemente les diremos adiós!
    • La comunicación se realizará a través de sockets .
      Lamentablemente nuestro cliente tendrá que manejar un doble canal de comunicación: uno RESTful para el motor del juego y un socket para el servidor de chat. Esto podría aumentar un poco la complejidad del cliente, pero al mismo tiempo utilizará los mejores métodos de comunicación para cada módulo. (No tiene ningún sentido forzar REST en nuestro servidor de chat o forzar sockets en nuestro servidor de juegos. Ese enfoque aumentaría la complejidad del código del lado del servidor, que es el que también maneja la lógica de negocios, así que centrémonos en ese lado. por ahora.)

    Eso es todo para el servidor de chat. Al fin y al cabo, no será complejo, al menos no al principio. Hay más que hacer cuando llega el momento de empezar a codificarlo, pero para este artículo, es información más que suficiente.

     

    El cliente

    Este es el último módulo que requiere codificación y será el más tonto de todos. Como regla general, prefiero que mis clientes sean tontos y mis servidores inteligentes. De esa forma, crear nuevos clientes para el servidor resulta mucho más fácil.

    Para que estemos en la misma página, aquí está la arquitectura de alto nivel con la que deberíamos terminar.

    Arquitectura final de alto nivel de todo el desarrollo ( vista previa grande )

    Nuestro sencillo cliente ClI no implementará nada muy complejo. De hecho, la parte más complicada que tendremos que abordar es la interfaz de usuario real, porque es una interfaz basada en texto.

    Dicho esto, la funcionalidad que deberá implementar la aplicación cliente es la siguiente:

    1. Crea un nuevo juego .
      Como quiero mantener las cosas lo más simples posible, esto solo se hará a través de la interfaz CLI. La interfaz de usuario real sólo se utilizará después de unirse a un juego, lo que nos lleva al siguiente punto.
    2. Únete a un juego existente .
      Dado el código del juego devuelto en el punto anterior, los jugadores pueden usarlo para unirse. Nuevamente, esto es algo que deberías poder hacer sin una interfaz de usuario, por lo que esta funcionalidad será parte del proceso requerido para comenzar a usar la interfaz de usuario de texto.
    3. Analizar archivos de definición de juegos .
      Hablaremos de esto más adelante, pero el cliente debe poder comprender estos archivos para saber qué mostrar y cómo usar esos datos.
    4. Interactuar con la aventura.
      Básicamente, esto le da al jugador la capacidad de interactuar con el entorno descrito en cualquier momento dado.
    5. Mantener un inventario para cada jugador .
      Cada instancia del cliente contendrá una lista de elementos en memoria. Esta lista será respaldada.
    6. Chat de soporte .
      La aplicación cliente también debe conectarse al servidor de chat e iniciar sesión como usuario en la sala de chat del grupo.

    Más sobre la estructura interna y el diseño del cliente más adelante. Mientras tanto, terminemos la etapa de diseño con la última parte de la preparación: los archivos del juego.

     

    El juego: archivos JSON

    Aquí es donde se vuelve interesante porque hasta ahora he cubierto las definiciones básicas de microservicios. Algunos de ellos pueden hablar REST y otros pueden funcionar con sockets, pero en esencia, todos son iguales: usted los define, los codifica y brindan un servicio.

    Para este componente en particular, no planeo codificar nada, pero necesitamos diseñarlo. Básicamente, estamos implementando una especie de protocolo para definir nuestro juego, las escenas que contiene y todo lo que contiene.

    Si lo piensas bien, una aventura de texto es, en esencia, básicamente un conjunto de habitaciones conectadas entre sí, y dentro de ellas hay "cosas" con las que puedes interactuar, todas unidas con una historia, con suerte, decente. Ahora bien, nuestro motor no se encargará de esa última parte; esa parte dependerá de ti. Pero para el resto hay esperanza.

    Ahora bien, volviendo al conjunto de habitaciones interconectadas, eso a mí me suena a gráfico, y si además le sumamos el concepto de distancia o velocidad de movimiento que os comentaba antes, tenemos un gráfico ponderado. Y eso es sólo un conjunto de nodos que tienen un peso (o simplemente un número, no te preocupes por cómo se llama) que representa ese camino entre ellos. Aquí hay una imagen (me encanta aprender viendo, así que solo mira la imagen, ¿de acuerdo?):

    Un ejemplo de gráfico ponderado ( vista previa grande )

    Ese es un gráfico ponderado, eso es todo. Y estoy seguro de que ya lo has descubierto, pero para estar completo, déjame mostrarte cómo lo harías una vez que nuestro motor esté listo.

    Una vez que comiences a configurar la aventura, crearás tu mapa (como ves a la izquierda de la imagen a continuación). Y luego lo traducirás a un gráfico ponderado, como puedes ver a la derecha de la imagen. Nuestro motor podrá recogerlo y permitirle recorrerlo en el orden correcto.

    Gráfico de ejemplo para una mazmorra determinada ( vista previa grande )

    Con el gráfico ponderado anterior, podemos asegurarnos de que los jugadores no puedan ir desde la entrada hasta el ala izquierda. Tendrían que pasar por los nodos entre esos dos, y hacerlo consumirá tiempo, que podemos medir usando el peso de las conexiones.

    Ahora, pasemos a la parte "divertida". Veamos cómo quedaría el gráfico en formato JSON. Tened paciencia conmigo aquí; Este JSON contendrá mucha información, pero repasaré toda la que pueda:

    { "graph": [ { "id": "entrance", "name": "Entrance", "north": { "node": "1stroom", "distance": 1 } }, { "id": "1st room", "name": "1st Room", "south": {"node": "entrance", "distance": 1} , "north": { "node": "bigroom", "distance": 1} } , { "id": "bigroom", "name": "Big room", "south": { "node": "1stroom", "distance": 1}, "north": { "node": "bossroom", "distance": 2}, "east": { "node": "rightwing", "distance": 3} , "west": { "node": "leftwing", "distance": 3} }, { "id": "bossroom", "name": "Boss room", "south": {"node": "bigroom", "distance": 2} } { "id": "leftwing", "name": "Left Wing", "east": {"node": "bigroom", "distance": 3} } { "id": "rightwing", "name": "Right Wing", "west": { "node": "bigroom", "distance": 3 } } ], "game": { "win-condition": { "source": "finalboss", "condition": { "type": "comparison", "left": "hp", "right": "0", "symbol": "=" } }, "lose-condition": { "source": "player", "condition": { "type": "comparison", "left": "hp", "right": "0", "symbol": "=" } } }, "rooms": { "entrance": { "description": { "default": "You're at the entrance of the dungeon. There are two lit torches on each wall (one on your right and one on your left). You see only one path: ahead." }, "items": [ { "id": "littorch1", "name": "Lit torch on the right", "triggers": [ { "action": "grab", //grab Lit torch on the right "effect":{ "statusUpdate": "has light", "target": "game", } } ] , "destination": "hand" }, { "id": "littorch2", "name": "Lit torch on the left", "triggers": [ { "action": "grab", //grab Lit torch on the left "effect":{ "statusUpdate": "has light", "target": "game", } } ] , "destination": "hand" } ] }, "1stroom": { "description": { "default": "You're in a very dark room. There are no windows and no source of light, other than the one at the entrance. You get the feeling you're not alone here.", "conditionals": { "has light": "The room you find yourself in appears to be empty, aside from a single chair in the right corner. There appears to be only one way out: deeper into the dungeon." } }, "items": [ { "id": "chair", "name": "Wooden chair", "details": "It's a wooden chair, nothing fancy about it. It appears to have been sitting here, untouched, for a while now.", "subitems": [ { "id": "woodenleg", "name": "Wooden leg", "triggeractions": [ { "action": "break", "target": "chair"}, //break  { "action": "throw", "target": "chair"} //throw  ], "destination": "inventory", "damage": 2 } ] } ] }, "bigroom": { "description": { "default": "You've reached the big room. On every wall are torches lighting every corner. The walls are painted white, and the ceiling is tall and filled with painted white stars on a black background. There is a gateway on either side and a big, wooden double door in front of you." }, "exits": { "north": { "id": "bossdoor", "name": "Big double door", "status": "locked", "details": "A aig, wooden double door. It seems like something big usually comes through here."} }, "items": [] }, "leftwing": { "description": { "default": "Another dark room. It doesn't look like it's that big, but you can't really tell what's inside. You do, however, smell rotten meat somewhere inside.", "conditionals": { "has light": "You appear to have found the kitchen. There are tables full of meat everywhere, and a big knife sticking out of what appears to be the head of a cow." } }, "items": [ { "id": "bigknife", "name": "Big knife", "destination": "inventory", "damage": 10} ] }, "rightwing": { "description": { "default": "This appear to be some sort of office. There is a wooden desk in the middle, torches lighting every wall, and a single key resting on top of the desk." }, "items": [ { "id": "key", "name": "Golden key", "details": "A small golden key. What use could you have for it?", "destination": "inventory", "triggers": [{ "action": "use", //use  on north exit (contextual) "target": { "room": "bigroom", "exit": "north" }, "effect": { "statusUpdate": "unlocked", "target": { "room": "bigroom", "exit": "north" } } } ] } ] }, "bossroom": { "description": { "default": "You appear to have reached the end of the dungeon. There are no exits other than the one you just came in through. The only other thing that bothers you is the hulking giant looking like it's going to kill you, standing about 10 feet from you." }, "npcs": [ { "id": "finalboss", "name": "Hulking Ogre", "details": "A huge, green, muscular giant with a single eye in the middle of his forehead. It doesn't just look bad, it also smells like hell.", "stats": { "hp": 10, "damage": 3 } } ] } }}

    Sé que parece mucho, pero si lo reduces a una simple descripción del juego, tienes una mazmorra que comprende seis habitaciones, cada una interconectada con otras, como se muestra en el diagrama de arriba.

     

     

    Tu tarea es atravesarlo y explorarlo. Encontrarás que hay dos lugares diferentes donde puedes encontrar un arma (ya sea en la cocina o en el cuarto oscuro, rompiendo la silla). También te enfrentarás a una puerta cerrada; Entonces, una vez que encuentres la llave (ubicada dentro de la sala similar a una oficina), podrás abrirla y luchar contra el jefe con cualquier arma que hayas recolectado.

    O ganarás matándolo o perderás si te mata.

    Entremos ahora en una descripción más detallada de toda la estructura JSON y sus tres secciones.

    Grafico

    Éste contendrá la relación entre los nodos. Básicamente, esta sección se traduce directamente en el gráfico que vimos antes.

    La estructura de esta sección es bastante sencilla. Es una lista de nodos, donde cada nodo comprende los siguientes atributos:

    • una identificación que identifica de forma única el nodo entre todos los demás en el juego;
    • un nombre, que es básicamente una versión legible por humanos del ID;
    • un conjunto de enlaces a los otros nodos. Esto se evidencia en la existencia de cuatro claves posibles: norte”, sur, este y oeste. Eventualmente podríamos agregar más direcciones sumando combinaciones de estas cuatro. Cada enlace contiene el ID del nodo relacionado y la distancia (o peso) de esa relación.

    Juego

    Esta sección contendrá las configuraciones y condiciones generales. En particular, en el ejemplo anterior, esta sección contiene las condiciones de ganar y perder. En otras palabras, con esas dos condiciones, le avisaremos al motor cuándo puede terminar el juego.

    Para simplificar las cosas, agregué solo dos condiciones:

    • O ganas matando al jefe.
    • o perder si lo matan.

    Habitaciones

    De aquí proceden la mayoría de las 163 líneas, y es el tramo más complejo. Aquí es donde describiremos todas las habitaciones de nuestra ave






    Tal vez te puede interesar:

    1. ¿Deberían abrirse los enlaces en ventanas nuevas?
    2. 24 excelentes tutoriales de AJAX
    3. 70 técnicas nuevas y útiles de AJAX y JavaScript
    4. Más de 45 excelentes recursos y repositorios de fragmentos de código

    Escribir un motor de aventuras de texto multijugador en Node.js (Parte 1)

    Escribir un motor de aventuras de texto multijugador en Node.js (Parte 1)

    Implemente rápidamente. Implementar inteligentemente Patrones de diseño de interfaces inteligentes, vídeo de 10h + formación UX Índice

    programar

    es

    https://pseint.es/static/images/programar-escribir-un-motor-de-aventuras-de-texto-multijugador-en-node-960-0.jpg

    2024-04-04

     

    Escribir un motor de aventuras de texto multijugador en Node.js (Parte 1)
    Escribir un motor de aventuras de texto multijugador en Node.js (Parte 1)

    Si crees que alguno de los contenidos (texto, imagenes o multimedia) en esta página infringe tus derechos relativos a propiedad intelectual, marcas registradas o cualquier otro de tus derechos, por favor ponte en contacto con nosotros en el mail [email protected] y retiraremos este contenido inmediatamente

     

     

    Top 20