Systems Breakdown - Swipe Movement Controls
Even when they try, humans don't swipe in straight lines.
It's true! You'll realize it after about 5 seconds of prototyping any sort of swipe-based control system, and then you'll wonder why you didn't think of it sooner. Even our swiftest gestures have a lot of variation in them, and because of that, developing a swiping control scheme that both feels good and allows for consistent accuracy is MUCH harder than it seems. Because of that, creating a buttery-smooth control scheme was my #1 priority right from the beginning of CROSSNIQ's development - without it, nothing else would matter.
CROSSNIQ's swipe control system is made of four distinct parts! I'll overview each of them one by one:
- Directional detection
- Proportional speed
- "Axial bias"
- "Proximity cones"
We'll use this simple move of a tile one space to the right to demonstrate/diagram all of the systems.
The obvious starter for swipe-based movement is: which direction is the player swiping in?
Fortunately, this one is pretty easy to determine. A simple check on the X and Y values of the touch/mouse point, in relation to that of the touched tile, can determine the direction based on the positivity/negativity of X and Y values.
One additional precaution must be taken, however - if all we check are +/- of X and Y, this means that the slightest shift, no matter how small, will register as a move - even one as simple as your finger twitching! To prevent this, we create a basic "deadzone" (or radius which is deemed too small to be registered as a movement.)
Here's a question for you: how quickly should a tile move when it is swiped?
There's no one correct answer... if you're moving it a far distance, you certainly wouldn't want the tile speed to be slow, since the controls would feel sluggish. However, if you crank the speed up, small movements (like ours) end up feeling jarring and imprecise.
The answer I decided on is: both! Fortunately, there's a very simple way to have the speed at which a tile travels adjust itself in proportion to a swipe.
To do so, we simply measure the vector magnitude (if you're unfamiliar in this case, think of it as the actual size of a directional vector, though the reality is slightly more complicated), and with a little fiddling, we can use it as a multiplier for a base speed value. The greater the distance between the tile and the point a swipe stops at, the faster it will travel there! This adds an elegant and responsive "snappy" feel to the controls.
With these two systems in place, we have the basics of what's needed for a swipe movement system to work on paper. However, even a short amount of time playing around with this system will expose a litany of problems - mainly our aforementioned conundrum of humans not swiping in straight lines, even when they intend to. As a result, our current system would feel "touchy", "twitchy", and "inaccurate" - when in reality, the only inaccurate element is the human hand.
Because of this, we have to engineer a system that does its best to assume which way a player is intending to swipe in. There are many, many, MANY ways to skin this particular cat, ranging from the basic (my system) to the complex (actual gesture recognition software). Since CROSSNIQ has the benefit of being locked to four-directional movement, I had the liberty to engineer a lightweight system that I refer to as "axial bias".
The premise of the axial bias system is that with a given swipe, the player is more likely to continue moving on the axis (vert or horiz) that they are presently moving on or last moved on.
The first piece of the axial bias system is simple: simply add an additional amount of distance that the user must swipe in order to register movement on the axis perpendicular to their current/last movement. Consider it a "cushion", or an extension of the previously mentioned deadzone.
I presumed that this system would work well enough on its own to make the controls smoother. However, users quickly told me that small, precise movements onto the perpendicular axis to their last move (the axis with bias applying) felt "sticky" and "difficult to make precisely". To remedy this, I applied a bit of system #2 to this problem. In the current version, starting from a low base value, I increase the axial bias amount in proportion with the magnitude of the swipe's directional vector. This means that small, precise movements have a low axial bias, and sweeping, broad swipes (more likely to be inaccurate) have much more axial bias.
This last piece is a bit of a weird one, but nonetheless necessary. During testing, even with the previous three systems in place, players were running into an odd problem - when they made a small swipe closely aligned with the 45 degree diagonals of a tile, it would begin to move rapidly back and forth on one axis, as if it were confused on which direction it ought to be going in. Shame on me for this, but I never really took the time to figure out exactly why... it could be due to floating point rounding, or it could be due to the swipe's location reaching a point that would register contradicting movement depending on where the tile was currently wiggling. Regardless, I applied a blunt solution to the problem - if your swipe is short enough, it only is considered to be movement if it is within a certain range of angles from the center of the tile you're currently swiping. These "proximity cones" kind of emulate the zones of an analog stick (at least, that's how I envisioned it).
Essentially, if your swipe is a). short, and b). isn't within a + or - amount of degrees from the absolute direction (up/down/left/right) you're trying to swipe in, it is disregarded. If your swipe is long, though, it's far away enough from the base tile to where it doesn't become a problem. So, rather than extending out into infinity, these proximity cones cut off at a certain distance from the tile.
It's a hard concept to write out, so hopefully this (rough and not dead-accurate) diagram explains the rest.
Put It All Together, And... Movement!
This post was rather long-winded, but for good reason - the movement code in CROSSNIQ is some of the most complex in the game, right behind the system for tile wrapping and object pooling (which will be another post). Hopefully this gives developers setting out on their first touch-based project a little bit of inspiration!
Leave a comment
Log in with your itch.io account to leave a comment.