CAAD

Comunidad de Aventuras Conversacionales y Relatos Interactivos
Fecha actual 11 Jul 2020 06:49

Todos los horarios son UTC + 1 hora




Nuevo tema Responder al tema  [ 16 mensajes ]  Ir a página 1, 2  Siguiente
Autor Mensaje
NotaPublicado: 08 Mar 2006 22:06 
Desconectado
Samudio
Samudio
Avatar de Usuario

Registrado: 10 Sep 2004 00:17
Mensajes: 3069
Ubicación: Chile
Saludos:

Para mi AC en desarrollo "Goteras" necesito crear un objeto del jugador (un reloj digital) que en tiempo real haga una cuenta regresiva de 1 hora.

La idea es:

-> Poder leer el reloj en formato HH:MM:SS (los segundos, si se puede)
-> Poder imprimir el estado del reloj como texto de salida en otro objeto en formato HH:MM:SS (los segundos, si se puede)
-> Gatillar eventos según decrece el tiempo (a los 10 min algo, a los 20 otra cosa, etc. y, por supuesto, un evento importante cuando se acabe la hora de tiempo)
-> Poder parar la cuenta regresiva si ocurren algunos eventos.

Casi nada, ¿no? :P

Entiendo que la cosa va por las librerías "Relojes.h" o "RTimex.h" pero la verda es que no entendí mucho cómo usarlas... :oops:

Se despide, de antemano agradecido,

_________________
[Incanus]
El Escritorio - Blog Aventurero y Literario


Arriba
 Perfil  
 
NotaPublicado: 09 Mar 2006 00:10 
Desconectado
Implementador
Implementador
Avatar de Usuario

Registrado: 10 Mar 2004 21:40
Mensajes: 1444
Ubicación: Nímgar, Ciudad Lunar
Incanus escribió:
Saludos:

Para mi AC en desarrollo "Goteras" necesito crear un objeto del jugador (un reloj digital) que en tiempo real haga una cuenta regresiva de 1 hora.

La idea es:

-> Poder leer el reloj en formato HH:MM:SS (los segundos, si se puede)
-> Poder imprimir el estado del reloj como texto de salida en otro objeto en formato HH:MM:SS (los segundos, si se puede)
-> Gatillar eventos según decrece el tiempo (a los 10 min algo, a los 20 otra cosa, etc. y, por supuesto, un evento importante cuando se acabe la hora de tiempo)
-> Poder parar la cuenta regresiva si ocurren algunos eventos.

Casi nada, ¿no? :P

Entiendo que la cosa va por las librerías "Relojes.h" o "RTimex.h" pero la verda es que no entendí mucho cómo usarlas... :oops:

Se despide, de antemano agradecido,


Relojes.h no está pensada para trabajar en tiempo real...

Es que las cosas en tiempo real...

:(

Pero se puede usar, si defines un reloj digital y sustituyes 'miHora' por lo que quieras...

RelojDigital RelojDigialPrueba "reloj digital"
with
nombre 'reloj' 'digital',
descripcionSinHora "Un reloj digital.",
valorHora 0,
miHora [; return valorHora; ];

Faltaría ahora cambiar 'valorHora' mediante RTimeX.

Lamentablemente no hay documentación ni ejemplos adecuados de esa librería en el kit... y yo nunca la he usado así que doy paso a alguien que sepa usarla.

La idea sería colocar un valor adecuado en valorHora y que el demonio de RTimeX permita el arranque de un demonio 'director de juego' que verifique tus eventos y vaya variando el contenido de 'valorHora'. La librería de Relojes se encargaría de mostrar la 'hora' en el formato que quieras.

Lamentablemente no puedes usar los planificadores de Relojes.h porque no les puse un 'miHora' a los planificadores y usan 'la_hora' directamente... pero no es muy difícil de cambiar...

:)

http://www.terra.es/personal/mel-hyth/Relojes.zip

Ahí tienes una nueva versión en el que los planificadores tienen un miHora, que puede cambiarse para lo que necesites...


Arriba
 Perfil  
 
NotaPublicado: 09 Mar 2006 03:09 
Desconectado
Grafista
Grafista

Registrado: 09 Mar 2004 17:20
Mensajes: 504
Incanus escribió:
Entiendo que la cosa va por las librerías "Relojes.h" o "RTimex.h" pero la verda es que no entendí mucho cómo usarlas... :oops:


