How To Make A Basic Dpad For Touchscreens

As i told you on an earlier post, Starship Constructor is a puzzle game (maybe i didn't state puzzle but you can infer that from the text), but that doens't mean that i don't test other genres. I wanted to test something really basic for a platformer and i needed to use a directional pad or DPad. That being said, as usual, i didn't know how to do it.

So, i looked at 2 games i bought from the Play Store, Eternity Warriors 2 and N.O.V.A 3. The way they made the Dpad was "wherever you touch, there you'll have your pad". Of course this is not entirely true, because there's only one restriction, "only if you touch on the left side of the screen". So, that's two things to have in mind. The second one is the easiest, because you can just check if the TouchEvent X coordinate is between the boundaries.

X = [0 ... screen_width/2]

Now the first one is tricky. Not because you'll show the Dpad image wherever you touch (thats pretty easy, just take the coordinates of the Touch Down event), but because the first Touch Down will have to give you an axis, then you will have to calculate the angle you are making in degrees with the next Touch Drag event. Yup, highschool all over again. Take a look at this picture. Note: i took that little pink guy from somewhere over the internet. Can't remember where. Just needed something to move around.

Now that you saw this i think you'll understand it. Don't worry, i won't start giving you the details of the calculation or a trigonometry class, because all you need is to make it work. What i'll give you is the method to calculate the angle, and what i do with it.

``` 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; } ```

So you dont remember what atan2 means? well go to http://en.wikipedia.org/wiki/Atan2 and find out. Ok, i made a class named Vector that has an X and Y coordinate, with a method named angle. That same method can receive another Vector and calculate the angle they make. As you may guess, the first vector is the position of the Touch Down event, and the Vector passed as a parameter is the position of the Touch Drag event, or as i call it, direction.

You'll want to call that method as quickly as possible, so i call it everytime the screen is redrawed. Now, what do i do with that angle you ask? Well, that method angle is called in fact within the the next method of my class 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")); } } } ```

Here you have the code for a 8-direction DPad, as you can see there is a position vector and a direction vector. The position is set whenever you make a Touch Down event on the designated area, and direction is set whenever you make a Touch Drag. The dead zone is the distance between your first and second vector where you just want to discard movement. This is just one thing you can do to adjust sensitivity of the DPad. Then you calculate the angle between the position of the DPad and the direction Vector (your current thumb position while dragging). Then is just a matter of specifying the angles of the directions, and adding the correct speed vector to your objects position or force vector (if you are applying physics).

If you are just interested in 4 directions, you may use this method instead:

``` 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")); } } } ```

Well that's pretty much it. If you have any questions, suggestions, or anything to say, the comments are below. Happy coding. 