A finales de 2025 recibi un correo de un desarrollador ruso aficionado a la ficcion interactiva. Su nombre es Nikita Tseykovets y estaba interesado en portar Jim del espacio exterior a su engine de creación de aventuras interactivas: UrqW, además de traducirlo al ruso para participar en una jam de ficción interactiva, lo cual me hizo bastante ilusión, para qué voy a negarlo. Aquí podéis encontrar la versión en ruso: https://urqw.github.io/UrqW/index.html?id=jim_from_outer_space_ru y aquí la versión en español: https://urqw.github.io/UrqW/?id=jim_from_outer_space
No he leído las críticas que tuvo el juego en dicha jam porque soy consciente de que es una obra amateur y es probable que no sean buenas. A ver, la escribí en las noches de un verano de post adolescencia con el noble fin de llamar la atención de alguna fémina y que esta se fijara en mí con erótico resultado. Me hubiera venido mejor apuntarme a un gimnasio o invertir en acciones pero en aquella época no pensaba demasiado y no tenía dinero ni ganas de hacerlo. Escribir era más sencillo. No funcionó pero quedó esta obra inmortal que podéis encontrar en Amazon o en el blog en el que comenzó todo.
Este renovado interés por mi "obra" me dio ánimos para terminar una empresa que había dejado a medias hacía mucho: portar el libro-juego, también, a las pantallas móviles o de ordenador. Para ello decidí utilizar Twine con el formato de historia Sugarcube. Modifiqué la plantilla de estilos y añadí alguna cosa más. Lo más destacado que hice fue el sistema de memoria de finales por el cual cada vez que alcanzas uno de los 39 posibles finales, este se desbloquea en el modo Historias y puedes disfrutar de la trama que te ha llevado a él sin necesidad de jugar de nuevo. Necesita de bastantes mejoras pero como prueba no está mal.
Para lograr esto en Twine 2 y SugarCube 2.37, necesitamos combinar dos cosas: el almacenamiento permanente del navegador (memorize y recall) para que los finales no se borren al reiniciar el juego, y un sistema de arrays (listas) para ir guardando el texto de los pasajes que el jugador va leyendo en su partida actual.
1. Pasajes de Configuración e Inicio
Pasaje: StoryInit
Este pasaje especial sirve para preparar la lista vacía donde registraremos la historia del jugador en la partida actual.
Fragmento de código
<<set $historialActual to []>>
Pasaje: Start (Pantalla de Inicio)
La pantalla principal con los dos botones que pides.
Fragmento de código
# Jim del espacio exterior
<<button "Comenzar JUEGO" "Introduccion">>
<<set $historialActual to []>>
<</button>>
<<button "Ver Historias/Finales" "PantallaHistorias">><</button>>
2. El truco: Guardar los textos automáticamente
Para no tener que escribir código en cada nodo del juego, usaremos un pasaje especial de SugarCube llamado PassageReady. Todo lo que pongas aquí se ejecuta automáticamente cada vez que el jugador entra a un pasaje nuevo.
Pasaje: PassageReady
Crea un pasaje con este nombre exacto y pega lo siguiente:
Fragmento de código
<<if tags().contains("historia")>>
<<run $historialActual.push({
titulo: passage(),
texto: story.get(passage()).processText()
})>>
<</if>>
💡 ¡IMPORTANTE! Para que este sistema funcione, todos los pasajes de tu juego que tengan texto de la historia deben llevar la etiqueta (tag)
historia. Los pasajes de menús o pantallas de fin no deben llevarla para que no se mezcle el texto de los menús en la lectura final.
3. Registrar los Finales para Siempre
Cuando el jugador llegue a un pasaje de final, usaremos memorize() para guardar permanentemente esa ruta en el navegador.
- Pasaje de ejemplo:
Final 1(Etiqueta:historia)
Llegaste al Final 1: Te convertiste en polvo de estrellas.
<<run memorize("final_1_desbloqueado", clone($historialActual))>>
* **Pasaje de ejemplo: `Final 2` (Etiqueta: `historia`)**
```tweecode
Llegaste al Final 2: Salvaste la galaxia.
<<run memorize("final_2_desbloqueado", clone($historialActual))>>
[[Volver al Menú Principal|Start]]
4. La Pantalla de "Historias" (Menú de Finales)
Aquí comprobamos qué finales existen en la memoria del navegador (recall). Si no hay ninguno, solo mostrará el botón de volver.
Pasaje: PantallaHistorias
Fragmento de código
# Registro de Viajes Espaciales
<<set _hayFinales to false>>
<<if recall("final_1_desbloqueado")>>
<<set _hayFinales to true>>
<<button "Leer: Final 1 (Polvo de Estrellas)" "VerFinal">>
<<set $finalAVisualizar to recall("final_1_desbloqueado")>>
<</button>>
<</if>>
<<if recall("final_2_desbloqueado")>>
<<set _hayFinales to true>>
<<button "Leer: Final 2 (Héroe Galáctico)" "VerFinal">>
<<set $finalAVisualizar to recall("final_2_desbloqueado")>>
<</button>>
<</if>>
<<if not _hayFinales>>
<p>Aún no has desbloqueado ningún final. ¡Explora el espacio exterior para registrar tus viajes!</p>
<</if>>
---
<<button "Volver al Inicio" "Start">><</button>>
5. El Lector de Historias Completo
Este pasaje agarra la lista de pasajes guardados y los imprime de corrido, uno debajo del otro, para que el jugador pueda leer toda su aventura de seguido.
Pasaje: VerFinal
Fragmento de código
# Bitácora de Vuelo Completa
<div class="historia-corrida">
<<for _nodo range $finalAVisualizar>>
<div class="nodo-leido">
/* Opcional: Descomenta la línea de abajo si quieres mostrar los títulos de los pasajes */
/* <h3>_nodo.titulo</h3> */
<p>_nodo.texto</p>
</div>
<hr>
<</for>>
</div>
<<button "Volver a Historias" "PantallaHistorias">><</button>>
🎨 Un toque visual (Opcional)
Para que la lectura de corrido no se vea desordenada, puedes añadir esto en el Estilo de la historia (Story Stylesheet) de tu Twine:
CSS
.nodo-leido {
margin-bottom: 20px;
line-height: 1.6;
}
.historia-corrida hr {
border: 0;
border-top: 1px dashed #444;
margin: 30px 0;
}
Tras publicarla, doy por terminado el capítulo Jim del espacio exterior. Es hora de pasar a nuevos proyectos.
Podéis encontrar la aventura en su página de Itch.io: https://backsidegames.itch.io/jim-del-espacio-exterior-the-cyoa Aunque os pida que verifiquéis que sois mayores de edad, no hay imágenes explícitas de ningún tipo, solo ligeros toques picantes en algunos pasajes, pero por si las moscas, y sin tener ninguna pretensión comercial, lo he puesto como NSFW.


