Eeer, respuesta corta... ¡¡¡No, tu no quieres hacer eso!!!! :P

Bueeeno, respuesta menos corta... sí, vale,sí lo quieres hacer... así que hazlo en un ejecutable para Windows de cualquier lenguaje de programación que se te de bien y pueda manejar tiempo real... Así al menos el resultado se parecerá a lo que quieres !!! :wink:

Vaaale, vaaaale, vamos con la respuesta larga... XDD

La máquina Z no sabe ni quiere saber nada de tiempo real... OK, es mentira, sí que sabe. Según el intérprete, puede saber contar en décimas de segundo durante, y sólo durante, el tiempo que está en espera de un input del jugador. ¡Bien! ya tenemos algo a lo que agarrarnos. ¿Cómo lo hace? Pueees, la cosa es que la sentencia de ensamblador @aread está preparada para llamar a cualquier rutina que le indiquemos cada determinada cantidad de décimas de segundo que le señalemos.

Esto es lo que hace la librería Rtimex (sustituyendo el grueso del código de Eparser.h que se encarga de leer el teclado por su versión del mismo)... además de organizar la pantalla como a ella le gusta y varias lindezas más... ¿Estas obligado a tragar con ello? ¡No! ¡Tú puedes hacerlo a tu manera!

Básicamente, creemos un objeto reloj que podría parecerse a esto:

Código:
Objeto reloj "reloj"
with
nombre 'reloj',
horas 0,
minutos 0,
segundos 0,
descripcion
[;
   print self.horas,":",self.minutos,":",self.segundos;
];


(la hora está sin formatear, en tus manos queda ponerla "bonita" :) )

Indiquemosle al compilador que vamos a sustituir la rutina KeyboardPrimitive de Eparser.h por una versión nuestra con el correspondiente "Replace" antes de los includes habituales

Código:
Replace KeyboardPrimitive;


Y ¿con qué lo vamos a sustituir? pues con algo similar a:

Código:
[KeyboardPrimitive b p k;

   b ->1=0; !esto es un salvavidas, no preguntes :-)
   p ->1=0; !Idem que el anterior

   @aread b p 10 tiempo ->k;
   
   !la sentencia anterior lee un input del teclado,
   !llamando a la función "tiempo" cada 10 décimas
   !de segundo, o sea, un segundo   8)
];


Y ¿qué podría haber en esa función "tiempo"? Pues... ¡lo que tu quieras! pero podría parecerse a:

Código:
[tiempo;

   !un contador bastante burdo de segundos,
   !minutos y horas. Además en vez de descontar
   !el tiempo, lo aumenta, pero puedes hacerlo
   !al revés o como quieras. También puedes
        !hacer que la rutina retorne sin actualizar
        !los valores si se da alguna condición, en cuyo caso, recuerda
   !volver con rfalse (¡es importante!)

   reloj.segundos ++;
   if (reloj.segundos>59)
   {
      reloj.minutos ++;
      reloj.segundos=0;
   }
   if (reloj.minutos>59)
   {
      reloj.horas ++;
      reloj.minutos=0;
   }
   if (reloj.horas>23) reloj.horas=0;

   rfalse;

   !el rfalse es vital, prueba a quitarlo y verás
   !XDDD
   
];


Y una vez que hubieras hecho todo esto... pues ya sólo tienes que consultar desde un reloj, o un daemon, o desde una propiedad "cada_turno"... lo que mejor te parezca, el valor de horas-minutos-segundos y desencadenar los acontecimientos que consideres oportunos -incluyendo un fin de juego horrible y cruel :o

En el mejor de los casos el resultado será... impreciso (ejem) y al igual que Rtimex, esto sólo vale para máquina Z, en Glulx la maniobra es completamente diferente, si eso mañana le echamos un vistazo (ahora la cama me espera impaciente :wink: )


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 09 Mar 2006 07:48 
Desconectado
Semimomio
Semimomio
Avatar de Usuario

Registrado: 15 Dic 2004 21:28
Mensajes: 2302
Hay otro tema a tener en cuenta, y es el manejo de la pantalla, realmente quedaría incómodo y feo que mientras el jugador está escribiendo una orden de repente al saltar un evento saque algún texto que desbarate lo que el jugador intenta escribir.


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 09 Mar 2006 10:18 
Desconectado
Grafista
Grafista

