Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Detección De "comandos"

Iniciado por ALRAZ, 03 de Octubre de 2004, 11:20:38 PM

« anterior - próximo »

ALRAZ

 Alo de nuevo  :lol:


Pregunta ALRAZiana:
Alguien me podría dar alguna guía sobre como se hace eso de captar comandos al estilo de los juegos de lucha?

Ya saben el clásico Street Fighter:
"Abajo, abajo-adelante, Adelante + Botón" = Movimiento especial...

La cosa es... Como sé cuando el usuario ha marcado la secuencia anterior..?

Estoy usando SDL para obtener las entradas, aunque creo que eso es lo de menos, ya que las entradas se pueden convertir a cualquer otra cosa


ALRAZ

Cita de: "Lessman"Intenta probar con una maquina de estados finita, para interpretar la entrada del usuario.
:huh:

Estem......  :blink:


Qué ser Máquina de Estados Finita?  :(  

Zaelsius

 http://en.wikipedia.org/wiki/Finite_state_machine y http://en.wikipedia.org/wiki/DFA.

En un juego de lucha, el lenguaje a reconocer sería el conjunto de posibles combinaciones de teclas que resultan en un movimiento o ataque. Tendrias que programar/diseñar un autómata para cada combinación que quieras reconocer.
Eso es más o menos lo que habría que hacer, aunque hay más detalles de implementación claro..

Seguramente encuentres mejores explicaciones y tutoriales buscando sobre autómatas de estados finitos aplicados a juegos(busca en los artículos de GameDev.Net por ejemplo).

Con éste método, podrías definir los movimientos en un fichero de texto y crear los autómatas a partir de esta descripción.

Tambien puedes optar por soluciones "caseras" menos rigurosas, pero en el fondo estarás implementando lo anterior, sólo que de mala manera.

Edit: Esta es otra de esas cosas que enseñan en 1º o 2º curso de carrera y que segun algunos no sirve para nada(no me refiero a gente del foro)  :rolleyes:  

ALRAZ

Cita de: "ZaelSiuS"Edit: Esta es otra de esas cosas que enseñan en 1º o 2º curso de carrera y que segun algunos no sirve para nada(no me refiero a gente del foro)  :rolleyes:
O_O

Nunca nos enseñaron tal cosa :angry:
Al menos en los primeros cursos.

Aunque para la cochinada de escuela en la que estoy, no me extraña para nada  <_<

por cierto, gracias por los links  :D  

Thenend

 mmm, yo hice eso para un juego de peleas en div hace unos años, pero he perdido el código (y el juego). Por lo que recuerdo, almacenaba las entradas en una lista junto con el tiempo en el que se habían producido. Cuando había pasado demasiado tiempo desde la pulsacion de una tecla, borraba la lista.

Para reconocer la secuencia usaba la fuerza bruta (comparando con todas las posibles secuencias de movimientos). Sí que es verdad que un autómata es perfecto para esa misión, pero dado que no suele haber más de 6 u 8 movimientos especiales, cualquier código capaz de reconocer la secuencia te puede valer (aunque seguramente llegarás de forma intuitiva a algo parecido a un autómata).

De cualquier modo, estudiate bien los autómatas porque en los juegos en general son muy útiles pero es que en los de lucha son imprescindibles. A poco complejo que lo hagas acabarás con toda una señora máquina de estados.

Abc7

 mmm.. yo lo q haria seria guardar un array d ints para cada movimiento, y cada valor del array seria un movimiento (SDLK_UP, SDLK_t, etc) y desde el ultimo SDL_KEYUP se activa un timer q indica cuanto tiempo tiene el usuario para hacer otro movimiento hasta q se considere q es otro, y no parte del combo.
entonces cuando se termina el movimiento, chekeo los arrays a ver si alguno coincide con el array d movimientos q hizo el usuario, y si alguno coincide llama a la funcion o lo q sea q se encargue d hacer ese combo =)
pero cmo dijeron, es una mala solucion.. quizas otro t d una mejor

ALRAZ

 (uoh)
XD

Me van a creer que eso de los autómatas es casi exactamente lo que estoy usando para los estados de los personajes
(Que no es un juego de lucha sino de Scroll 2D, pero pienso incluir algo de comandos  :P )

Soy tan bruto (rules)


