Original Author: Alex Moore
This post is going to be a little different to my usual posts, as it’s going to be more akin to how I write a document for a mechanic. The mechanic in question is a challenge I set myself: try and design a touch based joystick that, in a single stick, provides the functionality that usually requires two. I’ve decided to call this task “Single Joystick”.
Read on to see how I went about finding out if such a this is possible…
For lots of types of games, touch screens are a fantastic input device. They currently don’t offer any sense of tactile response, though I’m sure that’s coming in time. Today, the games which are most successful on our phones and tablets are ones that use touch screens to their advantage. There is demand, however, to put games that have been very successful on PC and console straight onto our phones and tablets; by which I refer to first person and third person action games.
To date, this has often been done by drawing two virtual joysticks on the screen, one in each corner. These react in a similar fashion to how the physical joysticks do on a traditional console controller, with the left stick controlling XY movement and the right stick controlling rotation and looking up and down.
This approach has two main flaws:
- The amount of screen space required for the joysticks
- To hold the device so you can use both thumbs, you effectively remove the ability to use any other fingers at the same time.
In addition, such approaches:
- Assumes that the user is familiar with twin joystick controls from console games, which requires a significant amount of skill and dexterity.
- Often does not offer support for left handed players
- Does not offer support for gamers with reduced mobility
I think these are all fairly well known, but it’s still an accepted approach because there doesn’t seem to be a better alternative.
Or is there?
The initial concept is to combine moving and rotating into a single joystick. This is something that is only possible on a touch-based device, as the user can be very precise about exactly where they are touching the screen.
The joystick is made up of 3 core elements:
- The move gizmo
- The rotate gizmo
- The nub graphic
Arranged as such:
The Move Gizmo
The move gizmo works the same as in an ordinary two-stick system:
- The centre of the graphic is stored as (x,y).
- The radius of the gizmo is known (stored as a variable, InnerRadius, to allow for tweaking)
- When the user touches the screen, a check is done to ensure they are inside the move graphic.
- If they are, then the touch location is stored as (x1, y1):
- The amount to move the player by is simply calculated by:
- Position.x = (x1 – x) / InnerRadius
- Position.y = (y1 – y) / InnerRadius
- This returns a value between 0 – 1, which gets applied directly to the player movement code per frame, where a multiplier is added as a scalar to allow for faster movement if required.
- Because of the size of the stick, there is unlikely to be any need to apply an acceleration curve to this movement. There may be a need to implement a dead zone, to be decided in testing.
The Rotate Gizmo
The rotate gizmo fully encompasses the move gizmo, and has an internal size stored as the variable OuterRadius. The rotate gizmo is only active when the user’s touch position is between InnerRadius and OuterRadius.
To calculate the rotation amount, the gizmo works off angles rather than absolute location of the touch. This is very different to how rotate joysticks usually work.
- At the point where the user’s touch enters the rotate gizmo, the position is stored and a vector is calculated from that position back to the centre of the joystick (x, y):
- The user is now required to keep their touch within the rotation gizmo, and the position they move to creates an additional vector, current vector. The angle, θ, between this new vector and the original determines how much the user rotates per frame:
- If the user rotates clockwise past the initial vector then they turn clockwise, and likewise turning anti-clockwise past the initial vector turns them that way.
- There may need to be a maximum rotation speed, to be determined with testing.
- If the user’s touch moves outside of the OuterRadius then the joystick deactivates and resets.
- If they move their touch back inside the move gizmo, the rotation stops and movement resumes from where the updated touch resides.
- Releasing the touch or moving outside of OuterRadius stops all movement and rotation, and resets the joystick to its initial phase.
- If the user’s initial touch is within the rotate gizmo then the user can look around on the spot.
The key to Single Joystick is this:
If the user starts touching inside the move gizmo and then moves into the rotation gizmo, (x1,y1) remains at the point that they ‘pierced’ the rotation gizmo. This allows for circle strafing on a single touch.
This is just a simple graphic that moves to reflect the current touch position, assuming the user is inside the OuterRadius.
The one downside of the Single Joystick is that it doesn’t have any support for controlling vertical look. There are several possible solutions to this by using additional touches or lock-ons, but for initial prototyping a simple height check slightly in front of the player camera (2m) is performed. If the check is lower than the player height then make the camera look up, and likewise look down if it is higher:
Testing the theory
Writing a game mechanic requires a leap of imagination and, for me, often involves a great degree of holding the input device, closing my eyes and moving my fingers trying to imagine myself playing the game.
This is great, and helps iron out any major flaws with a specification. But nothing beats actually playing it.
As I’m currently freelance, access to programmers is limited. However, access to game engines isn’t: especially with Unity available for free. I already had a licence for iOS deployment, and once registered as an Apple developer I could very quickly build projects and get them running on my iPad. Note: this is not to say the mechanic is only devised for Apple devices, but purely to say that’s what I had to hand and thus it made sense to use it.
So, here’s a prototype of this mechanic running. The stuttering is due to my capture method off my iPad, rather than framerate – as you’d hope / expect, it runs at a solid 60fps currently.
As you can probably see, the concept works to a decent degree but isn’t yet completely robust. I’ve been playing with this for about a week now, tweaking bits here and there. If you’ve read everything above, you’ll notice no mention of the icon that lights up when the touch is inside the rotate gizmo: that came about simply because you can’t see the nub (or, in fact, half of the background) when you’re actually touching it.
There’s quite a few more improvements to make, but I thought that this project had hit a point where I should write about it and see if anyone else has any feedback. I’ve tested it on a few people, with varying degrees of success – everyone needs to be told how it works, so at the ‘intuitive’ point from the brief it’s not quite there yet.
I’ll hopefully do a follow up post in a few weeks with improvements I’ve made. For now though, hopefully I’ve started to set designers everywhere a challenge: find a way to make touch screen joysticks better.