Registrado: 09 Mar 2004 17:20
Mensajes: 504
presi escribió:
Hay otro tema a tener en cuenta, y es el manejo de la pantalla, realmente quedaría incómodo y feo que mientras el jugador está escribiendo una orden de repente al saltar un evento saque algún texto que desbarate lo que el jugador intenta escribir.


¡Eeexacto! :) por eso fijaos en que me he cuidado muy mucho de que la rutina llamada durante la espera de teclado (en mi ejemplo llamada "tiempo") se limite a contar segundos (también podría "no contarlos" dependiendo de alguna condición, como Incanus sugería para "detener" la cuenta atrás o lo que fuera) y retornar false, es decir, no interferir con el desarrollo normal de la rutina de introducción de texto, y he indicado expresamente que cualquier decisión, mensaje, evento, lo que fuera... se tome desde fuera de esta consultando los valores actualizados de las propiedades de, en mi ejemplo, el objeto reloj.

Esto a la larga añade una dosis adicional de "imprecisión" pero es una vacuna eficaz contra corrupciones inesperadas de pantalla u otras formas de caos imprevistas.

Otra manera de prevenir esa posibilidad es la abordada por RTimex, que viene a ser curarse en salud a base de "scottadamizar" (yo me entiendo, yo me entiendo XDD) el juego separando el input del jugador en una ventana (concretamente la que sería normalmente la de la barra de estado) y el texto de la aventura en otra. Una decisión, en mi humilde opinión, demasiado drástica para que la tome la librería en lugar del autor, pero, en cualquier caso, eficaz también para prevenir corrupciones de pantalla por repentina invasión de textos en el momento y lugar inadecuados.

Más detalles en las pags 316-17 del manual inglés y en sus ejercicios (cap 42, "Devices and Opcodes") más o menos por http://www.inform-fiction.org/manual/html/s42.html#p326 y en la FAQ de Roger firth en http://www.firthworks.com/roger/informfaq/tt.html#5


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 09 Mar 2006 11:15 
Desconectado
Semimomio
Semimomio
Avatar de Usuario

Registrado: 15 Dic 2004 21:28
Mensajes: 2302
Radio Marte Libre escribió:
presi escribió:
Hay otro tema a tener en cuenta, y es el manejo de la pantalla, realmente quedaría incómodo y feo que mientras el jugador está escribiendo una orden de repente al saltar un evento saque algún texto que desbarate lo que el jugador intenta escribir.


¡Eeexacto! :) por eso fijaos en que me he cuidado muy mucho de que la rutina llamada durante la espera de teclado (en mi ejemplo llamada "tiempo") se limite a contar segundos (también podría "no contarlos" dependiendo de alguna condición, como Incanus sugería para "detener" la cuenta atrás o lo que fuera) y retornar false, es decir, no interferir con el desarrollo normal de la rutina de introducción de texto, y he indicado expresamente que cualquier decisión, mensaje, evento, lo que fuera... se tome desde fuera de esta consultando los valores actualizados de las propiedades de, en mi ejemplo, el objeto reloj.

Esto a la larga añade una dosis adicional de "imprecisión" pero es una vacuna eficaz contra corrupciones inesperadas de pantalla u otras formas de caos imprevistas.


Sí, pero eso solo sirve si queremos tener un cronómetro pasivo, es decir que sólo moleste cuando nosotros queramos: cuando lo miremos para saber el tiempo, cuando le apretemos un botón o lo que sea.

Pero en cambio no sirve para uno de los requisitos de Incanus que era que se produjera algún evento síncrono a cierto tiempo, por ejemplo un aviso a los 20 minutos o la inevitable y dantesca muerte si el cronómetro llega a 0, con la solución que propones, ese evento se produciría, como pronto, después del retorno del read, y eso supone que si el jugador se está 2 horas (por ejemplo) sin darle al enter, el evento se producirá entonces y no en el tiempo real requerido.


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 09 Mar 2006 12:31 
Desconectado
Grafista
Grafista

Registrado: 09 Mar 2004 17:20
Mensajes: 504
presi escribió:
Sí, pero eso solo sirve si queremos tener un cronómetro pasivo, es decir que sólo moleste cuando nosotros queramos: cuando lo miremos para saber el tiempo, cuando le apretemos un botón o lo que sea.

