32blogby StudioMitsu

Opciones y Ramificaciones en Ren'Py: De Menús a Múltiples Finales

Aprende a implementar opciones y ramificaciones en Ren'Py 8.5. Cubre sintaxis de menú, jump vs call, gestión de flags, opciones condicionales y múltiples finales.

7 min read
Contenido

Lo que hace que una novela visual merezca ser rejugada son las opciones. La historia cambia según lo que el jugador elige, y eso es lo que le hace volver.

Esta guía cubre cómo implementar opciones y ramificaciones en Ren'Py 8.5.2, desde la declaración básica menu hasta múltiples finales.

La declaración menu

La declaración menu presenta opciones al jugador y ramifica según su selección.

renpy
label start:
    "The road splits in two."

    menu:
        "Which way?"

        "Take the left path":
            "You chose the left path. A forest stretches ahead."

        "Take the right path":
            "You chose the right path. A river comes into view."

    "The journey continues."

La cadena directamente debajo de menu: ("Which way?") es el subtítulo. Las cadenas debajo se convierten en las opciones. Cada bloque de opción contiene el código que se ejecuta cuando se selecciona esa opción.

Después de que termina el bloque de opción, la ejecución continúa en la línea después del menu ("The journey continues."). Independientemente de qué opción se eligió, el flujo se une aquí.

Haciendo que un personaje pregunte

En lugar de un subtítulo, puedes hacer que un personaje diga la pregunta.

renpy
define e = Character("Eileen")

label start:
    menu:
        e "Which do you prefer?"

        "Tea":
            e "Tea it is."

        "Coffee":
            e "Coffee it is."

Escribir e "Which do you prefer?" lo muestra como diálogo de Eileen y luego muestra las opciones.

jump vs call

Cuando los bloques de opciones se hacen largos, mueve la lógica a labels separados con jump o call. Estos dos se parecen pero difieren en un aspecto crítico: si la ejecución regresa o no.

jump — Solo ida

renpy
label start:
    menu:
        "Which way?"

        "The forest":
            jump forest_route

        "The town":
            jump town_route

label forest_route:
    "You ventured deep into the forest."
    jump chapter_2

label town_route:
    "You arrived at a bustling town."
    jump chapter_2

label chapter_2:
    "Chapter 2 begins."

jump mueve la ejecución al label especificado y nunca regresa. Úsalo para transiciones de ruta y finales.

call — Ir y volver

renpy
label start:
    "Time to prepare for the adventure."

    call shop

    "Shopping done. Time to set off."

label shop:
    "What will you buy?"

    menu:
        "Buy a sword":
            $ has_sword = True
        "Buy a shield":
            $ has_shield = True

    return

call mueve la ejecución al label especificado, y return la devuelve al llamador. Úsalo para escenas compartidas (tiendas, minijuegos, flashbacks) que quieras invocar desde múltiples lugares.

Comparación

jumpcall
RegresaNoSí, vía return
Úsalo paraRamificaciones de ruta, finalesEscenas compartidas, subrutinas
Pila de llamadasNo agregaAgrega (consumido por return)

Gestionando ramificaciones con flags

Guarda los resultados de las opciones en variables (flags) para referenciarlos en escenas posteriores.

Declarando flags

renpy
# Declarar con default (se guarda en archivos de guardado)
default met_fairy = False
default affection = 0

label start:
    menu:
        "Talk to the fairy?"

        "Talk to her":
            $ met_fairy = True
            $ affection += 10
            "You became friends with the fairy."

        "Ignore her":
            "You walked past."

Siempre declara flags con default. Las variables declaradas con default se guardan en los archivos de guardado y se restauran correctamente al cargar.

Ramificando según flags

renpy
label chapter_2:
    if met_fairy:
        "The fairy from before appeared."
        $ affection += 5
    else:
        "An unfamiliar fairy appeared."

    if affection >= 10:
        "The fairy smiled at you."
    else:
        "The fairy is cautious."

Usa if/elif/else para cambiar texto y eventos según los valores de las variables.

Opciones condicionales

Agrega una condición if a una opción para mostrarla solo cuando se cumple la condición.

