Check the new version here

Popular channels

[Homebrew 3DS] Entrada del usuario

Pensaba hacer este tutorial separado, pero ya tengo listo todo el programa desde hace un par de días y no he tenido mucho tiempo para hacer el correspondiente post. Pero no se diga más que aquí está.


Un videojuego sería muy aburrido si no tuviese interacción con el jugador. Con este post vas a salir sabindo manejar todos los controles de tu Nintendo 3DS.

Para todas nuestras funciones usaremos el prefijo hid- que significa Human Input Device(s).

Lo primero que vamos a hacer es definir cómo se van a mostrar todos los botones en la pantalla superior. Vamos a dejar la pantalla inferior para desplegar otra información:

int imprimeBotones()
{
  printf("x1b[0m");//Colorea a blanco las letras

  //L, zL, zR, R
  printf("x1b[%d;%dHL" , 6,  7);
  printf("x1b[%d;%dHzL", 6, 10);
  printf("x1b[%d;%dHzR", 6, 22);
  printf("x1b[%d;%dHR" , 6, 27);

  //Arriba, Abajo, Izq, Der
  printf("x1b[%d;%dHArriba", 12,  5);
  printf("x1b[%d;%dHAbajo" , 16,  5);
  printf("x1b[%d;%dHIzq"   , 14,  2);
  printf("x1b[%d;%dHDer"   , 14, 11);

  //A, B, X, Y
  printf("x1b[%d;%dHA", 14, 27);
  printf("x1b[%d;%dHB", 16, 25);
  printf("x1b[%d;%dHX", 12, 25);
  printf("x1b[%d;%dHY", 14, 23);

  //Select, Start
  printf("x1b[%d;%dHStart ", 20,  5);
  printf("x1b[%d;%dHSelect", 20, 23);

  //cArriba, cAbajo, cDer, cIzq
  printf("x1b[%d;%dHcArriba", 21, 12);
  printf("x1b[%d;%dHcAbajo" , 27, 12);
  printf("x1b[%d;%dHcIzq"   , 24,  8);
  printf("x1b[%d;%dHcDer"   , 24, 18);

  return 0;
}

Vamos a tener un resultado como este(tortícolis):


Vamos a crear otras tres funciones que van a ser las que dibujen nuestros botones presionados, mantenidos y liberados.

Presionados:

int imprimeBotonesApretados()
{
  printf("x1b[32m");//Colorea a verde las letras

  //L, zL, zR, R
  printf("x1b[%d;%dHL" , 6,  7);
  printf("x1b[%d;%dHzL", 6, 10);
  printf("x1b[%d;%dHzR", 6, 22);
  printf("x1b[%d;%dHR" , 6, 27);

  //Arriba, Abajo, Izq, Der
  printf("x1b[%d;%dHArriba", 12,  5);
  printf("x1b[%d;%dHAbajo" , 16,  5);
  printf("x1b[%d;%dHIzq"   , 14,  2);
  printf("x1b[%d;%dHDer"   , 14, 11);

  //A, B, X, Y
  printf("x1b[%d;%dHA", 14, 27);
  printf("x1b[%d;%dHB", 16, 25);
  printf("x1b[%d;%dHX", 12, 25);
  printf("x1b[%d;%dHY", 14, 23);

  //Select, Start
  printf("x1b[%d;%dHStart ", 20,  5);
  printf("x1b[%d;%dHSelect", 20, 23);

  //cArriba, cAbajo, cDer, cIzq
  printf("x1b[%d;%dHcArriba", 21, 12);
  printf("x1b[%d;%dHcAbajo" , 27, 12);
  printf("x1b[%d;%dHcIzq"   , 24,  8);
  printf("x1b[%d;%dHcDer"   , 24, 18);

  return 0;
}



Mantenidos(como tú):