Pero en cambio no sirve para uno de los requisitos de Incanus que era que se produjera algún evento síncrono a cierto tiempo, por ejemplo un aviso a los 20 minutos o la inevitable y dantesca muerte si el cronómetro llega a 0, con la solución que propones, ese evento se produciría, como pronto, después del retorno del read, y eso supone que si el jugador se está 2 horas (por ejemplo) sin darle al enter, el evento se producirá entonces y no en el tiempo real requerido.


Eeeexacto! :) Al fin y al cabo se trata precisamente de eso, de que "moleste cuando queramos" y no "cuando no queramos" XDD y de todos modos iba a dar lo mismo. Cuando se pulsase enter la comprobación que se hubiese programado detectaría el paso del tiempo y tomaría las decisiones pertinentes tanto si se han tardado dos horas como si han sido 2, 10, o 20 segundos, el resultado sería el mismo.

Ahora que si queremos tiempo real 100% nos comemos las interferencias de textos inoportunos... o no.

La única alternativa conocida hasta la fecha a retornar false es... retornar true (¡bravo genio! XDD) pero si vuelves hacia el aread con true... te lanzas de cabeza hacia las entrañas de Eparser sin red y sin saber muy bien donde podrías aparecer (como decía arriba, quita el rfalse y diviertete un rato XDD)... a no ser que el programador decida una acción por defecto a asumir en esa situación y la tokenize él mismo a mano (en los ejercicios de la página del manual que enlazaba antes hay un ejemplo de ello) pero... la verdad... Incanus es buena gente, yo no le metería en semejante pitote!!! Sí, ya se que el tema tiene muy mal color, pero eso es lo que hay.

Ahora que si es cuestión de meternos en el berenjenal, pues nos metemos! :o


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 09 Mar 2006 13:22 
Desconectado
Semimomio
Semimomio
Avatar de Usuario

Registrado: 15 Dic 2004 21:28
Mensajes: 2302
Radio Marte Libre escribió:
La única alternativa conocida hasta la fecha a retornar false es... retornar true (¡bravo genio! XDD) pero si vuelves hacia el aread con true... te lanzas de cabeza hacia las entrañas de Eparser sin red y sin saber muy bien donde podrías aparecer (como decía arriba, quita el rfalse y diviertete un rato XDD)... a no ser que el programador decida una acción por defecto a asumir en esa situación y la tokenize él mismo a mano (en los ejercicios de la página del manual que enlazaba antes hay un ejemplo de ello) pero... la verdad... Incanus es buena gente, yo no le metería en semejante pitote!!! Sí, ya se que el tema tiene muy mal color, pero eso es lo que hay.

Ahora que si es cuestión de meternos en el berenjenal, pues nos metemos! :o


¿Y la solución de RtimeX y sus ventanas scottadamianas no nos valdría en este caso con la ventaja de que solo nos metemos en un poco del berenjenal, no en el berenjenal al completo?

¿O me he perdido y el ejercicio se trataba de hacerlo sin usar librerías? :D


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 09 Mar 2006 14:50 
Desconectado
Grafista
Grafista
Avatar de Usuario

Registrado: 15 Ene 2005 22:26
Mensajes: 780
Hola! El tiempo real!!! Un año solar, un pestañeo para la gran montaña, ciento de generaciones para aquella mariposa posada en mi monitor, seis materias y una novia para este humilde servidor.

¿Qué me dices del tiempo real en Glulx?

Retomando los símbolos de RML....
Código:
[ Inicializar;
   localizacion = habitacion_inicial;
 
   if (~~glk_gestalt(gestalt_Timer, 0)) {
      print "^¡Este intérprete no soporta tiempo real! Para jugar
           necesitas uno que lo soporte.^";
      KeyCharPrimitive();
      quit;
   }
  glk_request_timer_events(100); !arrancar timer, setear a 100 milisegundos (1 seg)
];


Objeto reloj "reloj"
with
nombre 'reloj',
horas 0,
minutos 0,
segundos 0,
descripcion
[;
   print self.horas,":",self.minutos,":",self.segundos;
];


