dudas de niubie con los joy o gamepads

Started by Noivern, September 25, 2010, 09:45:47 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Noivern

Buenas!

Estoy intentando darle la opción de jugar con gamepad al juego de naves del ojo mortífero.
He terminado mis primeras pruebas esta madrugada y pues bien tengo varias dudas:
¿Cual es la diferencia entre los ejes y los hat?
Estoy probando con un gamepad chino usb de 10 botones y me reporta que posee 2 ejes, los 10 botones y nada más.
Además, me sucede que al principio, si no presiono nada, reporta correctamente que tanto eje 0 como 1
estan a valor = 0. Luego si presiono el direccional, reporta el 32 mil algo (¿o era el max_int? mierda, no recuerdo y ya apague el equipo con el mando de pruebas, estoy muriendo de sueño ahora) con signo dependiendo hacia que lado presione.... peeero al dejar de presionar, el eje 0 se queda a -1. ¿Es esto normal?
Puedo hacer que las naves se muevan con esta información, pero desconozco si en todos los controles sucede lo mismo, menos sé si existen los ejes en todos los controles o si estan estandarizados, y claro, la idea es que la nave se mueva con cualquier control que le pongan al pc, no con cosas específicas.

Saludos!

BoMbErLiNk

#1
- Los ejes son las setas analogicas, creo que eran desde valores -32768 a 32768, tienes que sopesar la zona muerta del joystick, que el centro de calibración no va a quedar en 0 o neutral cuando dejes de moverla.
- El hat (o POV - Point of view) es para la cruceta, valores digitales.

Te pongo el código que hice para manejar ambos simultaneamente :

[code language="bennu"]POV=joy_gethat(control_joystick,0); POVx=0; POVy=0;

// ANALOGICO
IF (get_joy_position(control_joystick,0)<-10000) POVx=1; END // izquierda
IF (get_joy_position(control_joystick,0)>10000) POVx=2; END // derecha
IF (get_joy_position(control_joystick,1)<-7500) POVy=1; END // arriba
IF (get_joy_position(control_joystick,1)>7500) POVy=2; END // abajo

// DIGITAL
IF (POV==1) POVy=1; END // arriba
IF (POV==3) POVy=1; POVx=2; END // der
IF (POV==9) POVy=1; POVx=1; END // izq
IF (POV==4) POVy=2; END // abajo
IF (POV==6) POVy=2; POVx=2; END // der
IF (POV==12) POVy=2; POVx=1; END // izq
IF (POV==2) POVx=2; END // der
IF (POV==8) POVx=1; END // izq
[/code]

Control_joystick = número de joystick
POVx = movimiento X
POVy = movimiento Y
Si te fijas el ejeY es más tolerante que el ejeX, eso lo hice porque generalmente quedan mejor alineados verticalmente cuando se sueltan.

Noivern

¡Muchas gracias!
Y otra duda nub, ¿Todos los controles poseen ejes?
¿O hay algunos que sólo usan cruzeta digital?

BoMbErLiNk

#3
 :)

Si solo hay una cruceta en el mando debería ir con el get_joy_position, aunque sea digital.
También hay excepciones como Wiz en que son botones en lugar de ejes o hats.

Noivern

#4
Nuevamente gracias!

Bueno de la wiz no me preocupo, no pienso portar nada a una consola que no tengo, no quiero depender de otras personas para testear.
Me gustó tu código, me base en la idea para la solución que estoy probando, y la pongo acá pq quizás pueda servir a otros bennuseros:

[code language="bennu"]
process listenerCrucesJoys()
//este proceso deberia ser llamado justo antes de comenzar a controlar algo con los joys,
//normalmente al inicio del juego y no matarlo nunca (si se usa un let_me_alone(), llamarlo de nuevo)

