Skip to content

feat: add mobile touch controls to Null Pow!#10

Closed
penta2himajin wants to merge 8 commits into
masterfrom
claude/add-mobile-controls-ZGTNu
Closed

feat: add mobile touch controls to Null Pow!#10
penta2himajin wants to merge 8 commits into
masterfrom
claude/add-mobile-controls-ZGTNu

Conversation

@penta2himajin

Copy link
Copy Markdown
Owner

Summary

  • Swipe gestures: Swipe left/right/up/down on the game canvas to change player direction (threshold: 20px minimum)
  • Tap to start: Short taps (< 300ms, < 10px movement) trigger game start/restart, replacing Space key on mobile
  • On-screen D-pad: Semi-transparent directional pad rendered in the bottom-right corner during gameplay on touch devices, with interactive buttons and visual feedback on active direction
  • Adaptive UI text: Overlay messages show "SWIPE TO MOVE — TAP TO START" on touch devices instead of keyboard instructions

Implementation details

All changes are in examples/null-pow/src/main.tsx:

  • createSwipeHandler() — Tracks pointer down/up positions via Game's onPointerDown/onPointerUp props, calculates swipe direction or detects taps
  • DPad component — Phaser GameObjects (rectangles + text arrows) with interactive + onPointerDown for direct touch input
  • isTouchDevice detection via ontouchstart / maxTouchPoints
  • D-pad only visible during play phase on touch devices

Test plan

  • All 443 existing tests pass
  • Test on mobile browser: swipe in all 4 directions changes player movement
  • Test tap to start/restart from ready/dead/win screens
  • Test D-pad buttons respond to touch during gameplay
  • Verify keyboard controls still work unchanged on desktop
  • Verify D-pad is hidden on non-touch devices

https://claude.ai/code/session_01Acnw2xmmT7syDmbKsjnZkH

Add swipe gesture detection for directional input (swipe left/right/up/down
to change direction) and tap-to-start for game start/restart. Also adds an
on-screen D-pad overlay on touch devices during gameplay as a fallback input
method. Overlay text adapts to show touch-specific instructions on mobile.

https://claude.ai/code/session_01Acnw2xmmT7syDmbKsjnZkH
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Mar 24, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
solidion e16fbaf Commit Preview URL

Branch Preview URL
Mar 25 2026, 03:38 AM

penta2himajin and others added 7 commits March 25, 2026 00:24
Phaser's scene-level pointer events may not fire until the scene is fully
initialized, making taps on the initial screen unresponsive. Switch to
native DOM touchstart/touchend events on the game container, which are
available immediately regardless of Phaser's boot state.

https://claude.ai/code/session_01Acnw2xmmT7syDmbKsjnZkH
The initial screen only accepted Space key via KeyboardInput, making it
impossible to start the game on mobile or by clicking. Add a pointerdown
handler on the Game component (matching Breakout/Aquarium/Floppy Heads
pattern) so click or tap starts/restarts the game from any non-play phase.
Update overlay text to mention click as an option on desktop.

https://claude.ai/code/session_01Acnw2xmmT7syDmbKsjnZkH
- Add "click on canvas starts the game" test (desktop)
- Add "tap on canvas starts the game" test (mobile)
- Add "swipe changes player direction" test (mobile, uses TouchEvent dispatch)
- Fix beforeEach: use focus() instead of click()/tap() to avoid
  accidentally starting the game via the new onPointerDown handler

All 17 null-pow E2E tests pass (desktop + mobile).

https://claude.ai/code/session_01Acnw2xmmT7syDmbKsjnZkH
Root cause: KeyboardInput used `scene.input.keyboard!` (non-null assertion).
On mobile devices where Phaser's keyboard plugin may be null, this crashes
and prevents the entire Game children tree from rendering — including the
onPointerDown handler that should allow taps to start the game.

Fix:
- Rename KeyboardInput → GameInput, combining keyboard + pointer input
- Guard `scene.input.keyboard` with null check (safe skip on mobile)
- Register `scene.input.on("pointerdown")` directly inside the component
  (fires reliably on both desktop click and mobile tap)
- Remove separate onPointerDown prop from <Game> (now handled in GameInput)
- Add E2E tests: JS error detection, synthetic TouchEvent tap, debug counters

https://claude.ai/code/session_01Acnw2xmmT7syDmbKsjnZkH
Two fixes:
1. Arrow keys caused page scrolling on desktop — switch from Phaser's
   keyboard plugin to document.addEventListener("keydown") with
   preventDefault(), matching Floppy Heads' approach.
2. Mobile tap still unreliable — bypass Phaser's input system entirely
   and register pointerdown + touchstart listeners directly on the
   canvas DOM element via scene.game.canvas. This eliminates dependency
   on Phaser's internal touch→pointer conversion pipeline.

Also simplifies touch input: swipe handler now registered on canvas
(not #game-container), tap handled by GameInput's canvas listeners.

https://claude.ai/code/session_01Acnw2xmmT7syDmbKsjnZkH
@penta2himajin penta2himajin deleted the claude/add-mobile-controls-ZGTNu branch March 25, 2026 03:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants