{"id":5626,"date":"2025-06-08T14:37:17","date_gmt":"2025-06-08T14:37:17","guid":{"rendered":"https:\/\/castle-engine.io\/wp\/?p=5626"},"modified":"2025-06-21T04:59:54","modified_gmt":"2025-06-21T04:59:54","slug":"game-controllers-gamepads-joysticks-new-comfortable-api-and-example-of-walking-and-talking-using-gamepad-from-delphi-summit-2025","status":"publish","type":"post","link":"https:\/\/castle-engine.io\/wp\/2025\/06\/08\/game-controllers-gamepads-joysticks-new-comfortable-api-and-example-of-walking-and-talking-using-gamepad-from-delphi-summit-2025\/","title":{"rendered":"Game controllers (gamepads, joysticks) &#8211; new comfortable API, and example of walking and talking using gamepad from Delphi Summit 2025"},"content":{"rendered":"<table class=\"thumbnails thumbnails-align-right\"><tr><td>\n          <a href=\"https:\/\/castle-engine.io\/wp\/wp-content\/uploads\/2025\/06\/xbox_controller_cge_demo.png\"\n             class=\"screenshot\"\n             title=\"Xbox Controller used to control our Castle Game Engine demo\"><img loading=\"lazy\" decoding=\"async\"\n            style=\"float: right\"\n            src=\"https:\/\/castle-engine.io\/wp\/wp-content\/uploads\/2025\/06\/xbox_controller_cge_demo-200x150.png\"\n             width=\"200\" height=\"150\" \n            alt=\"Xbox Controller used to control our Castle Game Engine demo\"\n          ><\/a><\/td><\/tr><tr><td>\n          <a href=\"https:\/\/castle-engine.io\/wp\/wp-content\/uploads\/2025\/06\/walk_3d_game_controllers.png\"\n             class=\"screenshot\"\n             title=\"Xbox Controller used to control our Castle Game Engine demo\"><img loading=\"lazy\" decoding=\"async\"\n            style=\"float: right\"\n            src=\"https:\/\/castle-engine.io\/wp\/wp-content\/uploads\/2025\/06\/walk_3d_game_controllers-200x117.png\"\n             width=\"200\" height=\"117\" \n            alt=\"Xbox Controller used to control our Castle Game Engine demo\"\n          ><\/a><\/td><\/tr><tr><td>\n          <a href=\"https:\/\/castle-engine.io\/wp\/wp-content\/uploads\/2025\/06\/game_controllers.png\"\n             class=\"screenshot\"\n             title=\"Game Controller example\"><img loading=\"lazy\" decoding=\"async\"\n            style=\"float: right\"\n            src=\"https:\/\/castle-engine.io\/wp\/wp-content\/uploads\/2025\/06\/game_controllers-200x119.png\"\n             width=\"200\" height=\"119\" \n            alt=\"Game Controller example\"\n          ><\/a><\/td><\/tr><tr><td>\n          <a href=\"https:\/\/castle-engine.io\/wp\/wp-content\/uploads\/2025\/06\/doom_controller.png\"\n             class=\"screenshot\"\n             title=\"Doom gamepad layout\"><img loading=\"lazy\" decoding=\"async\"\n            style=\"float: right\"\n            src=\"https:\/\/castle-engine.io\/wp\/wp-content\/uploads\/2025\/06\/doom_controller-200x114.png\"\n             width=\"200\" height=\"114\" \n            alt=\"Doom gamepad layout\"\n          ><\/a><\/td><\/tr><tr><td>\n          <a href=\"https:\/\/castle-engine.io\/wp\/wp-content\/uploads\/2025\/06\/fortnite_controller.png\"\n             class=\"screenshot\"\n             title=\"Fortnite gamepad layout\"><img loading=\"lazy\" decoding=\"async\"\n            style=\"float: right\"\n            src=\"https:\/\/castle-engine.io\/wp\/wp-content\/uploads\/2025\/06\/fortnite_controller-200x104.png\"\n             width=\"200\" height=\"104\" \n            alt=\"Fortnite gamepad layout\"\n          ><\/a><\/td><\/tr><\/table>\n<p>We&#8217;re proud to present a completely new comfortable API to handle <em>game controllers<\/em> (which includes <em>gamepads<\/em>, <em>joysticks<\/em> and similar devices). Everything is documented, with links to examples, in the <a href=\"https:\/\/castle-engine.io\/controllers\">dedicated manual page about game controllers<\/a>.<\/p>\n<p>Highlights of the new support:<\/p>\n<ol>\n<li>You receive information about pressing \/ releasing gamepad buttons by overriding <code><a href=\"https:\/\/castle-engine.io\/apidoc\/html\/CastleUIControls.TCastleUserInterface.html#Press-TInputPressRelease-\">TCastleUserInterface.Press<\/a><\/code> and <code><a href=\"https:\/\/castle-engine.io\/apidoc\/html\/CastleUIControls.TCastleUserInterface.html#Release-TInputPressRelease-\">TCastleUserInterface.Release<\/a><\/code> methods. Usually you define these overridden methods in your <a href=\"https:\/\/castle-engine.io\/view_events\">view<\/a> and handling the gamepad buttons is similar to handling key and mouse button presses.\n<p>The simplest example looks like this:<\/p>\n<pre><code class=\"language-delphi\">function TViewMain.Press(const Event: TInputPressRelease): Boolean;\nbegin\n  Result := inherited;\n  if Result then Exit; \/\/ allow the ancestor to handle keys\n\n  \/\/ handle key F1 or north button on gamepad  \n  if Event.IsKey(keyF1) or Event.IsController(gbNorth) then\n  begin\n    \/\/ .. do something\n    Exit(true); \/\/ input was handled\n  end;\nend;\n<\/code><\/pre>\n<p>Follow the <a href=\"https:\/\/castle-engine.io\/controllers\">documentation<\/a> for examples.<\/p>\n<\/li>\n<li>\n<p>Buttons are expressed using controller-agnostic enumerated values. In particular, the 4 <em>face buttons<\/em> (sometimes labeled <em>A B X Y<\/em>, sometimes <em>square triangle circle cross<\/em>, and occurring in various order on different pads) are called <code><a href=\"https:\/\/castle-engine.io\/apidoc\/html\/CastleKeysMouse.html#gbNorth\">gbNorth<\/a><\/code>, <code><a href=\"https:\/\/castle-engine.io\/apidoc\/html\/CastleKeysMouse.html#gbEast\">gbEast<\/a><\/code>, <code><a href=\"https:\/\/castle-engine.io\/apidoc\/html\/CastleKeysMouse.html#gbSouth\">gbSouth<\/a><\/code>, <code><a href=\"https:\/\/castle-engine.io\/apidoc\/html\/CastleKeysMouse.html#gbWest\">gbWest<\/a><\/code>. You can also access buttons&#8217; <em>caption<\/em> (which is a name to display to user, like <code>A<\/code> or <code>B<\/code>) and <em>meaning<\/em> (which corresponds to the typical meaning of the button, like <code><a href=\"https:\/\/castle-engine.io\/apidoc\/html\/CastleKeysMouse.html#gmConfirm\">gmConfirm<\/a><\/code>, <code><a href=\"https:\/\/castle-engine.io\/apidoc\/html\/CastleKeysMouse.html#gmCancel\">gmCancel<\/a><\/code>).<\/p>\n<p>Note: While the API is ready to support any gamepad in the future, the current mapping on PC (Windows, Linux) just assumes <em>Xbox Controller<\/em>. 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.<\/p>\n<\/li>\n<li>\n<p>The axes of controllers are available as simple <code><a href=\"https:\/\/castle-engine.io\/apidoc\/html\/CastleGameControllers.TGameController.html\">TGameController<\/a><\/code> functions:<\/p>\n<ul>\n<li><code><a href=\"https:\/\/castle-engine.io\/apidoc\/html\/CastleGameControllers.TGameController.html#AxisLeft\">TGameController.AxisLeft<\/a><\/code> (left stick, 2D)<\/li>\n<li><code><a href=\"https:\/\/castle-engine.io\/apidoc\/html\/CastleGameControllers.TGameController.html#AxisRight\">TGameController.AxisRight<\/a><\/code> (left stick, 2D)<\/li>\n<li><code><a href=\"https:\/\/castle-engine.io\/apidoc\/html\/CastleGameControllers.TGameController.html#AxisLeftTrigger\">TGameController.AxisLeftTrigger<\/a><\/code> (left trigger, 1D)<\/li>\n<li><code><a href=\"https:\/\/castle-engine.io\/apidoc\/html\/CastleGameControllers.TGameController.html#AxisRightTrigger\">TGameController.AxisRightTrigger<\/a><\/code> (right trigger, 1D)<\/li>\n<\/ul>\n<p>Observe them using e.g. <code>Update<\/code> method of your view. Again, follow the <a href=\"https:\/\/castle-engine.io\/controllers\">documentation<\/a> for many examples \ud83d\ude42<\/p>\n<\/li>\n<li>\n<p>The example <a href=\"https:\/\/github.com\/castle-engine\/castle-engine\/tree\/master\/examples\/game_controllers\">examples\/game_controllers<\/a> allows to test all this. Shows detected game controllers, reports pressed \/ released buttons, visualized axes of the selected controller.<\/p>\n<p>It is a &#8220;resurrected&#8221; version of the old example <code>examples\/deprecated_to_upgrade\/joysticsks<\/code>. But practically almost whole code of that example changed \ud83d\ude42<\/p>\n<\/li>\n<li>\n<p>On top of that, we have expanded our <code><a href=\"https:\/\/castle-engine.io\/apidoc\/html\/CastleInputs.TInputShortcut.html\">TInputShortcut<\/a><\/code> to accept game controller button press or axis move (and report &#8220;how much&#8221; it was moved above the <em>dead zone<\/em>).<\/p>\n<\/li>\n<li>\n<p>And on top on the new <code><a href=\"https:\/\/castle-engine.io\/apidoc\/html\/CastleInputs.TInputShortcut.html\">TInputShortcut<\/a><\/code> capabilities, we give you <code><a href=\"https:\/\/castle-engine.io\/apidoc\/html\/CastleCameras.TCastleWalkNavigation.html#UseGameController-Integer-\">TCastleWalkNavigation.UseGameController<\/a><\/code> method: a 1-liner to make your <code><a href=\"https:\/\/castle-engine.io\/apidoc\/html\/CastleCameras.TCastleWalkNavigation.html\">TCastleWalkNavigation<\/a><\/code> follow the typical 3D FPS games behaviors. So left stick moves, right stick rotates, you can jump \/ crouch \/ run using the typical button layout.<\/p>\n<\/li>\n<li>\n<p>New example <a href=\"https:\/\/github.com\/castle-engine\/conference-delphi-summit-2025\">walk_3d_game_controllers<\/a>, that Michalis showed at the <a href=\"https:\/\/delphisummit.com\/\">Delphi Summit 2025 this week<\/a>, shows a simple demo of a game where you can walk with gamepad and have simple interactions with horses and other weird NPCs \ud83d\ude42<\/p>\n<\/li>\n<li>\n<p>Also our <a href=\"https:\/\/github.com\/castle-engine\/castle-engine\/tree\/master\/examples\/fps_game\">examples\/fps_game\/<\/a> was adjusted to use controllers. We just added the 2 lines below to adjust the game to use the game controller:<\/p>\n<pre><code class=\"language-delphi\">Controllers.Initialize;\nMyWalkNavigation.UseGameController;\n<\/code><\/pre>\n<\/li>\n<li>We started this feature as an upgrade of our old <code>CastleJoysticks<\/code> 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)&#8230; until practically nothing remained.\n<p>So we decided to just break compatibility. Old API was really uncomfortable, and maintaining the backward-compatible &#8220;crutches&#8221; would risk that we confuse everyone what is the &#8220;proper non-deprecated way&#8221; of doing things. We also suspect not many people actually used the old API &#8212; 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.<\/p>\n<p>Of course, report if you have used old <code>CastleJoysticks<\/code> and have trouble upgrading. Tell us which exactly things you miss.<\/p>\n<\/li>\n<li>\n<p>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).<\/p>\n<\/li>\n<li>\n<p>As you see, our naming changed from <em>&#8220;joysticks&#8221;<\/em> to <em>&#8220;game controllers&#8221;<\/em>. This follows most of modern naming and APIs.<\/p>\n<ul>\n<li>We looked at Steam, Godot, Android and web APIs for gamepads and tries to take the best.<\/li>\n<li>We considered using\n<ul>\n<li><a href=\"https:\/\/en.wikipedia.org\/wiki\/Joystick\">&#8220;Joystick&#8221;<\/a><\/li>\n<li><a href=\"https:\/\/en.wikipedia.org\/wiki\/Gamepad\">&#8220;Gamepad&#8221;<\/a><\/li>\n<li><a href=\"https:\/\/en.wikipedia.org\/wiki\/Game_controller\">&#8220;Game controller&#8221;<\/a><\/li>\n<\/ul>\n<\/li>\n<li>None of above are really perfect.\n<ul>\n<li><em>&#8220;Joystick&#8221;<\/em> and <em>&#8220;gamepad&#8221;<\/em> are both too narrow, as APIs support both things, because for software they are generally the same thing, just with different physical shape.<\/li>\n<li><em>&#8220;Game controller&#8221;<\/em> sounds a bit too wide, as Wikipedia says that even mouse+keyboard is in principle <em>&#8220;a kind of a game controller&#8221;<\/em>.<\/li>\n<li>In the end, we choose &#8220;game controller&#8221;, because that&#8217;s what <a href=\"https:\/\/partner.steamgames.com\/doc\/features\/steam_controller\">Steam<\/a> and <a href=\"https:\/\/developer.android.com\/games\/sdk\/game-controller\">Android<\/a> call them. Though on <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Gamepad_API\/Using_the_Gamepad_API\">web they are gamepads<\/a>.<\/li>\n<li>We know, it&#8217;s the longest name possible. If Steam and Android APIs can handle it, so can we \ud83d\ude42 <\/li>\n<li>In many places, we shorten <em>&#8220;game controller&#8221;<\/em> to just <em>&#8220;controller&#8221;<\/em>.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>Note that this is not the end. We list a number of TODOs <a href=\"https:\/\/castle-engine.io\/controllers\">at the end of the doc page<\/a>. They include new <code>TCastleInputAxis<\/code> 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).<\/p>\n<\/li>\n<\/ol>\n<p>Enjoy! And as always, if you like the new development, please <a href=\"https:\/\/castle-engine.io\/donate\">donate<\/a>. Your support keep us going.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We&#8217;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 and methods. Usually you &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/castle-engine.io\/wp\/2025\/06\/08\/game-controllers-gamepads-joysticks-new-comfortable-api-and-example-of-walking-and-talking-using-gamepad-from-delphi-summit-2025\/\" class=\"more-link\">Continue reading  \u27a4<span class=\"screen-reader-text\"> &#8220;Game controllers (gamepads, joysticks) &#8211; new comfortable API, and example of walking and talking using gamepad from Delphi Summit 2025&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":5644,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"publish_to_discourse":"0","publish_post_category":"9","wpdc_auto_publish_overridden":"1","wpdc_topic_tags":"","wpdc_pin_topic":"","wpdc_pin_until":"","discourse_post_id":"6869","discourse_permalink":"https:\/\/forum.castle-engine.io\/t\/game-controllers-gamepads-joysticks-new-comfortable-api-and-example-of-walking-and-talking-using-gamepad-from-delphi-summit-2025\/1936","wpdc_publishing_response":"","wpdc_publishing_error":"","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[1],"tags":[],"class_list":["post-5626","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/castle-engine.io\/wp\/wp-content\/uploads\/2025\/06\/xbox_controller_cge_demo.png","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p9IgYW-1sK","jetpack_likes_enabled":false,"_links":{"self":[{"href":"https:\/\/castle-engine.io\/wp\/wp-json\/wp\/v2\/posts\/5626","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/castle-engine.io\/wp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/castle-engine.io\/wp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/castle-engine.io\/wp\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/castle-engine.io\/wp\/wp-json\/wp\/v2\/comments?post=5626"}],"version-history":[{"count":17,"href":"https:\/\/castle-engine.io\/wp\/wp-json\/wp\/v2\/posts\/5626\/revisions"}],"predecessor-version":[{"id":5648,"href":"https:\/\/castle-engine.io\/wp\/wp-json\/wp\/v2\/posts\/5626\/revisions\/5648"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/castle-engine.io\/wp\/wp-json\/wp\/v2\/media\/5644"}],"wp:attachment":[{"href":"https:\/\/castle-engine.io\/wp\/wp-json\/wp\/v2\/media?parent=5626"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/castle-engine.io\/wp\/wp-json\/wp\/v2\/categories?post=5626"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/castle-engine.io\/wp\/wp-json\/wp\/v2\/tags?post=5626"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}