CAAD

Comunidad de Aventuras Conversacionales y Relatos Interactivos
Fecha actual 17 Oct 2017 15:50

Todos los horarios son UTC + 1 hora




Nuevo tema Responder al tema  [ 10 mensajes ] 
Autor Mensaje
 Asunto: forceCommand
NotaPublicado: 06 Dic 2011 11:59 
Desconectado
xyzzy

Registrado: 09 Mar 2004 22:50
Mensajes: 9150
Me estoy dando cuenta de que cuando se ejecuta un forceCommand no se imprime el espacio en blanco entre éste y el siguiente comando del usuario.

Código:
> coge el agua
No puedes coger el agua con tus manos.
> sacar agua del pozo
No puedes coger el agua con tus manos.
> coge agua con el caldero
Necesitarás bajar el caldero al pozo para sacar agua.


No tengo claro si es algo que he hecho o es el comportamiento natural de AGE. ¿Lo es?

_________________
Si la mentira tuviera color, todos seríamos daltónicos...


Arriba
 Perfil  
 
NotaPublicado: 06 Dic 2011 12:08 
Desconectado
Samudio
Samudio
Avatar de Usuario

Registrado: 09 Mar 2004 16:16
Mensajes: 5272
Ubicación: Coruña
Que yo sepa, salvo bug raro, forceCommand no afecta a si se imprime una línea en blanco o no, eso sólo depende de si en el write donde escribes el mensaje (o en el fichero de mensajes por defecto, si es que es un mensaje por defecto) aparece un \n al final o no.

_________________
Actúa siempre de tal modo que las decisiones de tu voluntad pudiesen servir como preceptos de una legislación universal (E. Kant)


Arriba
 Perfil  
 
NotaPublicado: 06 Dic 2011 12:41 
Desconectado
xyzzy

Registrado: 09 Mar 2004 22:50
Mensajes: 9150
Al-Khwarizmi escribió:
Que yo sepa, salvo bug raro, forceCommand no afecta a si se imprime una línea en blanco o no, eso sólo depende de si en el write donde escribes el mensaje (o en el fichero de mensajes por defecto, si es que es un mensaje por defecto) aparece un \n al final o no.


Hmmm... tengo un poco de lío al respecto rellenando los campos de descripciones, igual el problema lo tengo ahí.
A ver, ¿lo normal entre comando y comando es que haya un solo salto de línea y nada más?
Es que yo veo que en muchos quedan dos, y me gusta más porque así los comandos quedan más separados, pero igual estoy provocando yo ese comportamiento y no es el normal de AGE ¿Es así?

_________________
Si la mentira tuviera color, todos seríamos daltónicos...


Arriba
 Perfil  
 
NotaPublicado: 06 Dic 2011 13:45 
Desconectado
Samudio
Samudio
Avatar de Usuario

Registrado: 09 Mar 2004 16:16
Mensajes: 5272
Ubicación: Coruña
Sí, la verdad es que esto no está en la documentación y, aunque es un detallito, es útil. Aclaro un poco el tema:

- Por defecto, AGE sólo pone un salto de línea (el necesario para que la siguiente orden aparezca en una línea nueva). Así que, por ejemplo, en una acción que definas tú, si pones un write y no lo terminas con \n, no se dejará una línea en blanco, y si lo terminas con \n, sí. El forceCommand no influye nunca nada en absoluto en esto.
- Al imprimir un mensaje por defecto, no se imprime tampoco ningún salto de línea si no está explícitamente en el mensaje (\n al final). Por eso, en el fichero de mensajes por defecto, los mensajes que son respuestas a acciones (como "Blandes $item en $limbs.\n") tienen un \n al final.
- El único \n en AGE que se imprime por defecto (salvo algún bug/despiste) es después del comportamiento por defecto de la acción "mirar", porque me pareció engorroso que el programador tuviese que terminar todas las descripciones de objetos con \n si quisiera una línea en blanco después de "mirar".

