my github
english | español
Waldo Urribarri HOME PROJECTS ABOUT ME


Cómo Hacer Un Dpad Básico Para Pantallas Táctiles

Como les comenté en una entrada previa, Starship Constructor es un juego estilo puzzle (tal vez no dije puzzle pero lo puedes inferir del texto), pero esto no significa que no pruebe otros estilos de juego. Quería probar algo muy básico para un plataformer y necesitaba usar un pad direccional o DPad. Dicho esto, como es usual, no sabía como hacerlo.

Entonces, miré 2 juegos que me compré en la Play Store, Eternity Warriors 2 y N.O.V.A 3. La forma en que hicieron el DPad fue "donde toques, ahí tendras el pad". Por supuesto esto no es completamente cierto, porque sólo hay una restricción, "sólo si tocas del lado izquierdo de la pantalla". Así que, esas son dos cosas a tener en mente. La segunda es la más facil, porque solo debes chequear si la coordenada X del TouchEvent está dentro de los límites.

X = [0 ... ancho_de_pantalla/2]

Ahora la primera es complicada. No porque tendrás que mostrar la imagen del DPad donde toques (eso es bastante fácil, sólo tomas las coordenadas del evento Touch Down), pero porque el primer Touch Down te dará un eje, y luego tendrás que calcular el ángulo que haces en grados con el próximo evento Touch Drag. Sip, bachillerato de nuevo. Mira esta foto.

thingy-test-screen-dpad

Nota: a este pequeño rosado lo tomé de algún lado en internet. No recuerdo donde. Sólo necesitaba algo para mover.

Luego que viste esto pienso que lo entenderás. No te preocupes, no comenzaré a darte detalles del cálculo o una clase de trigonometría, porque todo lo que necesitas es hacerlo funcionar. Lo que te daré es el método para calcular el ángulo, y qué hacer con esto.

public static float TO_DEGREES = (1/(float) Math.PI)*180;

public float angle(Vector p2) {
float angle = (float)(Math.atan2(p2.y - this.y, p2.x - this.x));
angle = angle * TO_DEGREES;
if (angle < 0)
angle += 360;
return angle;
}

¿Así que no recuerdas qué significa atan2? Bueno, ve a http://en.wikipedia.org/wiki/Atan2 y descúbrelo. Ok, hice una clase llamada Vector que tiene una coordenada X y Y, con un método llamado angle. Ese mismo método debe recibir otro Vector y calcular el ángulo que hacen entre ellos. Como debes imaginarte, el primer vector es la posición del evento Touch Down, y el vector pasado como parámetro es la posición del evento Touch Drag, o como lo llamo, direction.

Querrás llamar ese método lo más rápido posible, así que yo lo llamo cada vez que la pantalla es redibujada. Ahora preguntas, ¿Qué hago con ese ángulo? Bueno, ese método angle es llamado en realidad dentro del siguiente método de mi clase GameDpad:

public void controlObject8D() {
if(isOnScreen) {

// Dead zone
if(position.dist(direction) > getDeadZone()) {

// Check angle
float angle = position.angle(direction);

if((angle >= 337.5 && angle <= 359) ||
(angle >= 0 && angle <= 22.5))
object.position.add(directions.get("right"));

if(angle > 22.5 && angle < 67.5)
object.position.add(directions.get("bright")); // bottomright

if(angle >= 67.5 && angle <= 112.5)
object.position.add(directions.get("down"));

if(angle > 112.5 && angle < 157.5) // bottom left
object.position.add(directions.get("bleft"));

if(angle >= 157.5 && angle <= 202.5)
object.position.add(directions.get("left"));

if(angle > 202.5 && angle < 247.5)
object.position.add(directions.get("uleft")); // upper left

if(angle >= 247.5 && angle <= 292.5)
object.position.add(directions.get("up"));

if(angle > 292.5 && angle < 337.5) // upper right
object.position.add(directions.get("uright"));

}

}
}

Aquí tienes el código para un pad de 8 direcciones, como puedes ver hay un vector position y un vector direction. Position es establecida cada vez que realices un evento Touch Down en el área designada, y direction es establecida cada vez que hagas un Touch Drag. La zona muerta es la distancia entre el primer y segundo vector donde sólo quieres descartar cualquier movimiento. Esto es sólo una cosa que puedes hacer para ajustar la sensitividad del DPad. Luego calculas el ángulo entre la posición del DPad y el vector direction (la posición actual de tu dedo pulgar mientras realizas lo arrastras). Luego es sólo cuestión de específicar los ángulos de las direcciones, y sumar el vector velocidad correcto al vector posición o fuerza de tus objetos (en caso que estés aplicando físicas).

Si sólo estás interesado en 4 direcciones, puedes utilizar este método en su lugar:

public void controlObject4D() {
if(isOnScreen) {

// Dead zone
if(position.dist(direction) > getDeadZone()) {

// Check angle
float angle = position.angle(direction);

if((angle >= 315 && angle <= 359) ||
(angle >= 0 && angle <= 45))
object.position.add(directions.get("right"));

if(angle > 45 && angle < 135)
object.position.add(directions.get("down"));

if(angle >= 135 && angle <= 225)
object.position.add(directions.get("left"));

if(angle > 225 && angle < 315)
object.position.add(directions.get("up"));

}

}
}

Bueno eso es básicamente todo. Si tienes alguna pregunta, sugerencia, o algo que decir, los comentarios están abajo. Feliz codificación.