int imprimeBotonesMantenidos()
{
  printf("x1b[33m");//Colorea a amarillo las letras

  //L, zL, zR, R
  printf("x1b[%d;%dHL" , 6,  7);
  printf("x1b[%d;%dHzL", 6, 10);
  printf("x1b[%d;%dHzR", 6, 22);
  printf("x1b[%d;%dHR" , 6, 27);

  //Arriba, Abajo, Izq, Der
  printf("x1b[%d;%dHArriba", 12,  5);
  printf("x1b[%d;%dHAbajo" , 16,  5);
  printf("x1b[%d;%dHIzq"   , 14,  2);
  printf("x1b[%d;%dHDer"   , 14, 11);

  //A, B, X, Y
  printf("x1b[%d;%dHA", 14, 27);
  printf("x1b[%d;%dHB", 16, 25);
  printf("x1b[%d;%dHX", 12, 25);
  printf("x1b[%d;%dHY", 14, 23);

  //Select, Start
  printf("x1b[%d;%dHStart ", 20,  5);
  printf("x1b[%d;%dHSelect", 20, 23);

  //cArriba, cAbajo, cDer, cIzq
  printf("x1b[%d;%dHcArriba", 21, 12);
  printf("x1b[%d;%dHcAbajo" , 27, 12);
  printf("x1b[%d;%dHcIzq"   , 24,  8);
  printf("x1b[%d;%dHcDer"   , 24, 18);

  return 0;
}



Liberados/Soltados:

int imprimeBotonesLiberados()
{
  printf("x1b[34m");//Colorea a azul las letras

  //L, zL, zR, R
  printf("x1b[%d;%dHL" , 6,  7);
  printf("x1b[%d;%dHzL", 6, 10);
  printf("x1b[%d;%dHzR", 6, 22);
  printf("x1b[%d;%dHR" , 6, 27);

  //Arriba, Abajo, Izq, Der
  printf("x1b[%d;%dHArriba", 12,  5);
  printf("x1b[%d;%dHAbajo" , 16,  5);
  printf("x1b[%d;%dHIzq"   , 14,  2);
  printf("x1b[%d;%dHDer"   , 14, 11);

  //A, B, X, Y
  printf("x1b[%d;%dHA", 14, 27);
  printf("x1b[%d;%dHB", 16, 25);
  printf("x1b[%d;%dHX", 12, 25);
  printf("x1b[%d;%dHY", 14, 23);

  //Select, Start
  printf("x1b[%d;%dHStart ", 20,  5);
  printf("x1b[%d;%dHSelect", 20, 23);

  //cArriba, cAbajo, cDer, cIzq
  printf("x1b[%d;%dHcArriba", 21, 12);
  printf("x1b[%d;%dHcAbajo" , 27, 12);
  printf("x1b[%d;%dHcIzq"   , 24,  8);
  printf("x1b[%d;%dHcDer"   , 24, 18);

  return 0;
}


Ya que tenemos esto vamos a detenernos un poco para entender cómo funciona la lectura de los botones.
Para determinar si un botón fue presionado, mantenido, o liberado; necesitamos mantener el estado anterior.
Un estado está determinado de la siguiente manera:

Si eres observador, esto puede representarse con un entero sin signo de 8 bits(2^8=32) y es precisamente lo que vamos a usar para guardar nuestro estado.

Supongamos que el bit del botón A para el tiempo 0 lo tenemos en 0 y para el tiempo 1 pasa a ser 1

t0 = 0
t1 = 1

El "evento" que se "dispara" es el de presionado.

Supongamos ahora que el bit para el tiempo 2 el bit se mantiene en 1 hasta el tiempo n-1 de la siguiente forma:

t2 = 1
t3 = 1
[ ... ]
tn-1 = 1

El "evento" que se "dispara" es el de mantenido.

Ahora supongamos que para el tiempo n cambia a 0 nuevamente:

tn-1 = 1
 tn  = 0

El "evento" que se "dispara" es el de liberado.

Ok, todo muy bonito hasta ahora, ¿cómo se relaciona esto con la programación?

Pues tiene todo que ver, lo voy a ilustrar un poco mejor:


Haberlo puesto uno encima de otro tiene una razón de ser. Las X que están entre zR y Touch no sabesmos(por el momento) qué valores tienen, puesto que eso lo rellena el sistema al hacer el escaneo de los botones.
¿Qué pasaría si hacemos una operación bit a bit del estado K con la representación de A?

Obtenemos el número 128.

¡¡¡Esto no me dice nada, carajo, habla claro!!!

Tranquilo, amiguito. Todo tiene su razón de ser.
¿Qué valores de C/C++ son falsos? 0, NULL y false.

