| | | Cómo hacer cosas con Glulx Inform |
Cómo hacer cosas con Glulx Inform
Para compilar un juego con Inform Glulx, necesitarás lo siguiente:
Y para ejecutar el programa que has compilado, necesitarás:
- Un intérprete Glulx para tu plataforma, cuyo nombre será
probablemente una variación de "glulxe" (la "e" final es de
"ejecutar").
- Una versión de las librerías Glk para tu plataforma, que
proporciona al intérprete los recursos que necesita para correr.
Y si quieres incluir sonido o gráficos en tu juego, aún necesitas otra
cosa más: Blorb ¿Qué es eso? Sigue leyendo...
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:
- Un fichero de "recursos blorb" (básicamente es una lista de
qué ficheros quieres empaquetar juntos)
- Las imágenes y/o sonidos que usas
- El código fuente de tu juego Inform y las librerías que
requiera.
- Un compilador de Inform Glulx para tu plataforma
- Un blorbificador para tu plataforma
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.
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)
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:
- Ventanas de buffer de texto. Este tipo de ventanas
muestra texto, e incluso imágenes, pero lo hace en una forma de
"flujo" (stream). Esto es, cuando el juego le dice a la
ventana "imprime esta frase" o "muestra esta imagen", la frase o
la imagen son colocados justo después del texto o imágenes que
hubiera ya en esa ventana. Cuando la ventana de buffer de texto se
llena, el material más antiguo se desliza hacia arriba y desaparece
de la vista; en algunos intérpretes este material desaparece de la
pantalla para siempre, mientras que otros pueden proporcionar una
barra de desplazamiento que te permita retroceder páginas y ver
parte de lo que ha desaparecido. La ventana donde los jugadores
teclean sus comandos será normalmente una ventana de tipo buffer de
texto, salvo en los casos más excéntricos.
- Ventanas de rejilla de texto Este tipo de ventanas
también muestran texto, pero lo hacen en una forma diferente a las
ventanas de buffer de texto. Las ventanas de rejilla de texto
permiten al programador colocar los caracteres donde él quiera, como
si colocara fichas de Scrabble en el tablero. Esto las hace ideales
para el caso en que quieras sobreescribir información vieja, como en
la línea de estado que usan la mayoría de los juegos. Las ventanas
de rejilla de texto pueden aceptar entrada desde el teclado-
flechas arriba y abajo para mover la elección en un menú, por
ejemplo - pero intentar algo más avanzado requeriría manipular un
poco la librería.
- Ventanas gráficas. Este tipo de ventana no puede
mostrar texto en absoluto, pero a cambio permiten al programador
mostrar imágenes (en formato JPEG o PNG) que no "deslizarán" hacia
arriba a medida que el juego progrese. El programador puede incluso
crear sus propias imágenes usando los comandos de dibujo de Inform
Glulx, si tiene la paciencia necesaria. Las ventanas gráficas no
pueden aceptar entrada desde el teclado, pero pueden reconocer las
pulsaciones del ratón (una interesante capacidad, que comparten con
las ventanas de tipo rejilla de texto).
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:
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:
- 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í.
- 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:
winmethod_Above
: divide la ventana en dos partes, una encima
de otra, y la nueva ventana será la parte superior (en inglés,
above es "encima")
winmethod_Below
: divide la ventana en dos partes, una encima
de otra, y la nueva ventana será la parte inferior (en inglés,
below es "debajo")
winmethod_Left
: divide la ventana en dos pates, una al lado
de la otra, y la nueva ventna será la parte de la izquierda
(left en inglés)
winmethod_Right
:divide la ventana en dos pates, una al lado
de la otra, y la nueva ventna será la parte de la derecha
(right en inglés)
Después tienes que elegir una de las opciones siguientes:
winmethod_Fixed
: reserva un cierto número de líneas o
columnas (para las ventanas tipo texto), o de pixels (para las
ventanas gráficas) para la nueva ventana.
winmethod_Proportional
: reserva un cierto porcentaja de la
ventana original para la nueva ventana.
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...
- ...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).
- 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.
- 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.
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:
style_Emphasized
: para texto resaltado.
style_Preformatted
: para dibujar cosas a base de letras, como
tablas o cualquier otra cosa que requiera una disposición de
caracteres de ancho fijo (courier).
style_Header
: para dar título a secciones largas (por ejemplo,
"ACTO PRIMERO")
style_Subheader
: para dar título a secciones más pequeñas,
dentro de las secciones largas antes mencionadas (ej, "Escena I")
style_Alert
: para anuncios muy importantes (ej, "*** Has
muerto ***")
style_Note
: para anuncios menos importantes (ej, "[Tu
puntuación ha aumentado en 4 puntos.]")
style_BlockQuote
: para citas y similares
style_Input
: para el texto que el jugador escriba.
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:
- 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).
- El estilo al que se aplica esta sugerencia de estilo.
- El aspecto del estilo que se quiere cambiar (la lista de ellos
se verá en breve).
- 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.";
|
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:
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.
| | | Cómo hacer cosas con Glulx Inform |