Se me ha ocurrido hacer algo parecido a lo de los Arrays, pero con árboles, donde cada hijo de un  árbol es la tecla/botón que se debe presionar después de haber presionado la tecla/botón del nodo padre.
Ejemplifico:


                            Abajo
                       /                \
Abajo-Izquierda                   Abajo-Derecha
         |                                   /                  \    
    Izquierda                      Derecha         Abajo
         |                                  |                        |
     Patada                         Puño                  Puño
         |                                  |                         |
(Eh! Esto es un             (Joer! esto es          (Ah caray! Aquí
comando)                      OTRO comando)        tenemos un comando más!)


Seguro no es el árbol más xulo que hayan visto :P

Todavía no termina de convencerme la idea...
Opiniones?

[EX3]

 A mi me convence mas lo de guardar una lista con las teclas pulsadas y realizar la comparacion. Lo veo mas sencillo.

Yo por ejemplo iria concatenando los valores en una sola variable en vez de crear una lista o array y luego solo haria una sencilla comprobacion entre dos valores mediante un Select Case, la variable y una constante por ejemplo, lo veo mas sencillo y "algo" mas optimizado en cuanto a memoria se refiere (Variable < Array)

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

ALRAZ

Cita de: "[EX3"] A mi me convence mas lo de guardar una lista con las teclas pulsadas y realizar la comparacion. Lo veo mas sencillo.

Yo por ejemplo iria concatenando los valores en una sola variable en vez de crear una lista o array y luego solo haria una sencilla comprobacion entre dos valores mediante un Select Case, la variable y una constante por ejemplo, lo veo mas sencillo y "algo" mas optimizado en cuanto a memoria se refiere (Variable < Array)

Salu2...
O_O

Interesante proposición...

sés

 Te cuento cómo lo tenía hecho yo:

Cada jugador tiene unas teclas, a las que asigno un valor (bit):
Direcciones
IZQ=0x01
DER=0x02
ARR=0x04
ABA=0x08

Puños
P1=0x10
P2=0x20

Patadas
K1=0x40
K2=0x80

Así puedes guardar en un byte (si tienes más botones usa short o int) el estado de las teclas del jugador (IZQ | P1 | P2).

Implementé una lista (una por jugador, claro) como la que ya han comentado, en la que voy introduciendo los estados de las teclas.
En esta lista hacía varias operaciónes según lo que ocurriera:
- Si el estado cambia no hago nada. Yo no lo necesitaba, pero podrías guardar el tiempo que se mantiene el estado para el típico movimiento en el que tienes que cargar en una dirección.
- Si el estado cambia, lo añado a la lista, eliminando el más viejo si la lista estaba llena.
- Cada X tiempo (1s ó así) elimino la lista completa.

Para ver si se había ejecutado algún movimiento especial me hice una especie de "memcmp" que comparaba el contenido de la lista con los movimientos posibles del jugador, añadiendo algo de tolerancia para las diagonales.

Lo de las tolerancias es porque, si has jugado a estos juegos, sabrás que al hacer los movimientos tienes cierta libertad:

Típico "Dragon Punch" = F, D, DF + P
Todos sabemos que si haces algo del tipo: F, DF, D, DF + P funciona igual
También se traga: F, D, DF, P y F, DF, D, DF, P

Vamos que si haces una máquina de estado te tocará poner bastantes estados, a no ser que quieras que el jugador tenga que hacer los movimientos EXACTAMENTE como tú digas... y que se cansen a los 2 minutos porque no les sale nada :P

Tengo la implementación por ahí, esperando a que me ponga a hacer mi motor de juegos de lucha que tengo aparcado... aunque casi hecho -.-
Soy indeciso... ¿o no?

Malandrin

 Hola, hace un tiempecillo estaba con un juego de lucha, y yo lo hacía así:

- Definía en un archivo las posibles combinaciones del personaje. Ej:
 IZQUIERDA, ABAJO, ADELANTE, PUÑO_FUERTE -> ACCION
 DERECHA_ABAJO_IZQUIERDA_PATADA_DEBIL -> ACCION

- Un vez en el juego, tenía un array estático del tamaño de número de teclas que desencadenaban una acción (en el ejemplo PUÑO_FUERTE y PATADA_DEBIL),  luego iba parseando estas combinaciones y creando un arbol 'al revés', algo así:

 [PUÑO_FUERTE][PATADA_DEBIL] --> array estático
          /                         \
         /                           \
 [ADELANTE]           [IZQUIERDA]
       |                             |
 [ABAJO]                 [ABAJO]
      |                               |
 [IZQUIERDA]         [DERECHA]
     |                               |
 (ACCION)               (ACCION)

