Skip to content

Controls

Bubbleshum edited this page Jun 27, 2026 · 3 revisions

Controls

WPR maps modern input devices onto the Windows Phone touch / tilt model the games were written against. Mouse acts as touch on desktop; the keyboard drives a software accelerometer; real fingers and the mouse can coexist in the multi-touch slot table.


Supported inputs

Input Status Notes
Touchscreen Supported Windows touch devices + Android (when the UI renders)
Mouse (as touch) Supported Left click = touch, button-held drag = swipe
Multi-touch Supported Real fingers + mouse share slots additively
Keyboard Supported Drives the accelerometer simulator; per-game key bindings on top
Xbox / generic gamepads Not supported No mapping layer yet

Mouse as touch (desktop)

The mouse synthesises a single finger into the touch slot table:

Action Result
Left click (press) TouchLocationState.Pressed
Left button held + drag TouchLocationState.Moved
Left release TouchLocationState.Released
Hover (no button held) No touch event

The hover-suppression matters: previously, SDL mouse-motion events were forwarded to the touch panel unconditionally, including no-button hover, which set activeFingerId = 1 and routed the next real click into pinch-init instead of tap detection. Tap-gated screens (Tentacles' LemmyTravelScreen, "tap to continue" prompts) failed silently. Fixed 22/05/2026 — SDL2_FNAPlatform skips synthesised Moved events when evt.motion.state == 0.


Multi-touch (additive with mouse-as-touch)

Real fingers fill slots 0..MAX_TOUCHES-2 from SDL_GetTouchFinger. When TouchPanel.MouseAsTouch is on (the default for XNA games on WPR), the mouse takes the last slot with synthetic finger ID int.MaxValue so it can never collide with a real finger's ID.

Before this fix (22/05/2026), the touch poll branched either-or — turning MouseAsTouch on capped all input at a single touch even on multi-touch hardware. Sonic 4's "hold D-pad + tap jump" gameplay needed this.


Keyboard accelerometer

WPR's Controls sidebar binds four keys to simulated phone tilt. Readings flow through the existing Microsoft.Devices.Sensors.Accelerometer, so games see them without any per-game shim work.

Default bindings

Key Tilt direction (screen-relative)
W Tilt up the screen
A Tilt left
S Tilt down
D Tilt right

You can rebind all four on the Controls page in the WPR sidebar. The page also has:

  • Sensitivity slider — scales the magnitude of the synthesized reading.
  • Master toggle — disables the keyboard accelerometer entirely (use real touch / no tilt).
  • In-game tilt overlay — small HUD that visualises the live reading, drawn over the running game (Avalonia overlay for Silverlight, FNA DrawableGameComponent for XNA).
  • Live-preview dial — same overlay, but on the Controls page so you can test bindings before launching.

Orientation-aware

The screen-relative key intent is rotated into the device-portrait frame the WP7 sensor contract expects. So in a landscape game (W = "tilt up the screen"), the synthesized reading is the correct device-X tilt the game interprets as steer-left.

Desktop orientation is inferred from the back-buffer aspect because FNA's Window.CurrentOrientation only updates from SDL display-rotation events that never fire on the desktop.

Polling APIs

In addition to ReadingChanged, the shim exposes:

  • Accelerometer.CurrentValue — snapshot the latest reading.
  • Accelerometer.IsDataValid — set once a reading has been seen.
  • Accelerometer.TimeBetweenUpdates — read/write the polling interval.

Games that poll instead of subscribing see live readings too.

Games that use it today

Hydro Thunder GO's steering goes through the accelerometer — set up your WASD bindings on the Controls page and tilt to steer. Anything else that queries Microsoft.Devices.Sensors.Accelerometer will work the same way.


Per-game key bindings

A handful of games hard-bind specific keys (e.g. for menu navigation). Where the game's own input handler reads Keys.Whatever, WPR forwards SDL key events into FNA's Keyboard.GetState() unchanged — keys you press hit the game directly.


Touch on Android

When the Android target renders properly (see Android Setup), touch flows through the same SDL_GetTouchFinger path that desktop uses. No accelerometer simulator on Android — the device's own accelerometer feeds the shim directly.


Common input issues

Tap doesn't register on desktop

If a "tap to continue" prompt ignores your mouse clicks, you may be on a build older than 22/05/2026 — the hover-suppression fix landed then. Pull, rebuild, retry.

Multi-touch only registers one finger

Same date — the mouse-as-touch additive fix landed 22/05/2026. Older builds capped input at a single touch when MouseAsTouch was on.

Tilt is inverted / wrong axis

Check the orientation: a landscape game expects portrait-frame tilt. The overlay on the Controls page lets you see what the game is seeing. If the sign is wrong, swap W/S or A/D in the bindings.

Keyboard accelerometer not responding

  • Master toggle on the Controls page enabled?
  • Game actually using Microsoft.Devices.Sensors.Accelerometer? (Some games use their own polling routine.)
  • Sensitivity high enough? Push it up — the default is conservative.

Related pages

Clone this wiki locally