![]() |
![]() |
![]() |
![]() |
![]() |
We’re proud to present a completely new comfortable API to handle game controllers (which includes gamepads, joysticks and similar devices). Everything is documented, with links to examples, in the dedicated manual page about game controllers.
Highlights of the new support:
- You receive information about pressing / releasing gamepad buttons by overriding
TCastleUserInterface.Press
andTCastleUserInterface.Release
methods. Usually you define these overridden methods in your view and handling the gamepad buttons is similar to handling key and mouse button presses.The simplest example looks like this:
12345678910111213function TViewMain.Press(const Event: TInputPressRelease): Boolean;beginResult := inherited;if Result then Exit; // allow the ancestor to handle keys// handle key F1 or north button on gamepadif Event.IsKey(keyF1) or Event.IsController(gbNorth) thenbegin// .. do somethingExit(true); // input was handledend;end;Follow the documentation for examples.
-
Buttons are expressed using controller-agnostic enumerated values. In particular, the 4 face buttons (sometimes labeled A B X Y, sometimes square triangle circle cross, and occurring in various order on different pads) are called
gbNorth
,gbEast
,gbSouth
,gbWest
. You can also access buttons’ caption (which is a name to display to user, likeA
orB
) and meaning (which corresponds to the typical meaning of the button, likegmConfirm
,gmCancel
).Note: While the API is ready to support any gamepad in the future, the current mapping on PC (Windows, Linux) just assumes Xbox Controller. Because it seems to be the most common controller. Support to properly detect e.g. PlayStation gamepads connected to PC is coming. This week, we focused on having a simple and future-proof API to make it possible.
-
The axes of controllers are available as simple
TGameController
functions:TGameController.AxisLeft
(left stick, 2D)TGameController.AxisRight
(left stick, 2D)TGameController.AxisLeftTrigger
(left trigger, 1D)TGameController.AxisRightTrigger
(right trigger, 1D)
Observe them using e.g.
Update
method of your view. Again, follow the documentation for many examples 🙂 -
The example examples/game_controllers allows to test all this. Shows detected game controllers, reports pressed / released buttons, visualized axes of the selected controller.
It is a “resurrected” version of the old example
examples/deprecated_to_upgrade/joysticsks
. But practically almost whole code of that example changed 🙂 -
On top of that, we have expanded our
TInputShortcut
to accept game controller button press or axis move (and report “how much” it was moved above the dead zone). -
And on top on the new
TInputShortcut
capabilities, we give youTCastleWalkNavigation.UseGameController
method: a 1-liner to make yourTCastleWalkNavigation
follow the typical 3D FPS games behaviors. So left stick moves, right stick rotates, you can jump / crouch / run using the typical button layout. -
New example walk_3d_game_controllers, that Michalis showed at the Delphi Summit 2025 this week, shows a simple demo of a game where you can walk with gamepad and have simple interactions with horses and other weird NPCs 🙂
-
Also our examples/fps_game/ was adjusted to use controllers. We just added the 2 lines below to adjust the game to use the game controller:
123Controllers.Initialize;MyWalkNavigation.UseGameController; - We started this feature as an upgrade of our old
CastleJoysticks
unit. We were changing and changing old API (which was somewhat over-complicated, exposing internal system/controller-specific numbers, and weirdly inconsistent with how you handle keys/mouse)… until practically nothing remained.So we decided to just break compatibility. Old API was really uncomfortable, and maintaining the backward-compatible “crutches” would risk that we confuse everyone what is the “proper non-deprecated way” of doing things. We also suspect not many people actually used the old API — since you needed to account for internal button and axis numbers that were both system-specific and controller-specific, it was very difficult to make cross-platform applications using the old API.
Of course, report if you have used old
CastleJoysticks
and have trouble upgrading. Tell us which exactly things you miss. -
We also did some important fixes uncovered during code refactors. Disconnecting / reconnecting no longer crashes. It was crashing in at least 2 ways on Windows (free in the middle of iteration, mixed ids on the list vs Windows ids).
-
As you see, our naming changed from “joysticks” to “game controllers”. This follows most of modern naming and APIs.
- We looked at Steam, Godot, Android and web APIs for gamepads and tries to take the best.
- We considered using
- None of above are really perfect.
- “Joystick” and “gamepad” are both too narrow, as APIs support both things, because for software they are generally the same thing, just with different physical shape.
- “Game controller” sounds a bit too wide, as Wikipedia says that even mouse+keyboard is in principle “a kind of a game controller”.
- In the end, we choose “game controller”, because that’s what Steam and Android call them. Though on web they are gamepads.
- We know, it’s the longest name possible. If Steam and Android APIs can handle it, so can we 🙂
- In many places, we shorten “game controller” to just “controller”.
- Note that this is not the end. We list a number of TODOs at the end of the doc page. They include new
TCastleInputAxis
and actual support for more gamepad types. But the current work provides a solid foundation for it: we have API that is comfortable to use (simple press/receive, axes) and future-proof (makes sense on various platforms and with various devices).
Enjoy! And as always, if you like the new development, please donate. Your support keep us going.
Start the discussion at Castle Game Engine Forum