renpy
default has_key = False

label locked_door:
    "A locked door stands before you."

    menu:
        "Use the key" if has_key:
            "The door opened."
            jump secret_room

        "Turn back":
            "You decided to find another way."

Cuando has_key es False, "Use the key" no aparece en el menú. El jugador solo ve "Turn back."

Mostrando opciones deshabilitadas en gris

En lugar de ocultar las opciones no cumplidas, puedes mostrarlas en gris para señalar "esto existe pero aún no puedes elegirlo."

renpy
init python:
    config.menu_include_disabled = True

label locked_door:
    menu:
        "Use the key" if has_key:
            "The door opened."

        "Turn back":
            "You decided to find another way."

Establecer config.menu_include_disabled = True muestra las opciones no cumplidas en estado deshabilitado (gris). Esto le sugiere al jugador que diferentes condiciones podrían desbloquearlas.

Excluyendo opciones ya elegidas

Usa set para eliminar automáticamente las opciones que el jugador ya eligió.

renpy
default explored = set()

label explore:
    "What do you examine?"

    menu:
        set explored

        "The desk":
            "You found a letter."

        "The bookshelf":
            "You found an old diary."

        "The window":
            "You saw someone's shadow outside."

    if len(explored) < 3:
        jump explore
    else:
        "You've examined everything."

Implementando múltiples finales

Combina todo lo anterior para construir múltiples finales.

Basado en puntos: Ramificar por afinidad

Suma o resta puntos según las opciones del jugador, luego decide el final por el valor final.

renpy
default affection = 0

label start:
    "You met Eileen."

    menu:
        "Greet her":
            $ affection += 10
            "Eileen looks happy."

        "Walk past":
            "Eileen looks lonely."

    "The journey continued for a while."

    menu:
        "Help Eileen":
            $ affection += 20
            "Eileen's eyes lit up."

        "Look the other way":
            $ affection -= 10
            "Eileen looked disappointed."

    jump ending

label ending:
    if affection >= 20:
        jump good_ending
    elif affection >= 0:
        jump normal_ending
    else:
        jump bad_ending

label good_ending:
    "You and Eileen forged an unbreakable bond."
    "GOOD END"
    return

label normal_ending:
    "You and Eileen remained friends."
    "NORMAL END"
    return

label bad_ending:
    "Eileen left without a word."
    "BAD END"
    return

Basado en flags: Ramificar por combinaciones de eventos

En lugar de puntos, decide el final según si ocurrieron eventos específicos.

renpy
default saved_cat = False
default found_letter = False

label start:
    menu:
        "Save the cat":
            $ saved_cat = True
        "Walk past":
            pass

    menu:
        "Read the letter":
            $ found_letter = True
        "Ignore the letter":
            pass

    jump ending

label ending:
    if saved_cat and found_letter:
        "You uncovered the whole truth."
        "TRUE END"
    elif saved_cat:
        "The cat came back to return the favor."
        "CAT END"
    elif found_letter:
        "You solved the mystery of the letter."
        "LETTER END"
    else:
        "You found nothing."
        "NORMAL END"
    return

En la práctica, la mayoría de los juegos combinan ambos enfoques — usan puntos (afinidad) para determinar la ruta principal, y flags para variaciones más pequeñas dentro de cada ruta.

Conclusión

Lo que cubrimos:

  • Declaración menu: Sintaxis básica de opciones. Usa subtítulos o diálogo de personajes para plantear preguntas
  • jump vs call: jump es solo ida, call regresa vía return. Usa call para escenas compartidas
  • Gestión de flags: Declara variables con default para guardar resultados de opciones
  • Opciones condicionales: Controla la visibilidad con condiciones if. config.menu_include_disabled para visualización en gris
  • Múltiples finales: Patrones basados en puntos (afinidad) y basados en flags (seguimiento de eventos)

Para lo básico de Ren'Py, consulta la guía de inicio. Para gestión de variables, consulta la guía de gestión de estadísticas. Para la interfaz de usuario, consulta la guía de screen language. Cuando tu juego esté listo, consulta la guía de distribución para compilar y publicar.

Recursos oficiales: