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.

ParameterOur valueWhy
Swipe threshold26 pxSmall enough for fast swipes, big enough to ignore finger jitter
Move detectionpointerup - pointerdownSimpler than live velocity tracking; reliable for a 4-direction grid
Input channelsswipe + mouse drag + keysCovers 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


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.