Ya veo a dónde quieres llegar.
Si yo meto eso dentro de una condición
if voy a hacer algo cuando mi estado & A se cumpla.
¡Vaya gente más inteligente!


Claro que sí, smealum es un gran programador. Le debemos el homebrew a él y a todos los que colaboran en la comunidad.
modifiquemos nuestras funciones anteriores para que esto se mueva un poco mejor. Enviemos un dato u8 a nuestras funciones y trabajemos con él.

int imprimeBotonesApretados(u32 kDown)
{
  printf("x1b[32m");//Colorea a verde las letras

  //L, zL, zR, R
  if(kDown & KEY_L)
    printf("x1b[%d;%dHL" , 6,  7);

  if(kDown & KEY_ZL)
    printf("x1b[%d;%dHzL", 6, 10);
  
  if(kDown & KEY_ZR)
    printf("x1b[%d;%dHzR", 6, 22);
  
  if(kDown & KEY_R)
    printf("x1b[%d;%dHR" , 6, 27);

  //Arriba, Abajo, Izq, Der
  if(kDown & KEY_DUP)
    printf("x1b[%d;%dHArriba", 12,  5);

  if(kDown & KEY_DDOWN)
    printf("x1b[%d;%dHAbajo" , 16,  5);

  if(kDown & KEY_DLEFT)
    printf("x1b[%d;%dHIzq"   , 14,  2);

  if(kDown & KEY_DRIGHT)
    printf("x1b[%d;%dHDer"   , 14, 11);

  //A, B, X, Y
  if(kDown & KEY_A)
    printf("x1b[%d;%dHA", 14, 27);

  if(kDown & KEY_B)
    printf("x1b[%d;%dHB", 16, 25);

  if(kDown & KEY_X)
    printf("x1b[%d;%dHX", 12, 25);

  if(kDown & KEY_Y)
    printf("x1b[%d;%dHY", 14, 23);

  //Select, Start
  if(kDown & KEY_START)
    printf("x1b[%d;%dHStart ", 20,  5);

  if(kDown & KEY_SELECT)
    printf("x1b[%d;%dHSelect", 20, 23);

  //cArriba, cAbajo, cDer, cIzq
  if(kDown & KEY_CSTICK_UP)
    printf("x1b[%d;%dHcArriba", 21, 12);

  if(kDown & KEY_CSTICK_DOWN)
    printf("x1b[%d;%dHcAbajo" , 27, 12);
  
  if(kDown & KEY_CSTICK_LEFT)
    printf("x1b[%d;%dHcIzq"   , 24,  8);

  if(kDown & KEY_CSTICK_RIGHT)
    printf("x1b[%d;%dHcDer"   , 24, 18);

  return 0;
}

int imprimeBotonesMantenidos(u32 kHeld)
{
  printf("x1b[33m");//Colorea a amarillo las letras

  //L, zL, zR, R
  if(kHeld & KEY_L)
    printf("x1b[%d;%dHL" , 6,  7);

  if(kHeld & KEY_ZL)
    printf("x1b[%d;%dHzL", 6, 10);
  
  if(kHeld & KEY_ZR)
    printf("x1b[%d;%dHzR", 6, 22);
  
  if(kHeld & KEY_R)
    printf("x1b[%d;%dHR" , 6, 27);

  //Arriba, Abajo, Izq, Der
  if(kHeld & KEY_DUP)
    printf("x1b[%d;%dHArriba", 12,  5);

  if(kHeld & KEY_DDOWN)
    printf("x1b[%d;%dHAbajo" , 16,  5);

  if(kHeld & KEY_DLEFT)
    printf("x1b[%d;%dHIzq"   , 14,  2);

  if(kHeld & KEY_DRIGHT)
    printf("x1b[%d;%dHDer"   , 14, 11);

  //A, B, X, Y
  if(kHeld & KEY_A)
    printf("x1b[%d;%dHA", 14, 27);

  if(kHeld & KEY_B)
    printf("x1b[%d;%dHB", 16, 25);

  if(kHeld & KEY_X)
    printf("x1b[%d;%dHX", 12, 25);
  
  if(kHeld & KEY_Y)
    printf("x1b[%d;%dHY", 14, 23);

  //Select, Start
  if(kHeld & KEY_START)
    printf("x1b[%d;%dHStart ", 20,  5);

  if(kHeld & KEY_SELECT)
    printf("x1b[%d;%dHSelect", 20, 23);

  //cArriba, cAbajo, cDer, cIzq
  if(kHeld & KEY_CSTICK_UP)
    printf("x1b[%d;%dHcArriba", 21, 12);

  if(kHeld & KEY_CSTICK_DOWN)
    printf("x1b[%d;%dHcAbajo" , 27, 12);

  if(kHeld & KEY_CSTICK_LEFT)
    printf("x1b[%d;%dHcIzq"   , 24,  8);

  if(kHeld & KEY_CSTICK_RIGHT)
    printf("x1b[%d;%dHcDer"   , 24, 18);

  return 0;
}