! capturadora de eventos Glulx
[ HandleGlkEvent ev contexto;
    contexto = 0; ! Para que no de un aviso al compilar, pues aqui no lo usamos (para ete caso)
    switch (ev-->0) {
      evtype_Timer:
          reloj.segundos ++;
          if (reloj.segundos>59){
             reloj.minutos ++;
             reloj.segundos=0;
          }
          if (reloj.minutos>59){
            reloj.horas ++;
            reloj.minutos=0;
          }
          if (reloj.horas>23) reloj.horas=0;

          !chequeo de la hora exacta en la cual 'disparar' un evento
          if (reloj.horas==0 && reloj.minutos==20){ ! a los 20 minutos de comenzar el juego
               !disparar una funcion o setear una variable
          }     

          glk_request_timer_events(100); !re-arrancar timer, setear a 100 milisegundos (1 seg)

    }! switch ev
];


si piensas en Glulx, por ahi anda la cosa.
no se me ocurre nada mejor.


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 09 Mar 2006 15:50 
Desconectado
Samudio
Samudio
Avatar de Usuario

Registrado: 10 Sep 2004 00:17
Mensajes: 3069
Ubicación: Chile
Saludos:

Estoy muy agradecido por todos vuestros aportes.

Como (de momento) quiero mantener esto en la máquina Z, usaré la solución de RML (a quien mencionaré en los crédiots y agradecimientos, por supuesto).

Se despide, sumamente agradecido,

_________________
[Incanus]
El Escritorio - Blog Aventurero y Literario


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 09 Mar 2006 21:25 
Desconectado
Grafista
Grafista

Registrado: 09 Mar 2004 17:20
Mensajes: 504
presi escribió:
¿Y la solución de RtimeX y sus ventanas scottadamianas no nos valdría en este caso con la ventaja de que solo nos metemos en un poco del berenjenal, no en el berenjenal al completo?
¿O me he perdido y el ejercicio se trataba de hacerlo sin usar librerías? :D


Pues hombre... ¡a mí no me lo preguntes! XDD Yo he sido el primero en decir que la vía de Rtimex era tan eficaz como cualquier otra, aunque su método era más de "curarse en salud ante el problema" que "resolverlo" pero por lo demás es una solución perfectamente válida, aunque... ten en cuenta que Incanus y Mel, que estaban por la labor de usarla, se echaron atrás al no aclararse con su funcionamiento, y un servidor, que más o menos se aclaraba, se echaba para atrás ante la imposición sin posibilidad de opción alguna de un modelo de pantalla que no tiene por qué agradar a todo el mundo, más pequeños detalles como, por machacar más de lo que en mi opinión sería necesario el código original, y cito de su documentación, la pérdida de capacidades de edición, como la recuperación de las últimas órdenes o la posibilidad de cambiar otra letra que no sea la última de lo que estás tecleando...

Ante el cúmulo de desventajas, si te digo la verdad, la pregunta no es "¿qué tiene de malo Rtimex?" sino "¿qué tiene de malo buscar alternativas más óptimas?" :)

Y en ello estamos, teníamos una posibilidad "no muy complicada" pero "asíncrona" que a su vez podíamos hacer "síncrona" pero arriesgandonos a estropicios en la pantalla... a no ser que... y ahí me había quedado por no meterme en el berenjenal XDD

Pero una vez te tiras de cabeza no es tan malo, quiero decir, el escenario es el siguiente:

-Queremos controlar eventos en tiempo real en Z, y resulta que la única manera de hacerlo es mediante la sentencia de ensamblador @aread, que es, por cierto, la que usa Inform mientras espera el input por teclado del jugador.

-Una vez que te lanzas hacia ese @aread, sólo hay dos maneras de volver de la función que éste llama cada x décimas de segundo:

-a) con rfalse, en cuyo caso no interfieres el funcionamiento normal de la librería, el input de teclado espera normalmente a que el jugador introduzca algo y pulse return, y por tanto no hay resultados 100% "síncronos"

-b)con rtrue, en cuyo caso interrumpes el proceso normal y estás forzosamente obligado a elegir una acción por defecto y tokenizarla manualmente, si no no sales de ahí... bueno, salir sales XDDD, pero el parser "chirriará" un poquito.