begin
   priority = 10;//prioridad alta para que lea el estado de la direccional antes que cualquier cosa
   loop
      //estadoCruzJoy es una struct global de 2 posiciones con los 4 atributos byte (arriba, abajo... etc)
                     
                 //Control 1
      estadoCruzJoy[0].arriba = (joy_getaxis(0,1) < -10000 || joy_gethat(0, JOY_HAT_UP) || joy_gethat(0, JOY_HAT_LEFTUP) || joy_gethat(0, JOY_HAT_RIGHTUP));
      estadoCruzJoy[0].abajo = (joy_getaxis(0,1) > 10000 || joy_gethat(0, JOY_HAT_DOWN) || joy_gethat(0, JOY_HAT_LEFTDOWN) || joy_gethat(0, JOY_HAT_RIGHTDOWN));
      estadoCruzJoy[0].izquierda = (joy_getaxis(0,0) < -10000 || joy_gethat(0, JOY_HAT_LEFT) || joy_gethat(0, JOY_HAT_LEFTUP) || joy_gethat(0, JOY_HAT_LEFTDOWN));
      estadoCruzJoy[0].derecha = (joy_getaxis(0,0) > 10000 || joy_gethat(0, JOY_HAT_RIGHT) || joy_gethat(0, JOY_HAT_RIGHTUP) || joy_gethat(0, JOY_HAT_RIGHTDOWN));
      
                //Control 2
      estadoCruzJoy[1].arriba = (joy_getaxis(1,1) < -10000 || joy_gethat(1, JOY_HAT_UP) || joy_gethat(1, JOY_HAT_LEFTUP) || joy_gethat(1, JOY_HAT_RIGHTUP));
      estadoCruzJoy[1].abajo = (joy_getaxis(1,1) > 10000 || joy_gethat(1, JOY_HAT_DOWN) || joy_gethat(1, JOY_HAT_LEFTDOWN) || joy_gethat(1, JOY_HAT_RIGHTDOWN));
      estadoCruzJoy[1].izquierda = (joy_getaxis(1,0) < -10000 || joy_gethat(1, JOY_HAT_LEFT) || joy_gethat(1, JOY_HAT_LEFTUP) || joy_gethat(1, JOY_HAT_LEFTDOWN));
      estadoCruzJoy[1].derecha = (joy_getaxis(1,0) > 10000 || joy_gethat(1, JOY_HAT_RIGHT) || joy_gethat(1, JOY_HAT_RIGHTUP) || joy_gethat(1, JOY_HAT_RIGHTDOWN));
      
      say("arriba: " + estadoCruzJoy[0].arriba);
               say("abajo: " + estadoCruzJoy[0].abajo);
               say("izquierda: " + estadoCruzJoy[0].izquierda);
               say("derecha: " + estadoCruzJoy[0].derecha);
               say("");
      
   
      frame;
   end
end
[/code]


BoMbErLiNk

Hombre de esa forma estas haciendo muchas llamadas a funciones, pero si te vale perfecto  :)

Lo que si cambiaría es poner :
process listenerCrucesjoys(jugador);

Y usar jugador para los arrays y funciones, así te ahorras el añadir código extra por cada control nuevo que quieras añadir.

Noivern

#6
Tienes mucha razón, de hecho lo modifiqué para que sea un listener por jugador.
Luego edito en este mismo post el código, que acabo de terminar la funcionalidad y subir el juego (cof, cof, foro proyectos, cof cof), ahora quiero distraerme un poquito. Saludos y triple gracias bomber :)

EDIT:

Y lo de arriba lo cambié y finalmente quedó más o menos así:
[code language="bennu"]
process listenerCrucesJoys(byte numeroJugador)//numero de jugador = 0 o 1
private   
   int posicionHat;
