input_examples.rst 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. .. _doc_input_examples:
  2. Input examples
  3. ==============
  4. Introduction
  5. ------------
  6. In this tutorial, you'll learn how to use Godot's :ref:`InputEvent <class_InputEvent>`
  7. system to capture player input. There are many different types of input your
  8. game may use - keyboard, gamepad, mouse, etc. - and many different ways to
  9. turn those inputs into actions in your game. This document will show you some
  10. of the most common scenarios, which you can use as starting points for your
  11. own projects.
  12. .. note:: For a detailed overview of how Godot's input event system works,
  13. see :ref:`doc_inputevent`.
  14. Events versus polling
  15. ---------------------
  16. Sometimes you want your game to respond to a certain input event - pressing
  17. the "jump" button, for example. For other situations, you might want something
  18. to happen as long as a key is pressed, such as movement. In the first case,
  19. you can use the ``_input()`` function, which will be called whenever an input
  20. event occurs. In the second case, Godot provides the :ref:`Input <class_Input>`
  21. singleton, which you can use to query the state of an input.
  22. Examples:
  23. .. tabs::
  24. .. code-tab:: gdscript GDScript
  25. func _input(event):
  26. if event.is_action_pressed("jump"):
  27. jump()
  28. func _physics_process(delta):
  29. if Input.is_action_pressed("move_right"):
  30. # Move as long as the key/button is pressed.
  31. position.x += speed * delta
  32. .. code-tab:: csharp
  33. public override void _Input(InputEvent @event)
  34. {
  35. if (@event.IsActionPressed("jump"))
  36. {
  37. Jump();
  38. }
  39. }
  40. public override void _PhysicsProcess(double delta)
  41. {
  42. if (Input.IsActionPressed("move_right"))
  43. {
  44. // Move as long as the key/button is pressed.
  45. position.X += speed * (float)delta;
  46. }
  47. }
  48. This gives you the flexibility to mix-and-match the type of input processing
  49. you do.
  50. For the remainder of this tutorial, we'll focus on capturing individual
  51. events in ``_input()``.
  52. Input events
  53. ------------
  54. Input events are objects that inherit from :ref:`InputEvent <class_InputEvent>`.
  55. Depending on the event type, the object will contain specific properties
  56. related to that event. To see what events actually look like, add a Node and
  57. attach the following script:
  58. .. tabs::
  59. .. code-tab:: gdscript GDScript
  60. extends Node
  61. func _input(event):
  62. print(event.as_text())
  63. .. code-tab:: csharp
  64. using Godot;
  65. public partial class Node : Godot.Node
  66. {
  67. public override void _Input(InputEvent @event)
  68. {
  69. GD.Print(@event.AsText());
  70. }
  71. }
  72. As you press keys, move the mouse, and perform other inputs, you'll see each
  73. event scroll by in the output window. Here's an example of the output:
  74. ::
  75. A
  76. Mouse motion at position ((971, 5)) with velocity ((0, 0))
  77. Right Mouse Button
  78. Mouse motion at position ((870, 243)) with velocity ((0.454937, -0.454937))
  79. Left Mouse Button
  80. Mouse Wheel Up
  81. A
  82. B
  83. Shift
  84. Alt+Shift
  85. Alt
  86. Shift+T
  87. Mouse motion at position ((868, 242)) with velocity ((-2.134768, 2.134768))
  88. As you can see, the results are very different for the different types of
  89. input. Key events are even printed as their key symbols. For example, let's
  90. consider :ref:`InputEventMouseButton <class_InputEventMouseButton>`.
  91. It inherits from the following classes:
  92. - :ref:`InputEvent <class_InputEvent>` - the base class for all input events
  93. - :ref:`InputEventWithModifiers <class_InputEventWithModifiers>` - adds the ability to check if modifiers are pressed, such as :kbd:`Shift` or :kbd:`Alt`.
  94. - :ref:`InputEventMouse <class_InputEventMouse>` - adds mouse event properties, such as ``position``
  95. - :ref:`InputEventMouseButton <class_InputEventMouseButton>` - contains the index of the button that was pressed, whether it was a double-click, etc.
  96. .. tip:: It's a good idea to keep the class reference open while you're working
  97. with events so you can check the event type's available properties and
  98. methods.
  99. You can encounter errors if you try to access a property on an input type that
  100. doesn't contain it - calling ``position`` on ``InputEventKey`` for example. To
  101. avoid this, make sure to test the event type first:
  102. .. tabs::
  103. .. code-tab:: gdscript GDScript
  104. func _input(event):
  105. if event is InputEventMouseButton:
  106. print("mouse button event at ", event.position)
  107. .. code-tab:: csharp
  108. public override void _Input(InputEvent @event)
  109. {
  110. if (@event is InputEventMouseButton mouseEvent)
  111. {
  112. GD.Print("mouse button event at ", mouseEvent.Position);
  113. }
  114. }
  115. InputMap
  116. --------
  117. The :ref:`InputMap <class_InputMap>` is the most flexible way to handle a
  118. variety of inputs. You use this by creating named input *actions*, to which
  119. you can assign any number of input events, such as keypresses or mouse clicks.
  120. To see them, and to add your own, open Project -> Project Settings and select
  121. the InputMap tab:
  122. .. image:: img/inputs_inputmap.webp
  123. .. tip::
  124. A new Godot project includes a number of default actions already defined.
  125. To see them, turn on ``Show Built-in Actions`` in the InputMap dialog.
  126. Capturing actions
  127. ~~~~~~~~~~~~~~~~~
  128. Once you've defined your actions, you can process them in your scripts using
  129. ``is_action_pressed()`` and ``is_action_released()`` by passing the name of
  130. the action you're looking for:
  131. .. tabs::
  132. .. code-tab:: gdscript GDScript
  133. func _input(event):
  134. if event.is_action_pressed("my_action"):
  135. print("my_action occurred!")
  136. .. code-tab:: csharp
  137. public override void _Input(InputEvent @event)
  138. {
  139. if (@event.IsActionPressed("my_action"))
  140. {
  141. GD.Print("my_action occurred!");
  142. }
  143. }
  144. Keyboard events
  145. ---------------
  146. Keyboard events are captured in :ref:`InputEventKey <class_InputEventKey>`.
  147. While it's recommended to use input actions instead, there may be cases where
  148. you want to specifically look at key events. For this example, let's check for
  149. the :kbd:`T`:
  150. .. tabs::
  151. .. code-tab:: gdscript GDScript
  152. func _input(event):
  153. if event is InputEventKey and event.pressed:
  154. if event.keycode == KEY_T:
  155. print("T was pressed")
  156. .. code-tab:: csharp
  157. public override void _Input(InputEvent @event)
  158. {
  159. if (@event is InputEventKey keyEvent && keyEvent.Pressed)
  160. {
  161. if (keyEvent.Keycode == Key.T)
  162. {
  163. GD.Print("T was pressed");
  164. }
  165. }
  166. }
  167. .. tip:: See :ref:`@GlobalScope_Key <enum_@GlobalScope_Key>` for a list of keycode
  168. constants.
  169. .. warning::
  170. Due to *keyboard ghosting*, not all key inputs may be registered at a given time
  171. if you press too many keys at once. Due to their location on the keyboard,
  172. certain keys are more prone to ghosting than others. Some keyboards feature
  173. antighosting at a hardware level, but this feature is generally
  174. not present on low-end keyboards and laptop keyboards.
  175. As a result, it's recommended to use a default keyboard layout that is designed to work well
  176. on a keyboard without antighosting. See
  177. `this Gamedev Stack Exchange question <https://gamedev.stackexchange.com/a/109002>`__
  178. for more information.
  179. Keyboard modifiers
  180. ~~~~~~~~~~~~~~~~~~
  181. Modifier properties are inherited from
  182. :ref:`InputEventWithModifiers <class_InputEventWithModifiers>`. This allows
  183. you to check for modifier combinations using boolean properties. Let's imagine
  184. you want one thing to happen when the :kbd:`T` is pressed, but something
  185. different when it's :kbd:`Shift + T`:
  186. .. tabs::
  187. .. code-tab:: gdscript GDScript
  188. func _input(event):
  189. if event is InputEventKey and event.pressed:
  190. if event.keycode == KEY_T:
  191. if event.shift_pressed:
  192. print("Shift+T was pressed")
  193. else:
  194. print("T was pressed")
  195. .. code-tab:: csharp
  196. public override void _Input(InputEvent @event)
  197. {
  198. if (@event is InputEventKey keyEvent && keyEvent.Pressed)
  199. {
  200. switch (keyEvent.Keycode)
  201. {
  202. case Key.T:
  203. GD.Print(keyEvent.ShiftPressed ? "Shift+T was pressed" : "T was pressed");
  204. break;
  205. }
  206. }
  207. }
  208. .. tip:: See :ref:`@GlobalScope_Key <enum_@GlobalScope_Key>` for a list of keycode
  209. constants.
  210. Mouse events
  211. ------------
  212. Mouse events stem from the :ref:`InputEventMouse <class_InputEventMouse>` class, and
  213. are separated into two types: :ref:`InputEventMouseButton <class_InputEventMouseButton>`
  214. and :ref:`InputEventMouseMotion <class_InputEventMouseMotion>`. Note that this
  215. means that all mouse events will contain a ``position`` property.
  216. Mouse buttons
  217. ~~~~~~~~~~~~~
  218. Capturing mouse buttons is very similar to handling key events. :ref:`@GlobalScope_MouseButton <enum_@GlobalScope_MouseButton>`
  219. contains a list of ``MOUSE_BUTTON_*`` constants for each possible button, which will
  220. be reported in the event's ``button_index`` property. Note that the scrollwheel
  221. also counts as a button - two buttons, to be precise, with both
  222. ``MOUSE_BUTTON_WHEEL_UP`` and ``MOUSE_BUTTON_WHEEL_DOWN`` being separate events.
  223. .. tabs::
  224. .. code-tab:: gdscript GDScript
  225. func _input(event):
  226. if event is InputEventMouseButton:
  227. if event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
  228. print("Left button was clicked at ", event.position)
  229. if event.button_index == MOUSE_BUTTON_WHEEL_UP and event.pressed:
  230. print("Wheel up")
  231. .. code-tab:: csharp
  232. public override void _Input(InputEvent @event)
  233. {
  234. if (@event is InputEventMouseButton mouseEvent && mouseEvent.Pressed)
  235. {
  236. switch (mouseEvent.ButtonIndex)
  237. {
  238. case MouseButton.Left:
  239. GD.Print($"Left button was clicked at {mouseEvent.Position}");
  240. break;
  241. case MouseButton.WheelUp:
  242. GD.Print("Wheel up");
  243. break;
  244. }
  245. }
  246. }
  247. Mouse motion
  248. ~~~~~~~~~~~~
  249. :ref:`InputEventMouseMotion <class_InputEventMouseMotion>` events occur whenever
  250. the mouse moves. You can find the move's distance with the ``relative``
  251. property.
  252. Here's an example using mouse events to drag-and-drop a :ref:`Sprite2D <class_Sprite2D>`
  253. node:
  254. .. tabs::
  255. .. code-tab:: gdscript GDScript
  256. extends Node
  257. var dragging = false
  258. var click_radius = 32 # Size of the sprite.
  259. func _input(event):
  260. if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
  261. if (event.position - $Sprite2D.position).length() < click_radius:
  262. # Start dragging if the click is on the sprite.
  263. if not dragging and event.pressed:
  264. dragging = true
  265. # Stop dragging if the button is released.
  266. if dragging and not event.pressed:
  267. dragging = false
  268. if event is InputEventMouseMotion and dragging:
  269. # While dragging, move the sprite with the mouse.
  270. $Sprite2D.position = event.position
  271. .. code-tab:: csharp
  272. using Godot;
  273. public partial class MyNode2D : Node2D
  274. {
  275. private bool _dragging = false;
  276. private int _clickRadius = 32; // Size of the sprite.
  277. public override void _Input(InputEvent @event)
  278. {
  279. Sprite2D sprite = GetNodeOrNull<Sprite2D>("Sprite2D");
  280. if (sprite == null)
  281. {
  282. return; // No suitable node was found.
  283. }
  284. if (@event is InputEventMouseButton mouseEvent && mouseEvent.ButtonIndex == MouseButton.Left)
  285. {
  286. if ((mouseEvent.Position - sprite.Position).Length() < _clickRadius)
  287. {
  288. // Start dragging if the click is on the sprite.
  289. if (!_dragging && mouseEvent.Pressed)
  290. {
  291. _dragging = true;
  292. }
  293. }
  294. // Stop dragging if the button is released.
  295. if (_dragging && !mouseEvent.Pressed)
  296. {
  297. _dragging = false;
  298. }
  299. }
  300. else
  301. {
  302. if (@event is InputEventMouseMotion motionEvent && _dragging)
  303. {
  304. // While dragging, move the sprite with the mouse.
  305. sprite.Position = motionEvent.Position;
  306. }
  307. }
  308. }
  309. }
  310. Touch events
  311. ------------
  312. If you are using a touchscreen device, you can generate touch events.
  313. :ref:`InputEventScreenTouch <class_InputEventScreenTouch>` is equivalent to
  314. a mouse click event, and :ref:`InputEventScreenDrag <class_InputEventScreenDrag>`
  315. works much the same as mouse motion.
  316. .. tip:: To test your touch events on a non-touchscreen device, open Project
  317. Settings and go to the "Input Devices/Pointing" section. Enable "Emulate
  318. Touch From Mouse" and your project will interpret mouse clicks and
  319. motion as touch events.