_________________
Actúa siempre de tal modo que las decisiones de tu voluntad pudiesen servir como preceptos de una legislación universal (E. Kant)


Arriba
 Perfil  
 
NotaPublicado: 30 Nov 2015 10:27 
Desconectado
Betatester
Betatester
Avatar de Usuario

Registrado: 09 Feb 2012 20:33
Mensajes: 855
No sé qué se me escapa aquí que no me ejectua el forceCommand

Código:
public void mouseClicked(MouseEvent me) {
    for ( int i = 0; i < misTags.size() ; i++ ) {
        if ( misTags.get(i).matchCaret(panel.getCaretPosition())) {
            s = misTags.get(i).getAccion() + " " + misTags.get(i).getText();
            self.write ("\n" +  s + "\n" );
            self.forceCommand( s );
            break;
        }
    }
}


Cuando hago click en el tag de acción que he creado, se debe ejecutar la acción programada. El método está en el "jugador", todo va correcto, hasta la línea:
self.write ("\n" + s + "\n" );, que imprime correctamente la acción programada, para esta en concreto imprime "examinar cosa". Es decir que la cadena
Código:
s = misTags.get(i).getAccion() + " " + misTags.get(i).getText();

ha creado bien el comando, pero no lo ejecuta.

Luego cuando tecleo yo "examinar cosa", me ejecuta dos veces el comando.

El log:

Código:
Bienvenido a esta aventura...

Tu orden:  mirar
Descripción de la habitación tag uno más texto tag dos y otro texto, tag tres texto tag cuatro y final.
Aquí hay una cosa.
examinar cosa   --> cada vez que clico en "cosa" me ejecuta el self.write ("\n" +  s + "\n" );

examinar cosa --> cada vez que clico en "cosa" me ejecuta el self.write ("\n" +  s + "\n" );

examinar cosa --> cada vez que clico en "cosa" me ejecuta el self.write ("\n" +  s + "\n" );

Tu orden:  examinar cosa  --> al teclear "examinar cosa", me ha respondido dos veces.
Una {accion%examinar%cosa} que hay aquí.
Una {accion%examinar%cosa} que hay aquí.


y bueno la descripción de la cosa me saca el tag sin tratar, deberé en cada objeto que tenga un tag en su descripción capturar el "mirar" antes de que se ejecute.

_________________
Te quiero... lo siento Yoda sólo tenemos café.


Arriba
 Perfil  
 
NotaPublicado: 30 Nov 2015 12:50 
Desconectado
Betatester
Betatester
Avatar de Usuario

Registrado: 09 Feb 2012 20:33
Mensajes: 855
Creo que tiene que ver con el Listener del mouse pero ya me quedé sin ideas...

Dejo aquí el world para más datos.

https://dl.dropboxusercontent.com/u/231 ... %20age.zip

Gracias!

_________________
Te quiero... lo siento Yoda sólo tenemos café.


Arriba
 Perfil  
 
NotaPublicado: 30 Nov 2015 13:02 
Desconectado
Samudio
Samudio
Avatar de Usuario

Registrado: 09 Mar 2004 16:16
Mensajes: 5272
Ubicación: Coruña
Es un problema de threads y de cómo es la relación entre la interfaz gráfica y el modelo de mundo en AGE.

El tema es que tú estás capturando un evento de ratón, que como todos los eventos, se capturan de forma instantánea en el "event dispatching thread" de Swing. Por otra parte, las cosas que suceden en el mundo (como el hecho de que un jugador se mueva, coja un objeto, etc.) están vinculadas al thread del juego, el "game engine thread", y el mundo sólo se mueve si ese hilo itera, simulando una unidad de tiempo del juego. ¿Y cuándo itera ese hilo? Pues depende, en modo tiempo real una vez cada X tiempo, en modo síncrono cuando un jugador teclea una orden.

