GráficosContenidosGlulx e Inform Glulx Cómo hacer cosas con Glulx Inform

Cómo hacer cosas con Glulx Inform

Arrancando

Lo que necesitarás para usar Glulx Inform

Para compilar un juego con Inform Glulx, necesitarás lo siguiente: Y para ejecutar el programa que has compilado, necesitarás: Y si quieres incluir sonido o gráficos en tu juego, aún necesitas otra cosa más: Blorb ¿Qué es eso? Sigue leyendo...

Blorb

Como ya hemos señalado en secciones previas, la comunidad (inglesa) de programadores de ACs, tiende a dar una prioridad muy alta al hecho de que los juegos y herramientas para ACs sean utilizables por usuarios del mayor número posible de plataformas. Pero esta accesibilidad tiene un precio. Incluso el sólo hecho de jugar una AC generalmente requiere descargar una pareja de piezas diferentes: el intérprete apropiado para la máquina de uno, y el fichero con el juego; ahora imagina lo que ocurrirá si metemos la multimedia en la mezcla. Ya sería lo bastante malo si simplemente fuera cosa de coger unos cientos de imágenes y un generoso suministro de ficheros musicales y meterlos todos en un archivo zip junto con el fichero del juego, pero es más lioso que eso. Incluso si consigues que todos tus ficheros vayan del ordenador A al ordenador B, sin perder nada por el camino ¿quién dice que el ordenador B será capaz de comprenderlos? ¡Hasta los nombres de fichero pueden ser un problema cuando se intentan compartir datos entre diferentes tipos de plataforma! Las máquinas DOS y Windows requieren que los ficheros tengan una extensión de tres letras apropiada, para poder usarlos; las máquinas Acorn (como la que usó Graham para crear Inform) ni siquiera permiten extensiones en los nombres. Ser capaz de meter en un solo fichero todos los recursos que un juego necesita, junto con el propio juego, de forma que pueda ser leido por diferentes intérpretes en muchas plataformas diferentes, sería un gran avance. Para esto es Blorb. Para crear un fichero Blorb, necesitarás lo siguiente: Por desgracia, Blorb es muy nuevo, y las herramientas "blorbificadoras" aún no han sido estandarizadas, ni está muy ampliamente soportado de momento. Hasta que esto sea así, tenemos que apañarnos con las herramientas específicas disponibles para cada plataforma. Elige de la lista siguiente (aunque de momento, tus posibles elecciones son, ejem, limitadas): Para más información sobre Blorb, mira en la página de Blorb de Graham Nelson y en la página de Blorb de Andrew Plotkin.

Test de capacidades

Imagina que tienes un juego que transcurre en una ciudad del salvaje Oeste, y que cuando el protagonista entra a la ciudad, pasa junto a un cartel que dice "Perro Muerto, Kansas, Población 213" con la pintura gastada sobre un madero estropeado y acribillado a balazos. El jugador sin embargo no sabe lo que pone hasta que no ordena "EXAMINA CARTEL", la descripción del lugar simplemente tiene la línea "Aquí ves un cartel" o algo así, para indicar que está ahí. Y digamos que tienes una magnífica imagen de un estropeado cartel con balazos. Lo ideal sería que pudieras mostrar la imagen si el intérprete que usa el jugador puede manejar gráficos, o imprimir un párrafo describiendo el cartel si no. Para esto sirve glk_gestalt() Hay como una docena de cosas que puedes testear. En este ejemplo, la constante a usar sería gestalt_Graphics, y el código del cartel sería más o menos así:

Object  cartel "cartel erosionado"
 with   nombre 'cartel' 'erosionado',
        descripcion [;
            if (glk_gestalt(gestalt_Graphics, 0))
            {
                ! Aqui iría el código para mostrar el gráfico
            } else
                "El cartel dice ~PERRO MUERTO, KANSAS, POBL. 213.~ O
                quizás ponía 2130, o 21300, alguien ha volado la
                esquina del cartel de un disparo.";
        ],
 has    estatico; 