No es tan fiero el león como lo pintan, así que vamos a poner un ejemplo en el que coexisten las dos posibilidades, un retorno con false para los mensajes de "quedan x segundos" y otro con true para cuando la cuenta atrás llegué a cero y el juego se acabe. Para dar mayor sensación de "tiemporrealidad" el cronómetro lo pintaremos actualizandose cada segundo en la barra de estado.

En nuestro nuevo objeto reloj ya sólo nos fijaremos en los segundos, ya que el resto de la hora se puede obtener con facilidad a partir de ellos:

Código:
Objeto reloj "reloj"
with
nombre 'reloj',
segundos 30,
descripcion
[;
   imprime_hora();
];


La descripción del reloj ahora llama a una rutina "imprime_hora" que va a ser algo como esto (ahora ya con un formato de HH:MM:SS más o menos decente):

Código:
[imprime_hora x y;
   x=reloj.segundos/3600;
   y=reloj.segundos%3600;
   if (x<10) print "0";
   print x,":";
   x=y/60;
   y=y%60;
   if (x<10) print "0";
   print x,":";
   if (y<10) print "0";
   print y;
];


Reemplazamos DibujarLineaEstado por un simple copypasteo de su parte para Z en el que sustituimos (por cambiar algo) el número de jugadas por una llamada a imprime_hora para que salga nuestro cronómetro.

Código:
[ DibujarLineaEstado width posa posb;
   @split_window 1; @set_window 1; @set_cursor 1 1; style reverse;
   width = 0->33; posa = width-26; posb = width-13;
   spaces width;
   @set_cursor 1 2;
   if (localizacion == laoscuridad) print (name) localizacion;
   else
   {   FindVisibilityLevels();
       if (techo_de_visibilidad == localizacion)
           print (name) localizacion;
       else print (The) techo_de_visibilidad;
   }
!   if ((0->1)&2 == 0)
   if (la_hora == NULL)
   {   if (width > 76)
       {
       #IFNDEF NO_PUNTUACION;
         @set_cursor 1 posa; print (string) PUNTUACION__TX, lineaEstado1;
       #ENDIF; ! NO_PUNTUACION
         @set_cursor 1 posb; imprime_hora();
       }
       if (width > 63 && width <= 76)
       {
       #IFNDEF NO_PUNTUACION;
         @set_cursor 1 posb; print lineaEstado1, "/";imprime_hora();
       #IFNOT;
         posb = posb + 2;  ! Esto es porque en este caso no hay barra ('/')
         @set_cursor 1 posb; imprime_hora();
       #ENDIF; ! NO_PUNTUACION
       }
   }
   else
   {   @set_cursor 1 posa;
       print (string) HORA__TX;
       IdiomaHoraDelDia(lineaEstado1, lineaEstado2);
   }
   @set_cursor 1 1; style roman; @set_window 0;
];


y vamos a lo gordo: la versión nueva de keyboardprimitive y la función "tiempo" a la que llamaremos cada 10 décimas de segundo desde @aread y de la que volveremos con rfalse todas las veces excepto cuando el tiempo llegue a cero.
En ese último caso forcaremos manualmente una acción "examinar reloj" rellenando letra a letra el buffer del teclado y llamando nosotros al "tokenizador"... ¡suena peor de lo que realmente es!
Y he optado por "ex reloj" ya que esta produce un resultado (te muestra la hora del cronómetro, que estará a cero) que no queda fuera de contexto ni produce mensajes que queden mal. En cualquier caso, se podría mejorar con una acción falsa (fake) que fuese aún menos intrusiva.

Código:
[KeyboardPrimitive b p k;
   b ->1=0;
   p ->1=0;
   @aread b p 10 tiempo ->k;
        !ahora viene el relleno manual del buffer de teclado y su tokenización       
   if (k==0)
   {
      b->1=8; !longitud de la cadena que viene a continuación
      b->2='e';
      b->3='x';
      b->4=' ';
      b->5='r';
      b->6='e';
      b->7='l';
      b->8='o';
      b->9='j';
      @tokenise b p;
   }
];

[tiempo;
   reloj.segundos --;
   DibujarLineaEstado();
   if (reloj.segundos==15) print "^¡Quedan 15 segundos!^";
   if (reloj.segundos==0)
   {
      banderafin=1;
      "^!Se acabó!^";
   }
   rfalse;
];


