Tap-to-select: Common pitfalls and a robust solution

"Tap on the screen": A meme showing a water tap


tl;dr: This post covers a couple important issues with tap-to-select and how to solve them.


Tap-to-select: Common pitfalls and a robust solution

Tap-to-select is a common mechanic in many games. However, it's often implemented poorly, and is hard to use for the player!

Let's start simple: Use an object's collision shape

In most games, each character / item / selectable-thing has a defined collision shape. This is useful for other features like detecting collisions with the level. But we can re-use this collision shape for tap-to-select. We simply check whether the position of a given mouse/touch event intersects the collision shape.

However, there are a couple important problems with this approach: overlapping objects, and zoomed-out cameras.

Dealing with object overlap

An animated GIF of a recording from Meteor Power showing multiple collision-shapes that overlap.
Overlapping collision-shapes.

When objects overlap, and a tap intersects more than one object, a naïve implementation usually just chooses whichever object was added to the level first.

But that's not ideal. For example, if object A and object B overlap, and the tap position is near the center of object B, and near the edge of object A, then the player probably intends for the tap to select object B. We want to make sure our implementation won't return object A in this case!

A good solution for this problem is to check all of the intersected objects, and only use the object whose center is closest to the tap.

Dealing with camera zoom

An animated GIF of a recording from Meteor Power showing a collision-shape with different zoom levels.
Using a level-space collision-shape.

Another important problem relates to camera zoom. When the camera is zoomed way out, our selectable objects become very small, and their collision shapes may be less than a few tiny pixels across. These objects will then be very difficult to tap with fat fingers on a tiny mobile-phone screen!

A good solution for this problem is to select whichever object is closest to the tap.

But we also need to make sure that the tap is still within a reasonable radius. If the player taps too far from any object, we don't want to select the closest object. So for this to work, we need to define a tap-radius for each object.

This tap radius must be defined in screen space, since a level-space radius would suffer from the original problem of getting smaller when zoomed-out.

However, a screen-space radius might not make sense when zoomed-in, since the object's level-space shape could then be a lot bigger than the screen-space radius, and the player might still expect to be able to select the object by tapping anywhere within its shape.

An animated GIF of a recording from Meteor Power showing a tap radius with different zoom levels.
Using a screen-space tap radius.

Best of both worlds

Fortunately, we can combine both solutions, and use both level-space object shapes and screen-space tap-radii.

  • For each tap, we first check for all objects whose shape is intersected by the tap.
  • If there is some intersected object, we use whichever intersected object is closest to the tap.
  • If there is no intersected object, we then check for the closest object whose screen-radius encompasses the tap position.

An animated GIF of a recording from Meteor Power showing a collision-shape and tap radius with different zoom levels.
Combing level-space collision-shape and screen-space tap radius.

Source code

Here's an open-source implementation of this tap-to-select system.


🎉 Cheers!


This is a simple icon representing my sabbatical.

Comments