El método forceCommand lo que hace es que en la siguiente unidad de tiempo que se simule, se ejecute la orden dada. El problema es que, suponiendo modo síncrono ("turnos"), esa unidad de tiempo no se simula. El thread del juego está parado en una llamada bloqueante esperando por una entrada (por si le quieres echar un ojo, esto es concretamente en obtainCommandFromClient(), en Player.java, líneas 341 y siguientes, que a su vez llama -en el caso del cliente gráfico- a getInput(), en ColoredSwingClient.java, líneas 1420 y siguientes, con un wait en 1432); y hasta que no salga de esa llamada bloqueante no va a interpretar que ha recibido algo.

Vamos, en resumen: AGE tiene un bucle de entrada/salida, en el que se van esperando entradas del jugador, recibiendo, y procesando; y si de golpe tú metes una entrada de la nada porque alguien pulsó el ratón, entras como un elefante en una cacharrería en ese bucle :D En concreto, entras en un momento en que AGE está esperando por una entrada, que espera que le llegue de otra manera, y por mucho que le metas un forceCommand(), pues sigue esperando.

¿Hay forma de entrar "bien" y conseguir que te reciba la entrada de inmediato? Sí, por supuesto, sería cosa de hacer lo mismo que hace el cliente cuando el jugador pulsa "enter" tras teclear un comando, que viene a ser lo que hay en SwingEditBoxListener.java, método actionPerformed(), que a su vez llama (en la línea 92) al método setInputString() del cliente (ColoredSwingClient.java, 1534) que hace un notify(). El notify() al cliente es lo que hace que se despierte de la espera y diga "hey, me han pasado un dato, vamos a procesarlo".

Así pues, a grosso modo, lo que tienes que hacer es mandarle un notify() al cliente para que se despierte. Yo creo que con eso, más o menos, puede funcionar. Pero ojo, que estas cosas de threads son sutiles:

- Tienes que considerar qué va a pasar, y qué quieres que pase, si cuando mandas el notify() el thread NO está en espera (por ejemplo, porque el usuario clickea dos veces muy seguidas y aún no ha dado tiempo a procesar la simulación cuando ya le estás mandando otra orden).
- Esto es para modo "turnos". AGE tiene otro comportamiento distinto si el modo es tiempo real, donde la llamada no es bloqueante y no hay espera. Así que necesitarás algún if para considerar eso.
- Aparte al "puentear" todo el sistema de entrada, estarías "puenteando" cosas como el historial de comandos (que al darle hacia arriba te vayan saliendo las órdenes anteriores), o el sistema de "waitKeyPress" que también interactúa con esos hilos.
- Es muy posible que haya alguna otra sutileza que se me pase a ojo.

Vamos, que me temo que no es sencillo, porque el tema de interfaces gráficos en Java (que al fin y al cabo es lo que estás haciendo si capturas eventos de ratón) es bastante complejo. Yo lo que he hecho con AGE es que un autor de aventuras pueda hacer modelos de mundo tan complejos como quiera sin necesitar pelearse con todas estas cosas, ni saber que existen threads, eventos, llamadas bloqueantes, sincronización, etc. Pero claro, si trabajas contra la propia interfaz añadiéndole eventos... pues ahí ya te sales del entorno y si bien puedes hacer de todo porque cuentas con todas las APIs de interfaces gráficos de Java a tu disposición, también tienes que pelearte con la complejidad de todo eso.

_________________
Actúa siempre de tal modo que las decisiones de tu voluntad pudiesen servir como preceptos de una legislación universal (E. Kant)


Arriba
 Perfil  
 
NotaPublicado: 30 Nov 2015 13:09 
Desconectado
Samudio
Samudio
Avatar de Usuario

Registrado: 09 Mar 2004 16:16
Mensajes: 5272
Ubicación: Coruña
Pensando más, creo que hay una manera más sencilla de hacer lo que quieres hacer, sin tener que pelearte con toda esa complejidad porque reutilizarías más código de AGE.

Es la siguiente:

- Poner la cadena en la que han clickeado en el campo de texto.
- Simular que se ha pulsado enter (haciendo saltar los ActionListeners del campo de texto).

Esto lo puedes hacer en Swing de distintas maneras. No me acuerdo muy bien de los detalles de cómo se hacía porque hace tiempo que no me veo en esa situación y hoy no tengo mucho tiempo para mirar, pero no es difícil. Creo que una manera era con una clase llamada Robot (EDIT: creo que esa forma no es la ideal, porque es de demasiado alto nivel, mueve el cursor físicamente para clickear los botones de verdad y cosas así - pero hay maneras de disparar los eventos sin hacer eso). Con un puñado de búsquedas en StackOverflow por "simulate action listeners on text field", "programmatically trigger action events on text field" o cosas así seguro que te aparece.

Con esto básicamente harías que AGE crea que le han metido la cadena de la manera estándar, y se comporte exactamente igual, con lo cual con todo el tema de sincronización, threading, etc. se pegaría AGE y no tú. Creo que ahorrarás tiempo y preocupaciones, y te quedará un resultado mucho más elegante y mantenible, si lo haces así.

_________________
Actúa siempre de tal modo que las decisiones de tu voluntad pudiesen servir como preceptos de una legislación universal (E. Kant)


Arriba
 Perfil  
 
NotaPublicado: 30 Nov 2015 13:16 
Desconectado
Betatester
Betatester
Avatar de Usuario

Registrado: 09 Feb 2012 20:33
Mensajes: 855
Al-Khwarizmi escribió:
Pensando más, creo que hay una manera más sencilla de hacer lo que quieres hacer, sin tener que pelearte con toda esa complejidad porque reutilizarías más código de AGE.

Es la siguiente:

- Poner la cadena en la que han clickeado en el campo de texto.
- Simular que se ha pulsado enter (haciendo saltar los ActionListeners del campo de texto).

Esto lo puedes hacer en Swing de distintas maneras. No me acuerdo muy bien de los detalles de cómo se hacía porque hace tiempo que no me veo en esa situación y hoy no tengo mucho tiempo para mirar, pero no es difícil. Creo que una manera era con una clase llamada Robot. En cualquier caso, con un puñado de búsquedas en StackOverflow por "simulate action listeners on text field", "programmatically trigger action events on text field" o cosas así seguro que te aparece.

Con esto básicamente harías que AGE crea que le han metido la cadena de la manera estándar, y se comporte exactamente igual, con lo cual con todo el tema de sincronización, threading, etc. se pegaría AGE y no tú. Creo que ahorrarás tiempo y preocupaciones, y te quedará un resultado mucho más elegante y mantenible, si lo haces así.


Me has leído la mente... es lo que iba a intentar ahora

_________________
Te quiero... lo siento Yoda sólo tenemos café.


Arriba
 Perfil  
 
NotaPublicado: 30 Nov 2015 13:24 
Desconectado
Betatester
Betatester
Avatar de Usuario

Registrado: 09 Feb 2012 20:33
Mensajes: 855
:D :D :D ni 5 minutos he tardao!!!

Gracias, funciona perfecto, ha quedado:

Código:
public void mouseClicked(MouseEvent me) {
    String s = null;
     // Tomo todos las palabras del
    for ( int i = 0; i < misTags.size() ; i++ ) {
        if ( misTags.get(i).matchCaret(panel.getCaretPosition())) {
            s = misTags.get(i).getAccion() + " " + misTags.get(i).getText();
            input.setText (s);
            //self.write ("\n" +  s + "\n" );
            Robot robot = new Robot();
            robot.keyPress(KeyEvent.VK_ENTER);
            break;
        }
    }
}


Gracias de nuevo!

_________________
Te quiero... lo siento Yoda sólo tenemos café.


Arriba
 Perfil  
 
Mostrar mensajes previos:  Ordenar por  
Nuevo tema Responder al tema  [ 10 mensajes ] 

Todos los horarios son UTC + 1 hora


¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 3 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