int imprimeBotonesLiberados(u32 kUp)
{
  printf("x1b[34m");//Colorea a azul las letras

  //L, zL, zR, R
  if(kUp & KEY_L)
    printf("x1b[%d;%dHL" , 6,  7);

  if(kUp & KEY_ZL)
    printf("x1b[%d;%dHzL", 6, 10);
  
  if(kUp & KEY_ZR)
    printf("x1b[%d;%dHzR", 6, 22);
  
  if(kUp & KEY_R)
    printf("x1b[%d;%dHR" , 6, 27);

  //Arriba, Abajo, Izq, Der
  if(kUp & KEY_DUP)
    printf("x1b[%d;%dHArriba", 12,  5);

  if(kUp & KEY_DDOWN)
    printf("x1b[%d;%dHAbajo" , 16,  5);

  if(kUp & KEY_DLEFT)
    printf("x1b[%d;%dHIzq"   , 14,  2);

  if(kUp & KEY_DRIGHT)
    printf("x1b[%d;%dHDer"   , 14, 11);

  //A, B, X, Y
  if(kUp & KEY_A)
    printf("x1b[%d;%dHA", 14, 27);

  if(kUp & KEY_B)
    printf("x1b[%d;%dHB", 16, 25);

  if(kUp & KEY_X)
    printf("x1b[%d;%dHX", 12, 25);
  
  if(kUp & KEY_Y)
    printf("x1b[%d;%dHY", 14, 23);

  //Select, Start
  if(kUp & KEY_START)
    printf("x1b[%d;%dHStart ", 20,  5);

  if(kUp & KEY_SELECT)
    printf("x1b[%d;%dHSelect", 20, 23);

  //cArriba, cAbajo, cDer, cIzq
  if(kUp & KEY_CSTICK_UP)
    printf("x1b[%d;%dHcArriba", 21, 12);

  if(kUp & KEY_CSTICK_DOWN)
    printf("x1b[%d;%dHcAbajo" , 27, 12);

  if(kUp & KEY_CSTICK_LEFT)
    printf("x1b[%d;%dHcIzq"   , 24,  8);

  if(kUp & KEY_CSTICK_RIGHT)
    printf("x1b[%d;%dHcDer"   , 24, 18);

  return 0;
}


Yo normalmente en un juego presiono dos botones al mismo tiempo para que ocurrauna acción. Con esto no se puede saber si fueron presionados en conjunto a menos que anides un if. ¡LENTO! Jaque Mate

No, no y no. Tranquilo amiguito. Mira las cosas desde otra perspectiva.
Las operaciones de bit nos ayudaron antes y nos pueden ayudar para lo que pides(exigente).

Hasta ahora no tenemos una forma de volver a nuestro HB menu. Lo único que podemos hacer es colorear el botón de Start


Si nos ayudamos de las operaciones de Boole podemos hacer que al presionar Start y, por ejemplo, abajo en el d-pad regrese al menú

if( (kDown & KEY_START) && (kDown & KEY_DDOWN) ) break;


¡¡Pero que difícil!!, ¡hay que ser demasiado presiso!

Con nada se te da gusto.
Puedes combinar con una operación de bit los botones presionados y mantenidos. quedando, por ejemplo, kDown | kHeld | kUp aunque tal vez esto no sea muy útil...

if( ( (kDown | kHeld) & KEY_START ) && ( (kDown | kHeld) & KEY_DDOWN ) ) break;// Con esto va a ser más sencillo regresar al menú




Por ahora es todo, espera la segunda parte
0
0
0
0
0No comments yet