Phaser Swipe Input: Touch Controls for Mobile Games
Phaser Swipe Input: Touch Controls for Mobile Games
Direct answer: Implement swipe in Phaser 3 by listening to pointerdown and pointerup, comparing the delta against a small pixel threshold (we use 26px) to distinguish a swipe from a tap. Keep keyboard and mouse-drag paths working in parallel — mobile players expect swipe, desktop players expect keys.
We’re building Merge Fish 2048 (a 2048-style merge game) with exactly this setup on Phaser 3.90 + Vite. This guide walks through the input module as we use it in development, with the numbers that matter.
1. The core swipe detector
Phaser gives you the pointer events; you supply the math. Our approach: record the pointer position on pointerdown, and on pointerup compare it with the final position.
| Parameter | Our value | Why |
|---|---|---|
| Swipe threshold | 26 px | Small enough for fast swipes, big enough to ignore finger jitter |
| Move detection | pointerup - pointerdown | Simpler than live velocity tracking; reliable for a 4-direction grid |
| Input channels | swipe + mouse drag + keys | Covers mobile, tablet, and desktop with one code path |
const SWIPE_THRESHOLD = 26;
this.input.on('pointerdown', (p) => {
this.downX = p.x;
this.downY = p.y;
});
this.input.on('pointerup', (p) => {
const dx = p.x - this.downX;
const dy = p.y - this.downY;
if (Math.abs(dx) < SWIPE_THRESHOLD && Math.abs(dy) < SWIPE_THRESHOLD) return; // tap
const dir = Math.abs(dx) > Math.abs(dy) ? (dx > 0 ? 'right' : 'left')
: (dy > 0 ? 'down' : 'up');
this.moveBoard(dir);
});
One trap: if you only test pointerup, a tap looks like a tiny swipe. The threshold guard above is what keeps taps from nudging the board — in our first build, a tap on the pause button would occasionally shift a row of fish before the button handler ran.
2. The 1.2 ratio rule for portrait vs landscape
Mobile devices are not one canvas. We keep a single 1280×720 logical design and switch layout by viewport ratio:
const RATIO_THRESHOLD = 1.2; // < 1.2 portrait, >= 1.2 landscape
Every scene reads this single constant from the config file — no scene redefines its own copy. When the device rotates, we reload the scene with the matching layout. This matters for swipe games specifically: in portrait, the board lives in the lower half, so swipes should be captured across the whole screen; in landscape, the board is centered and we disable full-screen drag on UI buttons.
3. Keyboard and mouse fallback (free desktop support)
The same board-move function drives all input paths:
this.input.keyboard.on('keydown', (e) => {
const map = { ArrowUp: 'up', ArrowDown: 'down', ArrowLeft: 'left', ArrowRight: 'right',
W: 'up', S: 'down', A: 'left', D: 'right' };
if (map[e.key]) this.moveBoard(map[e.key]);
});
Desktop players will find your game through portals and review videos — they don’t have a touchscreen. Shipping keyboard support cost us about 20 lines and unlocked the entire PC audience.
Common mistakes
- Threshold too small (5-10px): normal taps register as swipes and the board jumps. Use 20-30px.
- Blocking page scroll: on mobile browsers, a vertical swipe on the canvas can scroll the page. Call
e.preventDefault()on the touchstart of the game container, or settouch-action: noneon the canvas. - Only testing in landscape: most casual H5 traffic is portrait. Test both orientations before submitting to any portal.
Related reading
- The 2026 Guide to HTML5 Game Monetization
- Phaser Scene Management: How We Structure 9 Scenes
- Phaser 3 Game Tutorial: Your First Playable in a Day
Written by ruofan, independent HTML5 game developer. Figures and thresholds come from Merge Fish 2048 (Phaser 3.90 + Vite), a game we’re building. Verify API details against the Phaser docs before relying on them.