En cada llamada a la rutina "tiempo" le damos un viaje a la linea de estado, con lo que esta se actualizará cada segundo. En el segundo 15 sale un mensaje de advertencia y retorna false, observad como afecta ello a la frase que el jugador pudiera estar tecleando (se conserva y vuelve a aprecer como estuviera, con lo que lo peor que sucedería es que en la pantalla se quedase una frase a medio terminar... un mal estético ciertamente menor y, para muchos, completamente ignorable, ¡e incluso a quienes les parezca "feo" no les perjudicará en la jugabilidad!)

¡Hey! Y gracias a Sarganar por aportar la manera de hacerlo en Glulx y a Incanus por lo de los créditos, aunque el mérito es de Graham Nelson, yo sólo he aplicado lo que sugería el manual de Inform! :oops:


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 09 Mar 2006 21:51 
Desconectado
Samudio
Samudio
Avatar de Usuario

Registrado: 10 Sep 2004 00:17
Mensajes: 3069
Ubicación: Chile
Esto ya es, a estas alturas, un poco extemporáneo, pero:

presi escribió:
Pero en cambio no sirve para uno de los requisitos de Incanus que era que se produjera algún evento síncrono a cierto tiempo, por ejemplo un aviso a los 20 minutos o la inevitable y dantesca muerte si el cronómetro llega a 0[...]


En realidad, eso puede hacerse en la función tiempo:

Código:
[ tiempo;

   !un contador bastante burdo de segundos
   !este es un ejemplo con cuenta regresiva

   reloj.segundos --;
   
   ! Fin del Juego por Time Out
   if (reloj.segundos==0) banderafin = 3;

  ! Para otros instantes de tiempo, otros if y ya...

   rfalse;

];


Burdo, pero funciona (ya lo probé)...

_________________
[Incanus]
El Escritorio - Blog Aventurero y Literario


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 09 Mar 2006 22:12 
Desconectado
Semimomio
Semimomio
Avatar de Usuario

Registrado: 15 Dic 2004 21:28
Mensajes: 2302
Radio Marte Libre escribió:
No es tan fiero el león como lo pintan, así que vamos a poner un ejemplo en el que coexisten las dos posibilidades, un retorno con false para los mensajes de "quedan x segundos" y otro con true para cuando la cuenta atrás llegué a cero y el juego se acabe. Para dar mayor sensación de "tiemporrealidad" el cronómetro lo pintaremos actualizandose cada segundo en la barra de estado.


Muy buena solución.


Radio Marte Libre escribió:
Reemplazamos DibujarLineaEstado por un simple copypasteo de su parte para Z en el que sustituimos (por cambiar algo) el número de jugadas por una llamada a imprime_hora para que salga nuestro cronómetro.

y vamos a lo gordo: la versión nueva de keyboardprimitive y la función "tiempo" a la que llamaremos cada 10 décimas de segundo desde @aread y de la que volveremos con rfalse todas las veces excepto cuando el tiempo llegue a cero.
En ese último caso forcaremos manualmente una acción "examinar reloj" rellenando letra a letra el buffer del teclado y llamando nosotros al "tokenizador"... ¡suena peor de lo que realmente es!
Y he optado por "ex reloj" ya que esta produce un resultado (te muestra la hora del cronómetro, que estará a cero) que no queda fuera de contexto ni produce mensajes que queden mal. En cualquier caso, se podría mejorar con una acción falsa (fake) que fuese aún menos intrusiva.


Efectivamente no acabo de entender muy bien la introducción con calzador de esa acción, si el resultado del cronómetro a cero va a ser de todas formas una pavorosa y horripilante muerte, no sería mejor simplemente exhibir el terrorífico texto correspondiente y acto seguido acabar el juego, y ciertamente en este caso, con el jugador ya defenestrado, no importa lo que estuviera escribiendo en su línea de entrada, seguro que ya no le iba a hacer falta. :twisted:

Radio Marte Libre escribió:
Código:
[KeyboardPrimitive b p k;
   b ->1=0;
   p ->1=0;
   @aread b p 10 tiempo ->k;
        !ahora viene el relleno manual del buffer de teclado y su tokenización       
   if (k==0)
   {
      b->1=8; !longitud de la cadena que viene a continuación
      b->2='e';
      b->3='x';
      b->4=' ';
      b->5='r';
      b->6='e';
      b->7='l';
      b->8='o';
      b->9='j';
      @tokenise b p;
   }
];

