Inspiration
What it does
How we built it
Challenges we ran into
Accomplishments that we're proud of
What we learned
What's next for EyeMole - Eye Whack-a-Mole
Inspiration
Whack-a-mole is the most physical arcade game there is: a hammer, a fist, a satisfying thump. I wanted to see what happens when you take the hands away completely. I had already built a small eye-tracking engine for my series of gaze games, and whack-a-mole felt like the purest test of it: the target is exactly where you are looking, so the controller is your attention itself.
What it does
EyeMole is whack-a-mole you play with your eyes only. The front TrueDepth camera tracks where you look; hold your gaze on a mole for 0.4 seconds and the hammer drops. No tapping, no swiping.
- 60-second score attack. Chain correct decisions to build a combo; the pace tightens over the round and a back row of holes opens up at 25 seconds.
- The dilemma. Looking is both how you identify and how you attack. A chick sometimes pops up — stare too long and you whack it (−5 seconds). Glance, recognize it, tear your eyes away, and you earn a bonus.
- A cast that plays with your attention: a Gold Mole that spawns in the hole farthest from where you're looking, a shiny Flash Mole decoy worth nothing, and a Helmet Mole boss that needs 1.5 seconds of steady gaze.
- Leaderboards (Today / Monthly / All-Time) on Game Center, in a ranking screen you can browse by gaze.
- Onboarding, a five-point gaze calibration, and gaze-dwell menus throughout.
It's free with ads and a heart system (3 hearts, one back every 10 minutes, or watch a video). A one-time EyeMole Pro purchase removes ads and makes hearts unlimited.
How I built it
- SwiftUI + SceneKit for the 3D field and procedurally modeled moles, chicks and hammer; haptics and synthesized sound effects on every hit.
- ARKit face tracking through EyeTrackKit, my own Swift package shared across my gaze games: per-eye gaze estimation, One Euro filtering, and a 2D affine calibration.
- Gaze selection uses hysteresis (enter at 100 pt, keep holding up to 145 pt) so a jittery gaze doesn't jump between holes.
- RevenueCat handles the Pro purchase: a single
proentitlement, a lifetime package in the current offering,customerInfoStreamfor live status, and restore. I built my own purchase screen so it can be operated by gaze. - RevenueCat Ad Monetization with the AdMob adapter (
loadAndTrack) so banner and rewarded ad revenue shows up next to IAP revenue. - Game Center recurring leaderboards for daily and 30-day rankings.
Challenges I ran into
- App Review. The first build was rejected twice under 2.5.1 ("TrueDepth API found but no feature uses it"). A written explanation wasn't enough; a real-device screen recording was. Then came the face-data questionnaire, which I answered by documenting EyeMole in my privacy policy.
- The hammer. I rebuilt the strike four times before it felt right: the wind-up is the idle pose while it follows your gaze, and the hit is a single arc around the grip.
- Gaze bugs you can't see in a simulator. Dwell progress was keyed by hole number, so a newly spawned chick could inherit progress and get whacked instantly. Coming back from the background never restarted the AR session, and my first fix paused on every notification banner — killing the round.
- Leaderboards that I created but hadn't released simply returned nothing on device.
What I learned
With gaze, fairness is the whole game. Every number — dwell time, hold radius, how long a boss stays up — decides whether a miss feels like your fault or the app's. And the simulator can't see your eyes: anything involving the camera has to be proven on a real device, then proven again to the reviewer.
What's next
More characters that play with where you look, continued tuning of gaze accuracy across devices, and bringing what I learned here to the next games in my eye-tracking series.
Built With
- admob
- app-tracking-transparency
- arkit
- avfoundation
- fastlane
- gamekit
- revenuecat
- scenekit
- swift
- swiftui
- xcode
Log in or sign up for Devpost to join the conversation.