The original Joy commands work in both language modes on Windows, macOS, iOS, Android and web. No initialization command is needed. Connect a controller, run the controller playground, and move, aim and shoot with the sticks, triggers and south face button.
The legacy Joy input commands retain Blitz3D's raw button and axis model. They suit existing programs and devices such as flight sticks and steering wheels, where a standard gamepad layout may not apply. Raw button and axis order depends on the device and driver.
The Gamepad commands give supported controllers a consistent layout: left and right sticks, separate triggers, face buttons and a D-pad, with configurable dead zones. Keeping these commands separate lets new games use portable controls without redefining the legacy Joy commands and breaking existing bindings.
Both command sets read the same connected devices and use the same port numbers. General features such as discovery, connection status, battery reporting and vibration keep the Joy prefix because they apply to both raw joysticks and mapped gamepads, where supported.
Ports start at 0. There are 16 slots. JoyCount() reports the connected count, while JoyPorts() reports the number of slots. Enumerate 0 to JoyPorts()-1 and test JoyConnected(port). Disconnected slots become empty without moving other players. New connections use the lowest empty slot; saved port numbers do not identify a particular physical controller across reconnects or program runs.
For port=0 To JoyPorts()-1
If JoyConnected(port) Then Print Str(port)+": "+JoyName$(port)
Next
Use JoyGamepad(port) to check for a standard mapping. GamepadAxis applies radial stick dead zones and separate trigger dead zones. The default values are 0.15 and 0.05; use GamepadDeadZone after connection to change them. Values outside the dead zone are rescaled to retain full travel. Axes 1..4 use -1..1, with positive Y pointing down; triggers use 0..1 and can be pressed simultaneously.
| Axis | Control |
|---|---|
| 1, 2 | Left stick X, Y |
| 3, 4 | Right stick X, Y |
| 5, 6 | Left, right trigger |
GamepadDown tests held buttons; GamepadHit consumes press counts. GetGamepad reads a FIFO of press events. Button positions are consistent across supported controllers, regardless of their printed letters.
| Button | Position |
|---|---|
| 1, 2, 3, 4 | South, east, west, north face button |
| 5, 6 | Left, right shoulder |
| 7, 8 | Back/select, start/menu |
| 9, 10 | Left, right stick click |
| 11, 12, 13, 14 | D-pad up, down, left, right |
| 15 | Guide/home (may be reserved by the OS) |
| 16 | Miscellaneous/capture |
| 17, 18, 19, 20 | Right paddle 1, left paddle 1, right paddle 2, left paddle 2 |
| 21 | Touchpad click |
Missing controls return zero. GamepadConstants.bb provides named constants for these numbers. FlushJoy clears both raw and standard hit counts and press queues, but keeps held buttons down. Each FIFO holds 31 presses; drain it regularly. The runtime samples controllers when it processes events (Flip, Delay and input reads); long calculations without event processing can miss presses.
JoyType returns 0 for absent, 1 for digital-only and 2 for analog devices. JoyDown, JoyHit, GetJoy, WaitJoy/JoyWait and FlushJoy retain their button/queue roles. Buttons are one based, up to 128. WaitJoy returns 0 if the controller is absent or disconnects while waiting.
JoyX/Y/Z read raw axes 1/2/3; JoyU/V read 7/8; JoyPitch/Yaw/Roll read 4/5/6 multiplied by 180. JoyAxis gives access to all raw axes (up to 16) without dead zones. Raw order is driver dependent, so old device-specific bindings may need adjustment. Use the standard API for portable gamepad controls.
JoyHat reads the first POV; JoyHatAngle reads up to four. Angles are clockwise from up in 45-degree steps. Centered, absent, invalid and unfocused hats return -1. This corrects the old absent-device return of 0, which was indistinguishable from pressing up. Recognized gamepads with no raw POV expose the d-pad as hat 1.
Check JoyRumbleSupported, then call JoyRumble(low,high,milliseconds,port). Low is the strong, low-frequency motor; high is the weak, high-frequency motor. Intensities are 0..1 and duration is capped at 60 seconds. A zero duration or two zero intensities stops the effect. A new effect replaces the previous one. Vibration stops on focus loss and runtime shutdown. JoyBattery returns a percentage when available, or -1.