[tiempo;
   reloj.segundos --;
   DibujarLineaEstado();
   if (reloj.segundos==15) print "^¡Quedan 15 segundos!^";
   if (reloj.segundos==0)
   {
      banderafin=1;
      "^!Se acabó!^";
   }
   rfalse;
];


En cada llamada a la rutina "tiempo" le damos un viaje a la linea de estado, con lo que esta se actualizará cada segundo. En el segundo 15 sale un mensaje de advertencia y retorna false, observad como afecta ello a la frase que el jugador pudiera estar tecleando (se conserva y vuelve a aprecer como estuviera, con lo que lo peor que sucedería es que en la pantalla se quedase una frase a medio terminar... un mal estético ciertamente menor y, para muchos, completamente ignorable, ¡e incluso a quienes les parezca "feo" no les perjudicará en la jugabilidad!)


Y ya que hemos retocado la barra de estado... umm, ¿no sería mejor imprimir el aviso de los 15 segundos en la propia línea de estado? así esto no afectaría absolutamente en nada a la línea de entrada del jugador, es más <publicidad>podría usarse mi librería barra.h para un manejo más sencillo de la barra de estado</publicidad> :wink: de ese modo habría que poner una propiedad de texto de la barra de estado, inicialmente vacía, que posteriormente se le asignaría el mensaje de los 15 segundos desde la función tiempo y luego vendría la llamada para redibujarla, siento no aportar código pero sé que Incanus será capaz de hacerlo por si mismo.


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 09 Mar 2006 22:18 
Desconectado
Semimomio
Semimomio
Avatar de Usuario

Registrado: 15 Dic 2004 21:28
Mensajes: 2302
Incanus escribió:
Código:
[ tiempo;

   !un contador bastante burdo de segundos
   !este es un ejemplo con cuenta regresiva

   reloj.segundos --;
   
   ! Fin del Juego por Time Out
   if (reloj.segundos==0) banderafin = 3;

  ! Para otros instantes de tiempo, otros if y ya...


Perfecto, de todas maneras como ya he comentado en el otro mensaje (antes de leer este) recomiendo que si los textos no son muy extensos se muestren en la barra de estado, pero bueno, eso ya a tu gusto.


Arriba
 Perfil  
 
 Asunto:
NotaPublicado: 09 Mar 2006 22:47 
Desconectado
Grafista
Grafista

Registrado: 09 Mar 2004 17:20
Mensajes: 504
presi escribió:
Efectivamente no acabo de entender muy bien la introducción con calzador de esa acción, si el resultado del cronómetro a cero va a ser de todas formas una pavorosa y horripilante muerte, no sería mejor simplemente exhibir el terrorífico texto correspondiente y acto seguido acabar el juego, y ciertamente en este caso, con el jugador ya defenestrado, no importa lo que estuviera escribiendo en su línea de entrada, seguro que ya no le iba a hacer falta. :twisted:


Lo ideal sería que funcionase así, pero... el bueno de Eparser está escrito de tal manera que, cuando la función llamada desde @aread devuelve true, él da por hecho que ya hay una acción tokenizada que pasa a procesar de inmediato... ¡dándose de bruces con que no la hay! y haciéndose un lío, claro.

(haciendo la prueba en este ejemplo, lo que hacía en concreto era imprimir el "¡Se acabó!"... quedarse un momento callado... imprimir en pantalla un "¿Perdón?" y continuar la cuenta atrás aún metiendose en números negativos XDD)

Así que hay que meterle alguna acción "con calzador" y elegir la que menos estorbe. Lo suyo podría ser una acción que no hiciese nada creada ex profeso para la ocasión, pero eso ya al gusto del autor.


Arriba
 Perfil  
 
Mostrar mensajes previos:  Ordenar por  
Nuevo tema Responder al tema  [ 16 mensajes ]  Ir a página 1, 2  Siguiente

Todos los horarios son UTC + 1 hora


¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 4 invitados


No puede abrir nuevos temas en este Foro
No puede responder a temas en este Foro
No puede editar sus mensajes en este Foro
No puede borrar sus mensajes en este Foro

Buscar:
Saltar a:  
Desarrollado por phpBB® Forum Software © phpBB Group
Traducción al español por Huan Manwë para phpBB-Es.COM