Y así con el resto de acciones posibles.

- A la hora de detectar estos movimientos: cada pulsación de tecla la iba almacenando en un array, el array se iba 'autoactualizando', vamos, que si durante n ticks no se detectaba pulsación, se pasaba a la siguiente posición del array marcando esa casilla como vacía, y si se pulsaba la misma tecla, se iba actualizando un contador en esa posición del array con el número de ticks pulsados. Cuando detectaba que era una tecla desencadenante de acción, comenzaba a recorrer el arbol de esa tecla a partir del array de entrada de pulsaciones, hasta que encontrara la acción o no.  Un caso particular eran las acciones contenidas en acciones, p.e. ABAJO,DERECHA,PUÑO y IZQUIERDA,ABAJO,DERECHA,PUÑO, que si hago la combinación larga por este método pillaría la corta, para solucionar esto, al encontrar una acción la guardo y sigo mirando el árbol, si encuentro otra pues me quedo con esa  y si no, con la anterior.

Y basicamente era eso :) Un saludo.

ALRAZ

 Wowowowowooooo  (uoh)
Esto se pone cada vez más interesante...

a ver si estoy entendiendo:

Malandrín:

El arreglo lo recorrías a partir de la posición final del movimiento?
 Es decir, si el movimiento termina en Puño, cuando el usuario presionaba Puño,
inmediatamente recorrías buscando en:
1)Las teclas/botones que había presionado el jugador ANTES de presionar Puño
2)tus arreglo de Posibles movimientos de modo que concordaran con lo anterior
Y comparabas que ambas fueran iguales o más o menos iguales
Estoy entendiendo?


sés:

Lo de los "grados de libertad" con las diagonales...
como se implementaría?

He visto que en algunos juegos (como Marvel Vs Capcom 2) esta "característica"
se puede explotar hasta extremos insospechados  :)  

Malandrin

 
CitarEl arreglo lo recorrías a partir de la posición final del movimiento?
Es decir, si el movimiento termina en Puño, cuando el usuario presionaba Puño,
inmediatamente recorrías buscando en:
1)Las teclas/botones que había presionado el jugador ANTES de presionar Puño
2)tus arreglo de Posibles movimientos de modo que concordaran con lo anterior
Y comparabas que ambas fueran iguales o más o menos iguales
Estoy entendiendo?

1) Efectivamente, si el array contiene [ATRAS][VACIO][ADELANTE][ATRAS][ABAJO][ADELANTE][PUÑO], cuando detecto el puño, entro en su árbol y busco el nodo de la tecla 'Adelante', si hay, me metó en él y busco el nodo de la tecla 'Abajo', y así sucesivamente, hasta que encuentre una acción, o un nodo que no lleve a ningún lado.

2) Realmente no hago ninguna comparación, simplemente voy recorriendo el árbol de acciones, en el que puedo llegar a un nodo hoja que será el que tenga la acción definida -p.e. un aduken-, o puedo llegar a un nodo en el que con la tecla del array de pulsaciones no me lleve a ningún lado.


       [PUÑO]
           |
    [ADELANTE]


En este ejemplo, si pulso puño, entraré en el array de puño y miraré la anterior tecla del array de pulsaciones, si es un 'Adelante', veo que existe ese nodo y que al ser hoja realiza una acción, (cada nodo hoja tiene información de la acción que realiza), si en vez de adelante, el array de pulsaciones tiene un 'Atrás', veo que desde 'Puño' no llego a ningún nodo 'Atrás', por lo tanto no hago nada.

sés

 Pues no me aceurdo bien. Si tengo un rato (y me acuerdo) busco el código, a ver si es legible.

Por cierto, lo de la tecla desencadenante de un movimiento no me convence. ¿IZQUIERDA no desencadena un movimiento? ¿Solo son movimientos si terminan con un disparo?
No olvidemos que F,F es un movimiento (salto alante o correr), D, U es otro (salto largo), etc.

Yo considero movimientos básicos: B, F, D, U, P1, P2, K1, K2. El resto son movimientos especiales.
Soy indeciso... ¿o no?






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.