begin
   priority = 10;//para que lo lea primero que todo   
   loop            
      
   posicionHat = joy_gethat(numeroJugador,0);//el 0 es el hat
   estadoCruzJoy[numeroJugador].arriba = joy_getaxis(numeroJugador,1) < -10000 || posicionHat == JOY_HAT_UP || posicionHat == JOY_HAT_LEFTUP || posicionHat == JOY_HAT_RIGHTUP;
   estadoCruzJoy[numeroJugador].abajo = joy_getaxis(numeroJugador,1) > 10000 || posicionHat == JOY_HAT_DOWN || posicionHat == JOY_HAT_LEFTDOWN || posicionHat == JOY_HAT_RIGHTDOWN;
   estadoCruzJoy[numeroJugador].izquierda = joy_getaxis(numeroJugador,0) < -10000 || posicionHat == JOY_HAT_LEFT || posicionHat == JOY_HAT_LEFTUP || posicionHat == JOY_HAT_LEFTDOWN;
   estadoCruzJoy[numeroJugador].derecha = joy_getaxis(numeroJugador,0) > 10000 || posicionHat == JOY_HAT_RIGHT || posicionHat == JOY_HAT_RIGHTUP || posicionHat == JOY_HAT_RIGHTDOWN;
      
   //says de prueba en consola
   say("arriba             -> 1P:   " + estadoCruzJoy[0].arriba +         "   2P:   "+ estadoCruzJoy[1].arriba);
           say("abajo              -> 1P:   " + estadoCruzJoy[0].abajo +          "   2P:   "+ estadoCruzJoy[1].abajo);
           say("izq                -> 1P:   " + estadoCruzJoy[0].izquierda +      "   2P:   "+ estadoCruzJoy[1].izquierda);
           say("der                -> 1P:   " + estadoCruzJoy[0].derecha +        "   2P:   "+ estadoCruzJoy[1].derecha);
           //say("presionando BTN?   -> 1P:   " + (numBotonPresionadoJoy(0) > -1) + "   2P:   "+ (numBotonPresionadoJoy(1) > -1));//se necesita la function que escribi mas abajo
           //say("BTN presionado     -> 1P:   " + numBotonPresionadoJoy(0) +        "   2P:   "+ numBotonPresionadoJoy(1));//lo mismo que la linea anterior
           say("");
            
      frame;
   end
end[/code]

La única gracia de esto es que sirve para obtener tanto ejes como hats y las diagonales. Lo uso para moverme en el menu y en el juego sin tener que escribir varias veces una misma condición (que vago... :D).

Además agregué una función para recoger el número del ultimo botón presionado, pero esta solo la uso en las opciones, al cambiar los botones y donde haya que "presionar una tecla para continuar", ya que solo recoge 1 botón a la vez y está haciendo ciclos for constantemente:
[code language="bennu"]
//numeroJugador = 0 o 1
function int numBotonPresionadoJoy(byte numeroJugador)//hay que declararla al comienzo del .prg para que retorne correctamente el int
                                                   //sino, retorna un unsigned int
                                                   //usaremos -1 como "no se ha presionado ningun botón"
private
   byte recorreBotones;   
begin   
   if (joy_numjoysticks() == 0 || numeroJugador+1 > 2) //si no hay joys o si se intenta usar el joy numero 3 o superior, no los toma en cuenta
      return -1; //y retornamos -1, es decir, no se ha presionado boton alguno
   end
      
   for (recorreBotones = 0; recorreBotones < joy_numbuttons(numeroJugador); recorreBotones++)//recorriendo el numero de botones del joy....      
      if (joy_getbutton(numeroJugador, recorreBotones)) //si se ha presionado alguno...
         return recorreBotones; //retornamos su numero, que corresponde al contador "recorreBotones"                              
      end
   end   
   return -1;//retorna -1, ya que el for no detectó nada
end
[/code]

Cualquier error lo corrijo a la brevedad.... :P

Noivern

Voví a corregir. Pasó que entendí mal la api del joy_gethat().
Pensé que el segundo parámetro era para preguntar por una posición en específico y que el retorno de la función era true o false.
Me dí cuenta que el segundo parámetro es el número de hat del control que estamos leyendo. Ahora si quedo más lindo y sin tanta llamada a función :P

Noivern

Me refloto, por que me surgió otra duda con los joys, en específico con el mapeado de la Caanoo:
¿Que botón en la caanoo viene siendo el select de la wiz?

¿El home?
¿O los que están a la izquierda? Esos que estan con 1 y 2 romanos donde dice help (I  y II)

Chistoso un comentario que puse más arriba, no hay que escupir al cielo xD

SplinterGU

ya no recuerdo... el help I no existe, el help II es el select y el HOME es el otro, que ahora no tengo la consola a mano.
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

Noivern

¿te recuerdas con que botón continuas cuando te matan en mi juego? Ese botón es el select en la wiz.

Entonces
¿select wiz = II caanoo? -> este es el que me importa  ;)

SplinterGU

Download Lastest BennuGD Release: http://www.bennugd.org/node/2

Noivern