Observa el 0 en la llamada a glk_gestalt - es obligatorio, porque glk_gestalt siempre requiere dos parámetros, incluso si el segundo no se necesita como en este caso. He aqui algunas constantes que puedes usar con glk_gestalt:
Constante Segundo parámetro Qué retorna
gestalt_Version 0 Un número de 32 bits que lleva codificado el número de versión de Glk (los 16 primeros bits, el número de versión mayor, los 8 siguientes el número menor y los 8 últimos el número sub-menor, de modo que la versión 0.6.1 se codificaría como 00000601
gestalt_CharOuput código de un carácter Esto es para comprobar si el intérprete es capaz de mostrar un carácter determinado (como la ñ). El resultado es uno de tres posibles valores: gestalt_CharOuput_ExactPrint si puede mostrarlo, gestalt_CharOutput_CannotPrint si no puede, o gestalt_CharOutput_ApproxPrint si lo cambia por algo parecido (por ejemplo n en vez de ñ)
gestalt_LineInput código de un carácter Como el anterior, pero para comprobar si ese carácter es admitido durante la lectura de una línea (o sea, la entrada que es procesada después de haber pulsado Intro)
gestalt_CharInput código de un carácter Como el anterior, pero para comprobar si ese carácter es admitido durante la lectura de una tecla (un tipo de entrada en el que sólo se procesa un carácter de cada vez)
gestalt_MouseInput tipo de ventana 1 si se soporta la entrada desde ratón, 0 si no
gestalt_Timer 0 1 si se soporta el tiempo real, 0 si no
gestalt_Graphics 0 1 si se soportan gráficos, 0 si no
gestalt_DrawImage tipo de ventana Este es para probar específicamente si se pueden colocar imágenes en un tipo concreto de ventana (wintype_TextBuffer o wintype_Graphics): 1 si se puede, 0 si no
gestalt_GraphicsTransparency 0 Esta es para comprobar si las imágenes PNG con zonas transparentes aparecerán realmente con la transparencia funcionando como debe. 1 si es así, 0 si no
gestalt_Sound 0 1 si hay sonido disponible, 0 si no
gestalt_SoundMusic 0 1 si se puede interpretar música MOD, 0 si no (esto puede retornar cero incluso si glk_gestalt(gestalt_Sound, 0) retornó 1 - en este caso sólo se soportan efectos de sonido AIFF
gestalt_SoundVolume 0 1 si funciona la función glk_schannel_set_volume(), 0 si no
gestalt_SoundNotify 0 1 si se puede hacer que HandleGlkEvent() ejecute el código que el programador desee en el momento que un sonido finaliza, 0 si no
gestalt_Hyperlinks 0 1 si se soportan los hipervínculos, 0 si no
gestalt_HyperlinkInput tipo de ventana 1 si los hipervínculos están soportados en ese tipo concreto de ventana, 0 si no.
Las siguientes secciones explicarán cómo sacar partido de estas capacidades - pero a cuando leas esas secciones, recuerda que antes de mostrar una imagen, o tocar música, o declarar un hipervínculo, o lo que sea, debes antes usar glk_gestalt() para comprobar si el intérprete del jugador puede hacer esas cosas. Si no, necesitarás preparar las cosas de forma alternativa - descripciones textuales de las imágenes, ese tipo de cosas - o al menos mostrar un mensaje advirtiendo al jugador de qué capacidades necesitaría en su intérprete para poder jugar tu juego. Idealmente, deberías hacer una llamada a glk_gestalt cada vez que fueras a usar una de las características opcionales de Glk - si solo haces la comprobación en Inicializar, te estás buscando problemas, si por ejemplo, el jugador comienza un juego en su lujoso ordenador de sobremesa, después guarda la partida y la carga de nuevo en su Palm para jugar en el avión más tarde. (Esto no implica necesariamente tener que escrbir un montón de glk_gestalt() - puedes por ejemplo crear una rutina MiDibujarGlk(), que haga las comprobaciones necesarias y después muestre la imagen en la forma que quieras)

Ventanas Glk

Cuando arrancas un intérprete Glulx, que llamaremos "Glulxe" de ahora en adelante, el sistema operativo de tu ordenador reservará un trozo de la pantalla para él. Esto puede ser simplemente una ventana más entre otras, como en Windows o en el Mac; o alternativamente puede ser la pantalla completa, como en DOS, que sólo puede ejecutar un programa de cada vez. Sea como sea, en lo que concierne al juego, el espacio reservado para Glulxe es el mundo completo. El juego no sabe de y ni puede afectar a nada de lo que está fuera del espacio de pantalla de Glulxe. Dentro del espacio de pantalla de Glulxe, al principio, no hay nada. Y no puede ponerse nada allí hasta haber creado una ventana Glk. Una ventana Glk es una porción del espacio de pantalla de Glulxe, que puede mostrar cosas y a veces aceptar input. Hay tres tipos de ventanas que el programador de juegos debe conocer: Los detalles de cómo usar cada uno de estos tipos de ventana serán cubiertos en las secciones siguientes. El resto de esta sección tratará de cómo crear y construir una disposición de ventanas personalizada para tu juego. Hay dos ventanas que son cradas por la librería InformATE automáticamente (aunque esto puede evitarse programando una función llamada InitGlkWindow(), enseguida veremos más sobre esto). La primera ventana es una ventana de buffer de texto, llamada gg_mainwin, que llena todo el espacio de pantalla de Glulxe. Esta ventana es inmediatamente dividida en dos, con una ventana de rejilla de texto llamada gg_statuswin ocupando una línea en la parte superior del espacio de pantalla de Glulxe, y gg_mainwin ocupando el resto. Si quieres añadir más ventanas, lo que tienes que hacer es esto. Primero, decide qué tipo de ventana deberá ser. Quizás quieras un dibujo de un mapa del mundo del juego, visible permanentemente en la pantalla. Esto requeriría una ventana gráfica. Después, piensa un nombre para la ventana. Puedes ponerle cualquiera, pero ya que la librería empieza todos los nombres de ventana con gg_, puedes hacer lo mismo tú tambien. De modo que la llamaremos gg_mapawin. Ahora tienes que elegir un "valor roca" para esta ventana. Este ha de ser un número cualquiera mayor o igual a 210. (Si no sabes qué es un "valor roca", no te desanimes - simplemente elige un número mayor o igual a 210, que no hayas usado ya para otra ventana, y prosigue). Para este ejemplo, elegiremos el 210. El siguiente paso es añadir un par de líneas a tu código. En la zona donde defines constantes, pon esta línea:

Constant GG_MAPAWIN_ROCA 210;

y en tu zona de variables globales, pon esta línea:

Global gg_mapawin = 0;

Con estas líneas añadidas al código, estamos preparados para crear realmente nuestra nueva ventana. La instrucción clave aquí será glk_window_open(). Dentro de los paréntesis van cinco parámetros:

  1. Primero, el nombre de la ventana que hay que partir en dos. En este caso partiremos la ventana principal, así que pondremos gg_mainwin aquí.
  2. Después, el método que queremos usar para partir la ventana. Este es un proceso en dos partes. Primero, necesitarás elegir uno de los siguientes cuatro métodos: Después tienes que elegir una de las opciones siguientes: Junta estas dos elecciones con un signo +. Así, por ejemplo, si queremos que el mapa del juego aparezca a la izquierda del espacio de pantalla de Glulxe, y sabemos que el mapa tiene 240 pixels de ancho, probablemente estaremos inclinados a usar (winmethod_Left+winmethod_Fixed). ¿Dónde va el 240? Vaya, es el...
  3. ...tercer argumento, donde podemos poner: bien el número de líneas o columnas que deben reservarse para la nueva ventana (si es una ventana de texto y se había elegido winmethod_Fixed); o el número de pixels que deben reservarse para la nueva ventana (si es una ventana gráfica y se había elegido winmethod_Fixed); o bien, si habíamos elegido winmethod_Proportional, el porcentaje de la ventana original que queremos reservar para la nueva ventana (por ejemplo, pondríamos 50 si quisiéramos dividir la ventana a la mitad, o 33 si quisiéramos reservar 1/3 del espacio que ocupaba la ventana original para la nueva ventana).
  4. A continuación, ponemos qué tipo de ventana queremos: wintype_TextBuffer para una ventana de tipo buffer de texto, wintype_TextGrid para una ventana de tipo rejilla de texto, o wintype_Graphics para una ventana gráfica. En este ejemplo, queremos el último caso.
  5. El último elemento de la lista es la constante que has declarado antes. En nuestro ejemplo, sería GG_MAPAWIN_ROCA
Esto nos deja la siguiente llamada:

gg_mapawin = glk_window_open(gg_mainwin,
                (winmethod_Left+winmethod_Fixed), 240, 
                 wintype_Graphics, GG_MAPAWIN_ROCA); 

Por supuesto, soltar una línea como esta en mitad de tu programa, es una mala idea. Hay que comprobar una serie de cosas antes. Para empezar, antes de abrir una ventana debes estar seguro de que la ventana no está ya abierta. ¿Cómo podría estarlo? Quizás el jugador acaba de restaurar una partida guardada (lo que no restaura automáticamente la configuración de ventanas que había en el momento de guardar la partida, esto tenes que hacerlo tú. Cómo hacer esto se explicará en breve). Así que envolvamos la línea en una condición:

if (gg_mapawin == 0) { 
  gg_mapawin = glk_window_open(gg_mainwin,
                   (winmethod_Left+winmethod_Fixed), 240, 
                    wintype_Graphics, GG_MAPAWIN_ROCA); 
  }  

Otra cosa a tener en cuenta, es que sólo porque hayas pedido que se abra una ventna, eso no significa que realmente se haya abierto. El jugador podría estar usando un intérprete que no soporta gráficos, por ejemplo, en cuyo caso tu intento de crear una ventana gráfica estará condenado al fracaso. O puede que el intérprete soporte gráficos, pero que el jugador haya reducido la zona de pantalla de Glulxe a menos de 240 pixels de ancho, por lo que la ventana que obtienes no es exactamente la que habías pedido. Deberías comprobar estas cosas; pero lo que hagas con los resultados de las comprobaciones queda a tu criterio. Por ejemplo, si tu juego es incomprensible sin el gráfico, entonces deberías comprobar si tu ventana gráfica realmente se ha abierto (con un test del tipo "if (gg_mapawin == 0)" y, si no se abrió, imprimir un mensaje como "Este juego necesita un intérprete capaz de mostrar gráficos. ¡Lo siento!" y finalizar el juego. Pero si el gráfico no es más que un añadido sin importancia, entonces podrías querer que el juego prosiguiera, pero en ese caso asegúrate de que no intentas nunca hacer un glk_image_draw() para poner una imagen en esa (inexistente) ventana - comprueba si la ventana es cero cada vez. Para cerrar una ventana, usa el comando glk_window_close(). Esta rutina necesita en realidad dos argumentos. El primero es el nombre de la ventana a cerrar. El segundo es extremadamente esotérico; si simplemente pones 0, todo irá bien.

Estilos de texto

Como hemos dicho antes, aquellos que quieran compilar sus juegos (preexistentes en forma de código fuente Inform) para GLulx, tienen que asegurarse de haber reemplazado cualquier instrucción de ensamblador Z, por ensamblador Glulx (o llamar a rutinas de Inform Glulx que hagan lo que antes hacía con el ensamblador Z). El otro cambio importante que los programadores de juegos necesitarán hacer es reemplazar cualquier comando como style bold; y style underline; - Glulx no los reconoce. En su lugar, tienes que poner llamadas a los cambios de estilo Inform Glulx. Las llamadas Inform Glulx para cambios de estilo son muy similares a los cambios de estilo del Inform clásico. Usas el comando glk_set_style() con el estilo que quieres aplicar dentro de los paréntesis, y todo el texto que imprimas después de eso aparecerá en el estilo especificado. No hay forma de "desactivar" un estilo, como se haría en HTML con sus tags </estilo> - para volver a imprimir texto normal, simplemente inserta la línea glk_set_style(style_Normal);. Otras posibilidades son: Pero exactamente ¿qué aspecto tienen todos estos estilos? Varía con cada intérprete. style_Emphasized puede ser negrita, o cursiva, o simplemente de un color más brillante. Sin embargo el programador puede hacer sugerencias con respecto a varios aspectos de un estilo dado (incluyendo dos estilos que se dejan para que el propio programador los defina: style_User1 y style_User2). Algunos intérpretes harán caso de estas sugerencias; otros no. (Y algunos incluso les harán caso pero de forma incorrecta: la versión de Glulxe para DOS basada en Allegro, actuelmente pone los colores de fondo y letra al revés) De momento, no hay un gestalt_StyleHints o algo asi que pueda servir para saber si nuestras sugerencias son atendidas o ignoradas. Pero si crees que tendrás suerte, usa la rutina glk_stylehint_set(), que requiere los siguientes cuatro parámetros:
  1. El tipo de ventana sobre la que debe aplicarse esta sugerencia de estilo. Las opciones son wintype_TextBuffer, wintype_TextGrid o wintype_AllTypes (pero no wintype_Graphics, puesto que no puedes imprimir texto en una ventana gráfica).
  2. El estilo al que se aplica esta sugerencia de estilo.
  3. El aspecto del estilo que se quiere cambiar (la lista de ellos se verá en breve).
  4. El número o constante que indica qué se cambia en ese estilo y cómo.
El significado del cuarto argumento varía drásticamente dependiendo de lo que el tercer argumento indique. Así, "1" puede significar: "indentar el texto un poco", "negrita", "prácticamente negro" u otras cosas, según el contexto. Por tanto, el tercer y el cuarto argumento no deben ser tratados separadamente, sino en tándem. He aquí una tabla de las combinaciones que se admiten:
Aspecto (3er argumento) Valor (4o argumento)
stylehint_Indentation Aquí debe ir un número que significa "mueve el siguiente trozo de texto tantas unidades a la derecha" (un valor negativo lo mueve hacia la izquierda). ¿Cuánto es una unidad? Depende del intérprete.
stylehint_ParaIndentation Esto es como el anterior, pero sólo afecta a la primera línea de cada párrafo.
stylehint_Justification Aquí puede ir una de las siguientes constantes: stylehint_just_LeftFlush (justificación a la izquierda), stylehint_just_RightFlush (justificación a la derecha), stylehint_just_LeftRight (justificación completa) o stylehint_just_Centered (centrada).
stylehint_Size Aquí hay que poner un número, pero no un número absoluto, como el tamaño en puntos, sino relativo. 0 significa "el tamaño por defecto", los valores positivos incrementan el tamaño una cierta cantidad, y los negativos lo decrementan. Los incrementos no son necesariamente de la misma magnitud: si 0 es 12 puntos, y +1 es 14 puntos, +2 puede ser 18 puntos.
stylehint_Weight 0=normal, 1=negrita, -1 = ligera.
stylehint_Oblique 0=no cursiva, 1=cursiva.
stylehint_Proportional 0=usar fuente de ancho fijo (tipo courier), 1=fuente de ancho proporcional
stylehint_TextColor Este debe ser un número de 32 bits que representa el color usado. Es mucho más fácil, con diferencia, si escribimos el número en hexadecimal nota3.html, lo que se hace en la forma siguiente. Primero, escribe el signo dolar (que indica a Inform que lo que sigue es un número hexadecimal). Después escribe un número hexadecimal de dos cifras, de 00 a FF, que representa la cantidad de rojo presente en el color. Después viene otro número de dos dígitos hexadecimales que representa la cantidad de verde, y finalmente otro número de dos dígitos hexadecimales que representa la cantidad de azul. Así, $000000 sería el negro, y $FFFFFF sería el blanco, $FF0000 sería un rojo intenso, $FFC000 sería un bonito dorado, $C0C0FF un azul bebé, etcétera.
stylehint_BackColor Aquí va un número de 32 bits, exactamente como el anterior, sólo que en esta ocasión estás seleccionando el color del "papel" detrás del texto. Sin embargo, éste no es el color de fondo de la ventana, y los resultados serán extremadamente horribles en algunos intérpretes (screen.gif). Actualmente no hay sugerencia de estilo para cambiar el color de fondo la ventana; con suerte, se le añadirá sin tardar mucho.
stylehint_Reverse 0=imprimir normalmente, 1=imprimir el texto usando el color del fondo, y viceversa.
Así que, juntándolo todo, pongamos que quieres definir el estilo "User1" como texto rojo sobre un fondo negro. Esto se lograría con el código siguiente:

glk_stylehint_set(wintype_TextBuffer, style_User1,
                  stylehint_TextColor, $FF0000); 
glk_stylehint_set(wintype_TextBuffer, style_User1, 
                  stylehint_BackColor, $000000); 

Sin embargo, las sugerencias de estilo sólo afectan a las ventanas que se crean a partir de entonces. Esto significa que si quieres usarlas, debes hacerlo antes de crear la ventana en la que quieres que se usen. Y puesto que la ventana gg_mainwin es creada por la libreria, si quieres que las sugerencias de estilo tengan efecto sobre la ventana principal del juego, ponerlas en Inicializar sería demasiado tarde - necesitas programar una rutina llamada InitGlkWindow(). Esta rutina es llamada desde la librería varias veces, y le pasa diferentes valores cada vez. En este caso, tienes que ejecutar tus sugerencias de estilo cuando el valor recibido sea igual al valor "roca" de gg_mainwin, así:

[ InitGlkWindow winrock; 
  switch (winrock) { 
     GG_MAINWIN_ROCK:
         glk_stylehint_set(wintype_TextBuffer, style_User1,
                           stylehint_TextColor, $FF0000); 
         glk_stylehint_set(wintype_TextBuffer, style_User1, 
                           stylehint_BackColor, $000000); 
     } 
  rfalse; ! si te olvidas esta linea, el juego no funcionará bien
];

Una última observación antes de proseguir. Podría parecerte que un código como este:

  print "Te he dicho que la violencia ";
  glk_set_style(style_Emphasized);
  print "no";
  glk_set_style(style_Normal);
  print " es la solución en este caso.";

es poco manejable. Lo es. Por otro lado no es mucho peor que:

  print "Te he dicho que la violencia ";
  style bold;
  print "no";
  style roman;
  print " es la solución en este caso.";

Por esto muchos programadores usan pequeñas rutinas para hacer todo esto más amigable. No es necesario escribir style_Emphasized un ciento de veces; algo como esto, lo haría perfectamente:

[ b texto;
  glk_set_style(style_Emphasized);
  print (string) texto;
  glk_set_style(style_Normal);
]

Y una vez que has creado esa rutina, puedes escribir el ejemplo de antes de esta otra forma:

   print "Te he dicho que la violencia ", (b) "no", 
         " es la solución en este caso.";
 

Líneas de estado

Uno de los usos más comunes del ensamblador-Z dentro de un juego Inform es el de crear líneas de estado personalizadas. Éstas no funcionarán con Inform Glulx, puesto que no reconoce el ensamblador-Z. En su lugar, tendrás que usar las llamadas a Glk equivalentes - que no son opcodes, sino más bien rutinas como cualquier otra. La línea de estado es una tradición tan arraigada dentro de las ACs (sobre todo inglesas) que cuesta realmente un poco deshacerse de ella. Un juego Inform estándar reservará una parte de la pantalla para mostrar el nombre de la localidad en la que se halla el jugador, la puntuación actual, y el número de movimientos realizados. Para cambiar esto, el programador debe insertar la línea "Replace DibujarLineaEstado;" al comienzo del programa (también vale si lo pones justo después de las constantes, en realidad, es suficiente que aparezca antes del primer Include). Después, el programador debe proporcionar una rutina DibujarLineaEstado alternativa. Pero aquí es donde las cosas divergen un poco. En Inform estándar, el comando para crear la ventana de la línea de estado (@split_line) se hacía dentro de la rutina DibujarLineaEstado de la librería. Si quieres reemplazar ésta, tienes que poner el comando @split_window en la tuya. Si quieres eliminar la línea de estado, todo lo que necesitarás hacer es reemplazar DibujarLineaEstado por una rutina vacía, como esta:

[ DibujarLineaEstado; ];

Esto ya no es suficiente en Glulx Inform. En la sección Glulx de InformATE biplataforma, la ventana para la línea de estado es creada en la rutina GGInitialise, no en DibujarLineaEstado. Esto significa que si te limitas a usar una DibujarLineaEstado vacía, la línea de estado saldrá vacía, pero aún estará ahi, burlándose de tí. De modo que lo que tienes que hacer es interceptar el comando que crea la ventana de estado, mediante una programación de la rutina InitGlkWindow como la siguiente:

[ InitGlkWindow winrock;
   switch (winrock) {
      GG_STATUSWIN_ROCK: rtrue;
   }
   rfalse; ! si olvidas esta línea el programa no funcionará
];

Si quieres mantener la línea de estado, pero configurar a tu gusto la información que se muestra en ella, he aqui algunos consejos. Lo primero, si quieres reservar más de una línea para la ventana de estado, debes hacerlo en InitGlkWindow, como aqui:

[ InitGlkWindow winrock;
   switch (winrock) {
      GG_STATUSWIN_ROCK:
         gg_statuswin_size = 2; ! el número de líneas que desees
   }
   rfalse; ! si olvidas esta línea el programa no funcionará
];

Después, al escribir tu propia DibujarLineaEstado, debes comenzar con el código siguiente:

   ! Si no hay ventana de estado, no hay que redibujarla
   if (gg_statuswin == 0)
      return;    ! Si no hay localización, tampoco
   if (localizacion == nothing || parent(jugador) == nothing)
      return;

La primera línea después de eso, debe ser glk_set_window(gg_statuswin); para cambiar a la ventana en la cual estás a punto de imprimir información de estado, y la última línea debe ser glk_set_window(gg_mainwin); para asegurarte de que el programa continuará imprimiendo el texto del juego en el lugar correcto. En el medio, puedes imprimir cualquier cosa, si bien el procedimiento para ello es ligeramente diferente al usado en una ventana de tipo buffer de texto. Recuerda que una ventana tipo rejilla de texto es una especie de tablero de Scrabble: aunque no se ven las líneas separando las casillas, la ventana consiste en una rejilla de casillas, cada una de las cuales puede contener un carácter - letra, número o puntuación. Cada casilla tiene un par de coordenadas asociadas, una coordenada X y una coordenada Y. La coordenada X es cuántas casillas hay antes de ella contando desde el borde izquierdo; la coordenada X de la primera casilla (junto al borde izquierdo) es 0. La coordenada Y es cuántas casillas hay por encima de la casilla actual, hasta el borde superior; la coordenada Y de las casillas superiores es 0. (Esto es diferente al Inform estándar, en el que la esquina superior izquierda no era (0,0), sino (1,1)). Para seleccionar el lugar donde quieres comenzar a escribir, usa la orden glk_window_move_cursor(), que necesita tres argumentos: el nombre de la ventana donde imprimirás, la coordenada X de la casilla en la que quieres que comience a imprimir, y la coordenada Y de esa casilla. Cuando imprimas, el cursor irá avanzando automáticamente hacia la derecha para cada letra del texto impreso - no necesitas moverlo para imprimir la siguiente letra de una palabra. Así que el código siguiente:

   glk_window_move_cursor(gg_statuswin, 3, 0);
   print "Hora: ";

colocará la letra "H" en la posición (3,0), la "o" en (4,0), "r" en (5,0), "a" en (6,0), dos puntos en (7,0) y un espacio en (8,0), dejando el cursor en (9,0). Presumiblemente después iría el código para imprimir la hora. Una cosa a tener en cuenta es que no todo el mundo que juegue tu juego tendrá la misma cantidad de espacio de pantalla reservado para Glulxe: la línea de estado puede tener espacio para 120 letras en el ordenador de una persona, y 40 en el de otra. O alguien puede cambiar de tamaño la ventana Glulxe, y el ancho cambiar de 120 a 40 en mitad del juego. Puedes programar la rutina DibujarLineaEstado para que tenga esto en cuenta (como de hecho se hace en la DibujarLineaEstado que viene con InformATE). Simplemente añade variables llamadas ancho y alto en la declaración de DibujarLineaEstado, e inserta el siguiente fragmento de código en tu rutina:

glk_window_get_size(gg_statuswin, gg_arguments, gg_arguments+4);
ancho = gg_arguments-->0;
alto = gg_arguments-->1;

Y después puedes hacer los ajustes que estimes oportuno. Digamos que estás haciendo un juego llamado Tritura, Machaca y Pisotea y quieres poner un indicador de hambre en la línea de estado, comenzando en la columna 40, que debe mostrar una de las palabras "HARTO", "SATISFECHO", "HAMBRIENTO", "FAMELICO". Esto podría llevarte hasta la columna 50. Puede que algunos jugadores estén jugando con menos de 50 columnas, y en ese caso prefieres que no se muestre este indicador (porque lo que desde luego no quieres es que aparezca incompleto, a mitad de una palabra). Usarías un código como el siguiente:

   if (ancho > 50) { ! Nos aseguramos de tener sitio
      glk_window_move_cursor(gg_statuswin, 40, 0);
      switch (gojira.hambre) {
         0: print "HARTO";    
         1: print "SATISFECHO"; 
         2: print "HAMBRIENTO";
         3: print "FAMELICO";
      }
   }

Observa que las cuatro palabras anteriores tienen diferentes longitudes. Si intentas sobreescribir "SATISFECHO" con "HARTO", obtendrás "HARTOFECHO", a menos que, o bien rellenes con espacios a la derecha cada palabra, o pongas un glk_window_clear(gg_statuswin); justo después de tu llamada a glk_set_window(gg_statuswin);. La librería InformATE usa este segundo método. Se pueden hacer acomodos más inteligentes que simplemente el no mostrar los elementos que no caben - podíamos haber puesto algún código elaborado para abreviar las cosas a medida que la línea de estado es más pequeña, por ejemplo. Lo bueno es que, ya que DibujarLineaEstado es llamada en cada turno, no necesitas andar tocando HandleGlkEvent para manejar los cambios de tamaño, como es necesario hacer con los gráficos. Más sobre esto en las secciones siguientes.


GráficosContenidosGlulx e Inform Glulx Cómo hacer cosas con Glulx Inform