I need dual joysticks for a touch screen for an upcoming hobby project. I couldn't find a lot of documentation to do it and found it wasn't as easy as I originally thought. So I figured it out myself. I thought I would share how I did that the best I can.
GitHub link for repo of prototype: https://github.com/mepis/Construct2/tree/master/Dual%20Joysticks
The article I wrote for my blog sharing the exact same thing : http://kurie.us/how-to-make-dual-joysticks-in-construct-2/#more-127
Capx example file: http://www.kurie.us/Downloads/construct2/DualJoysticksV1.0.zip
I'm a bit lazy, so the rest is mostly a copy and paste job from my blog. If anyone has any questions or needs a better explanation, please let me know. I'll be happy to help how ever I can when I have the time.
First, I assume a couple of things with this prototype:
No more than two touch points will ever be used at the same time, or if there are, the first two touch points will be either joystick.
There will be times when either joystick is initiated separately. As such, different touch combinations and events needed to be handled. This will explain the convoluted events used. I found them to work most accurately in this specific order.
I built this prototype with a couple of idealisms in mind:
The joysticks must disappear when not in use. I wanted to free up screen real estate when it wasn’t used.
The joysticks will be created when the screen is touched and destroyed when touch has ended. The joysticks will be created at the point that the finger touches the screen. I’ve always found joystick control on touch screens to be annoying. Not everyone has the same sized fingers. I tend to miss buttons easily or I get annoyed about the amount of screen real estate used up by touch controls. I wanted to solve both of these issues the best I could.
A couple of points to keep in mind:
The graphics don’t matter and only exist as a point of reference. As such, each graphic can be removed, changed, shrunk in size, or blown up according to needs. All interactions are based around the points in which the finger first touches the screen, not the objects on the screen.
The global variables event sheet contains two variables that should be altered per game and target device: XThreshold and YThreshold. This will adjust how quickly the left joystick reacts to movement from its zero point.
The outside ring around the left joystick only acts as a point of reference for the player. It allows the player a point of reference where to zero out the joystick. This can be removed though it’s suggested to have some graphic to signify the center of the joystick.
First, let’s go through the layout.
Only one object on this example has any behaviors. The red triangle, or the player, has 8-way movement attached to it. I use this to make life easier to move the player around the screen. The joystick will interact with this behavior later on.
It’s important to note that the ‘LTP’ and ‘RTP’ are two giant, clear objects that cover the entire windows. ‘LTP’ stands for ‘left touch panel’ while ‘RTP’ stands for ‘right touch panel’. Both objects are used to listen for and register touch. The left touch panel will be used for the left joystick that controls movement while the right touch panel will be used for the right joystick that will be used for rotation.
The left joystick is a two piece system per say. The smaller black dot acts as a visual representation of the thumb pad while the larger black ring acts as a pseudo boundary for the thumb pad. The boundary acts as a point of reference for the player to indicate where to return to so that movement can be stopped. The black thumb pad will follow the finger and move in all directions.
The red circle only rotates. It’s best to visualize this as a knob of sorts. The player can rotate this knob left and right. The player direction will match the angle at which this joystick is rotated.
Finally, the event sheet.
First, let me explain what’s going on here. The event sheet is broken into three groups, or functions. The first is for debugging labels. This can be ignored. It was only used in the process of making this to see the numbers of the inputs. The next two groups, or functions, control either the left joystick or the right joystick. I had to create three screen shoots (all below) to display the entire event sheet.
Let’s start with this screenshot. First, ignore the debugging group and focus on the Touch Controls group. Within the Touch Controls group is a separate group for the left joystick and the right joystick. Both the groups for the left and right joysticks are designed almost the same with adjustments only for the type movements they provide.
Let’s look at the left joystick first. First, I check to see if the player is touching the screen. If they aren’t, the joystick is destroyed and cleared from the screen. The right joystick is the same. I also set the touchID variable for the left joystick to -1. This is important because the code checks for existing touchIDs later on. Zero is a valid touchID so we can’t have the variables default to zero. Otherwise it causes confusion later on when the joysticks are created.
Next, I check to see if the player is touching the screen, specifically the corresponding touch panel for the joystick (Eg. left touch panel for left joystick and right touch panel for the right joystick).
Next I check for movement logic. This is a bit more complicated to explain. When the player touches the screen, the game needs a point of reference for finger movement. For example, the game needs to know if the player moved their thumb up or down. Notice the argument ‘Touch.XforID(leftTouchID)’. This is also very important. It checks for the X and Y coordinates of the specific touchID.
So, I store the X and Y values of the first touch in a couple of variables to reference. Then, for each step thereafter, I check the position of the finger on the screen to see where it is in relation to the initial touch point. If the finger moved in the right direction (up, down, left, right), the 8-way movement behavior is called to move the player around the screen.
Next, I check for either creation or destruction of the joystick. I save this for last. Please note, we are still technically in a ‘if-else’ type of statement. Otherwise, if the player is touching the left touch panel, check for everything I wrote above and the next paragraph.
This part gets a little silly. All three of the first conditions do the same thing. They check to see if the player is touching the screen, and if they are, they create the joystick. They check against different touchIDs though. If a touchID of the other joystick is a specific value, this code checks the touchID value of this joystick for a specific value. This needs to be done to clear up some confusion when the code goes to create a joystick. If both touchIDs for both the left and right joystick are the same value, weird things happen. As such, I need to assign touchIDs very specifically and that all depends on the current value of the other joystick.
Both joysticks go through this process. Both joysticks check the other’s values before assigning their own.
The final step is register and move the graphic for the joystick.
The right joystick follows the exact same logic and has almost the exact same wording and conditions. It should be pretty easy to follow if you understand the above explanations.