<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sam Ellis</title>
    <description>The latest articles on DEV Community by Sam Ellis (@samellis).</description>
    <link>https://dev.to/samellis</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4243289%2F0b6e218b-6436-4cf4-b1ed-fbb450f2dd32.png</url>
      <title>DEV Community: Sam Ellis</title>
      <link>https://dev.to/samellis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/samellis"/>
    <language>en</language>
    <item>
      <title>Building a GPS scavenger hunt app: the unglamorous problems that decide whether it works</title>
      <dc:creator>Sam Ellis</dc:creator>
      <pubDate>Sat, 14 Nov 2026 00:40:13 +0000</pubDate>
      <link>https://dev.to/samellis/building-a-gps-scavenger-hunt-app-the-unglamorous-problems-that-decide-whether-it-works-1nmm</link>
      <guid>https://dev.to/samellis/building-a-gps-scavenger-hunt-app-the-unglamorous-problems-that-decide-whether-it-works-1nmm</guid>
      <description>&lt;p&gt;Most write-ups about location-based games stop at the fun part: you turn up somewhere, match what you see with your camera, and the next spot unlocks. I work on exactly that kind of app — &lt;a href="https://pinghunt.com" rel="noopener noreferrer"&gt;Ping Hunt&lt;/a&gt; generates a hunt near you, walks you to real locations by GPS, and checks the scene against your camera.&lt;/p&gt;

&lt;p&gt;Here are the problems that actually cost us time, and what we learned solving them.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. GPS accuracy is a distribution, not a number
&lt;/h2&gt;

&lt;p&gt;The most common bug report in a location game is &lt;em&gt;"it says I'm at the right place but won't unlock"&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Android's &lt;code&gt;Location.getAccuracy()&lt;/code&gt; is a radius of confidence in metres, and it is rarely what people assume. On a phone sitting flat on a café table you will often see 5–20 m of horizontal accuracy. Indoors, behind a glass wall, it can be 50 m or worse, and in a dense city canyon it degrades further because the receiver is tracking reflections off buildings.&lt;/p&gt;

&lt;p&gt;So never ask "is the user at this location?" Ask "is the user inside the radius of this location, &lt;em&gt;expanded by the current accuracy&lt;/em&gt;?"&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tight spots (a specific bench, a specific shopfront): 20–30 m&lt;/li&gt;
&lt;li&gt;General spots (a park, a square): 50–80 m&lt;/li&gt;
&lt;li&gt;Always: also accept the fix if the distance is within &lt;code&gt;radius + min(accuracy, 40)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last term is the one that matters. If the phone says "I might be within 40 m of you", refusing a 35 m reading is simply wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Do not trust a single fix
&lt;/h2&gt;

&lt;p&gt;A single &lt;code&gt;Location&lt;/code&gt; callback can be a cached fix from ten minutes ago. On a cold start Android happily hands back the last known location before a fresh one arrives, and a stale fix is worse than no fix because it can be kilometres away.&lt;/p&gt;

&lt;p&gt;Always attach a timestamp and discard anything older than roughly 15 seconds. If you want more certainty, require two consecutive fixes that agree with each other before unlocking — a cheap hedge against the wandering positions a phone produces while it is moving.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The camera match needs to be forgiving
&lt;/h2&gt;

&lt;p&gt;Camera matching sounds like the hard part. It isn't, if you design for tolerance rather than precision.&lt;/p&gt;

&lt;p&gt;Two rules have done most of the work for us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Never compare against a single reference photo.&lt;/strong&gt; One photo of a location is one lighting condition, one camera, one season.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Score, don't gate.&lt;/strong&gt; Compute how well the captured image matches and accept above a fairly low threshold. It is much better UX to let someone through with a slightly imperfect match than to lock them out in the rain.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The thing that is worth doing properly is the &lt;em&gt;feedback&lt;/em&gt;. If a match is rejected, say why in a way that helps: not "wrong photo", but "that looks like the fountain, but we are looking for the red door on the north side". The difference between a frustrating wall and a fun retry is usually the quality of the error message.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Do the maths before you ask for permissions
&lt;/h2&gt;

&lt;p&gt;People deny location permission when they cannot see why you want it, and they revoke it when it feels invasive. The request that works is specific and adjacent to the value:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ping Hunt uses your location to guide you to the next spot. Your location stays on your phone.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then actually mean it — do not ship a background location permission you never need. A location game only needs foreground location while the hunt is open, and only for as long as the hunt is open.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Design for a bad signal
&lt;/h2&gt;

&lt;p&gt;A hunt will happen in a basement, a forest, and a basement in a forest. The interesting failure mode is not the missing fix — it is the &lt;em&gt;stale&lt;/em&gt; one, where the app happily says "you are 3 metres from the target" based on a fix from before you walked into the tunnel.&lt;/p&gt;

&lt;p&gt;A practical fallback is to let the player confirm manually when the GPS has been unhelpful for a while, with a clear prompt: &lt;em&gt;"Looks like the signal is poor here — are you at the spot with the blue door?"&lt;/em&gt; That single escape hatch removes most of the support messages a location app ever receives.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. The battery budget is a design constraint
&lt;/h2&gt;

&lt;p&gt;Everything above is expensive if you leave GPS on. A useful pattern is to register for location updates only while a hunt is active, and to drop to a slow interval when the player is stationary and speed up when they are moving.&lt;/p&gt;

&lt;p&gt;Two things worth measuring rather than guessing: how long a typical hunt session lasts on a mid-range phone, and how much of that is the GPS being left on while the screen is off.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;None of this is exotic, and that is the point. The parts of a location game that feel like game design — how the clues are written, how the camera step feels, whether the next unlock is satisfying — are the parts that are easy to iterate on.&lt;/p&gt;

&lt;p&gt;The parts that decide whether people finish a hunt are the boring ones: whether you trust a 35-metre fix when the phone says 40, whether you throw away the stale location from before the tunnel, and whether the error message tells someone what to do next.&lt;/p&gt;

&lt;p&gt;If you are building something like this, start with the tolerance of the distance check and the freshness of the fix. They are a few lines of code each, and they remove most of the failure you would otherwise spend weeks chasing.&lt;/p&gt;

</description>
      <category>gps</category>
      <category>mobile</category>
      <category>android</category>
      <category>geolocation</category>
    </item>
  </channel>
</rss>
