Tutoriales
Narrativas ramificadas sin espaguetis

Ocho patrones para que una novela gráfica ramificada siga siendo fácil de mantener en PanelWave: separa el flujo del estado y del contenido, construye cada decisión como una tríada, converge pronto, guarda las consecuencias en variables y prueba todos los caminos antes de que tu público encuentre el que se te escapó.
Todas las historias interactivas empiezan igual: una bifurcación limpia en la página tres. Al llegar al capítulo cuatro, el diagrama de flujo parece un plato de pasta, la mitad de las viñetas son copias de otras con una frase cambiada y nadie se atreve a tocar el grafo. Este artículo trata de cómo no llegar ahí. Da por supuesto que conoces lo básico del editor de Primeros pasos con PanelWave CMS y va directo a las decisiones de diseño que deciden si una obra ramificada sigue siendo editable.
En resumen: PanelWave te da tres herramientas distintas, y los espaguetis aparecen cuando solo usas una. El flujo vive en el grafo del capítulo. El estado vive en las variables. El contenido reacciona al estado mediante variantes de viñeta y condiciones de visibilidad. Mantén el grafo pequeño, deja que las variables lleven las consecuencias y que las viñetas las reflejen.
Patrón 1: Elige la herramienta adecuada para cada diferencia
Antes de dibujar una bifurcación, pregúntate qué cambia realmente entre los dos caminos. Hay tres respuestas, y cada una corresponde a un mecanismo distinto del formato:
La documentación resume las ventajas e inconvenientes en una tabla en Variantes frente a otros mecanismos condicionales. La mayoría de los grafos espagueti son variantes y condiciones de visibilidad que se dibujaron como bifurcaciones.
- Los lectores ven viñetas distintas. Es una diferencia de flujo. Usa aristas condicionales en el Graph Editor; la referencia del grafo recoge todas las propiedades.
- Los lectores ven la misma viñeta con contenido distinto. Un fondo diferente, una superposición adicional, una línea de diálogo cambiada. Eso es una variante de viñeta: el mismo nodo en el grafo, con contenido alternativo elegido por una condición. El flujo de la historia no cambia.
- Un elemento aparece o desaparece. Una zona interactiva que solo aparece cuando el lector tiene la llave, un bocadillo que solo se muestra tras una decisión. Eso es una condición de visibilidad en ese elemento, definida con el Condition Builder, y el resto de la viñeta queda intacto.
Patrón 2: Declara tu estado antes de ramificar
Las variables son la memoria de la historia: tienen tipo y se declaran de antemano. Ponles identificadores con espacio de nombres, separados por puntos, que digan a qué pertenecen: story.choice, stats.trust, inventory.hasKey, prefs.hints. Usa un enum para cualquier decisión con un conjunto fijo de resultados. Así, una errata en una condición da un error visible en lugar de no coincidir nunca, en silencio.
El ámbito es la decisión que casi todo el mundo se salta. Controla cuándo se reinicia un valor: page, chapter, global, session o persistent. La regla práctica de la guía de variables: las decisiones que toda la obra debe recordar van en global o persistent, el estado de un acertijo de corta duración en chapter o page, y los indicadores válidos solo para esta visita, como una pista descartada, en session. Las variables persistentes sobreviven entre visitas, y eso es lo que hace posibles los contenidos desbloqueables y los indicadores de finalización (guardar el progreso en el reproductor).
En el CMS esto se hace en el diseñador de variables: abre el Backstage de una obra, elige Variables y declara cada variable una vez con su identificador, tipo, ámbito y valor predeterminado. El diálogo valida los identificadores, las listas enum y los valores predeterminados antes de guardar nada, y la misma lista pasa al manifiesto, a los valores forzados de la página Preview y al reproductor. Si mantienes un manifiesto a mano, Export JSON te da las definiciones como un fragmento listo para pegar, e importar un manifiesto conserva su sección de variables. La guía de variables explica el diseñador paso a paso; el esquema de variables tiene el formato exacto.
{
"variables": {
"definitions": [
{
"id": "story.choice",
"type": "enum",
"enum": ["left", "right", "none"],
"default": "none",
"scope": "chapter"
},
{ "id": "stats.trust", "type": "integer", "default": 50, "scope": "global" }
]
}
}Patrón 3: Construye cada decisión como una tríada
En PanelWave, una decisión nunca es un único objeto. Son tres cosas que hacen referencia a una misma variable: una zona interactiva que la asigna, una arista por resultado que la comprueba y una arista incondicional como respaldo. Construye siempre las tres y nadie se quedará atascado.
En la viñeta de decisión, dibuja una zona interactiva por opción y dale a cada una su acción Set Variables: story.choice con el valor left, story.choice con el valor right. En el Graph Editor, selecciona la viñeta de origen, pulsa C, elige el destino y pulsa Enter para dibujar las aristas; después selecciona cada arista y escribe su condición. Las condiciones son JSON Logic: un operador, una referencia a una variable, un valor. La sección Condiciones de las aristas tiene ejemplos para copiar y adaptar con igualdad, mayor que y reglas combinadas.
{ "from": "p3", "to": "p4-left", "condition": { "==": [{ "var": "story.choice" }, "left"] }, "priority": 1 }
{ "from": "p3", "to": "p4-right", "condition": { "==": [{ "var": "story.choice" }, "right"] }, "priority": 1 }
{ "from": "p3", "to": "p4-left", "priority": 0 }La tercera arista es la red de seguridad: si el lector avanza sin hacer clic en ninguna puerta, el reproductor toma la arista incondicional. El campo priority ordena las aristas en competencia cuando coinciden varias, como se describe en Ramificación. El reproductor evalúa todo esto en cada paso; el algoritmo se explica en Cómo recorre el grafo el reproductor.
Un detalle de nomenclatura que confunde a mucha gente: en una arista, las escrituras de variables van en la lista action, mientras que en una zona interactiva van en mutations. La referencia del grafo lo señala expresamente. En el CMS rara vez tocas ninguna de las dos directamente, pero importa cuando lees un manifiesto exportado.
Patrón 4: Ramifica y luego converge
La forma clásica de una historia ramificada mantenible es el rombo: bifurca, recorre dos o tres viñetas por camino y converge en una viñeta compartida. Cada bifurcación que no converge duplica la cantidad de ilustraciones que tienes que dibujar y el número de caminos que tienes que probar. Converge pronto y a menudo.
Pero la convergencia parece amnesia si la historia olvida lo que pasó. Ahí vuelve a entrar el estado. La decisión ya vive en story.choice; las viñetas compartidas tras el cuello de botella pueden reflejarla con una variante de viñeta cuya condición when comprueba la variable y cuyos overrides cambian las capas o el diálogo. Un nodo de viñeta, dos versiones del momento, ninguna viñeta duplicada en el grafo. La documentación lo llama reflejo de la decisión y muestra un ejemplo completo en El patrón de decisión.
Dos reglas sobre las variantes que te ahorrarán depuración más adelante. Las variantes se evalúan en el orden del array y gana la primera que coincide, así que ordénalas de la más específica a la menos específica cuando las condiciones puedan solaparse (Orden de selección). Y si una variante sobrescribe el array layers, sustituye toda la pila, así que repite las capas base que quieras conservar. En el editor, las viñetas con variantes muestran una etiqueta V en el árbol de estructura, y la barra de filtros del árbol puede mostrar solo esas viñetas (Páginas y viñetas).
Patrón 5: Nodos centrales, bucles y contadores
Un grafo de PanelWave admite ciclos, y con ellos se construyen los nodos centrales: una sala a la que se vuelve entre exploraciones, una pantalla de mapa, un menú de conversación. El panel de validación del grafo señala los ciclos, pero solo como aviso: un bucle intencionado no es un error (Validación).
Lo que impide que un nodo central se convierta en un bucle infinito es un contador. Dale a cada misión secundaria una zona interactiva que incremente stats.visits o active un booleano como story.metCourier, y pon la arista de salida del nodo central detrás de una condición como stats.visits mayor o igual que tres. Las operaciones de mutación son set, increment, toggle, append y remove (Mutación). Se explora en cualquier orden, la salida se desbloquea al terminar y el grafo sigue siendo una estrella ordenada, no una permutación de todos los órdenes posibles.
Patrón 6: Condiciona elementos, no dupliques viñetas
Cuando solo una cosa de una viñeta depende del estado, condiciona esa cosa. Las zonas interactivas y los bocadillos tienen una sección Visibility Condition en el inspector; haz clic en Build Condition y el Condition Builder escribe la expresión por ti: variable, tipo, operador y valor, combinados con AND u OR. El caso clásico es una puerta cerrada con llave: la zona interactiva A asigna true a inventory.hasKey en otro punto de la historia, y la zona interactiva B de la puerta solo se puede pulsar cuando inventory.hasKey es igual a true (Condiciones en zonas interactivas).
Las mutaciones de las zonas interactivas van un paso más allá: un disparador When Variable Changes puede animar la opacidad, la escala, la posición o el color en el momento en que cambia el estado, de modo que la ilustración reacciona a una decisión sin cambiar de viñeta. En la obra publicada, el público ve las zonas interactivas como regiones con un contorno que late suavemente, totalmente accesibles con el teclado (la vista del lector); no ven nada de tu lógica de condiciones.
Patrón 7: Mantén el mapa legible
Un grafo que no puedes leer es un grafo que vas a romper. Unos pocos hábitos lo mantienen legible a medida que crece la obra:
- Un capítulo, un grafo. Cada capítulo tiene su propio grafo y su propia viñeta de entrada. Trata los capítulos como la unidad de ramificación: un capítulo debería contener una bifurcación con su convergencia completa, no media.
- Pon nombre a las viñetas. Dales un Friendly ID como courier-door-left en las Basic Properties del inspector (Páginas y viñetas); el Graph Editor etiqueta los nodos con los títulos de las viñetas, y el manifiesto puede llevar etiquetas de nodo visibles para el lector en los mapas de capítulo.
- Deja que la máquina lo ordene. Auto-Layout (L) dispone el grafo de izquierda a derecha según la profundidad de la historia y minimiza los cruces; las posiciones se recuerdan por capítulo. El interruptor List muestra el mismo grafo como un esquema anidado, apto para lectores de pantalla, con etiquetas de entrada y de final (Moverse por el grafo).
- Oculta lo que debe quedar oculto. Si el capítulo usa el lienzo infinito, configura las ramas secretas como Hidden until visited en los modos de revelado para que la vista general no las desvele; se recomienda el mismo ajuste para las viñetas tras un muro de pago.
Patrón 8: Prueba todos los caminos y luego mide los reales
Los errores de ramificación se esconden en el camino en el que no hiciste clic. PanelWave te da tres niveles de comprobación, y cada uno responde a una pregunta distinta.
Cuando la obra está publicada, las Analíticas te dicen qué ramas toman de verdad los lectores. El embudo de lectura muestra las sesiones por viñeta en orden de lectura, así que una caída brusca justo después de una bifurcación suele significar que la decisión no estaba clara. El mapa de calor de clics muestra dónde toca la gente, haya zona interactiva o no; un grupo de toques fuera de todas las zonas interactivas significa que esperaban una decisión que no ofreciste. Ambas cosas salen más baratas que adivinar.
- Estructura: el modo Simulate del Graph Editor recorre el grafo desde la entrada, enumera cada arista de salida en Where to next con su condición en línea e informa de los callejones sin salida. Solo recorre la estructura y no evalúa condiciones (Simular el flujo). Pulsa V para volver a ejecutar la validación, que señala nodos inalcanzables, nodos aislados y viñetas de entrada que faltan, con correcciones en un clic para los casos habituales.
- Lógica: Preview muestra cada variable con un campo adecuado a su tipo. Fuerza story.choice a cada valor y vuelve a leer el capítulo; guarda la combinación como escenario para la siguiente ronda (Forzar variables). Según la documentación, el error de ramificación más común es una condición que nunca puede cumplirse porque nada llega a asignar la variable. Prueba ambos lados de cada rama.
- Publicación: Preflight ejecuta comprobaciones en toda la obra antes de publicar, incluidos problemas de flujo como viñetas inalcanzables desde la entrada del capítulo y referencias de aristas rotas (Validación y Preflight). Los errores bloquean la publicación.
Un ejemplo práctico: el mensajero
Aquí tienes un capítulo completo diseñado con estos patrones. Siete viñetas, una bifurcación, un nodo central, ninguna ilustración duplicada.
De la viñeta 3 salen tres aristas, contando el respaldo; por el nodo central pasan tres bucles; hay una sola salida. El grafo cabe en una pantalla, Simulate lo recorre en menos de un minuto y todas las consecuencias de las decisiones del lector viven en tres variables que puedes inspeccionar en Preview.
- Variables: story.choice (enum: left, right, none; ámbito chapter), stats.visits (integer, ámbito chapter), inventory.hasKey (boolean, ámbito global).
- Viñetas 1 a 3: lineales. La viñeta 3 es la decisión: dos zonas interactivas de puerta, cada una con una acción Set Variables sobre story.choice y una acción Navigate a la viñeta 4.
- Viñeta 4: una viñeta, dos variantes. La variante left añade una superposición y la frase «Has tomado la escalera de la izquierda»; la variante right cambia el fondo. La viñeta base es el respaldo para quien avanza sin elegir.
- Viñeta 5: el nodo central, un patio con tres zonas interactivas. Cada una lleva a una viñeta lateral (6a, 6b, 6c) cuya arista de vuelta incrementa stats.visits; la que tiene la llave además asigna true a inventory.hasKey. La zona interactiva de salida del nodo central tiene la condición de visibilidad stats.visits mayor o igual que dos.
- Viñeta 7: el final. Su arista desde el nodo central es incondicional, y una variante comprueba inventory.hasKey para mostrar la versión desbloqueada.
Para seguir leyendo
- Navegación por grafo: por qué un grafo en lugar de un orden de páginas, y cómo lo recorre el reproductor.
- Variables: el modelo de estado que hay detrás de cada condición.
- Estado y condiciones en el reproductor: cómo evalúa el reproductor JSON Logic y guarda el estado.
- Zonas interactivas en el formato: las acciones goTo, setVariables, openExtras, openModal y pluginEvent.
- Monetización: dónde colocar el límite de un muro de pago en un capítulo ramificado y cómo previsualizar como lector gratuito o prémium.

