scripting_first_script.rst 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. ..
  2. Intention:
  3. - Giving a *short* and sweet hands-on intro to GDScript. The page should
  4. focus on working in the code editor.
  5. - We assume the reader has programming foundations. If you don't, consider
  6. taking the course we recommend in the :ref:`introduction to Godot page <doc_introduction_learning_programming>`.
  7. Techniques:
  8. - Creating a sprite.
  9. - Creating a script.
  10. - _init() and _process().
  11. - Moving an object on screen.
  12. .. _doc_scripting_first_script:
  13. Creating your first script
  14. ==========================
  15. In this lesson, you will code your first script to make the Godot icon turn in
  16. circles. As we mentioned :ref:`in the introduction
  17. <doc_introduction_learning_programming>`, we assume you have programming
  18. foundations.
  19. This tutorial is written for GDScript, and the equivalent C# code is included in
  20. another tab of each codeblock for convenience.
  21. .. image:: img/scripting_first_script_rotating_godot.gif
  22. .. seealso:: To learn more about GDScript, its keywords, and its syntax, head to
  23. the :ref:`doc_gdscript` section. To learn more about C#,
  24. head to the :ref:`doc_c_sharp` section.
  25. Project setup
  26. -------------
  27. Please :ref:`create a new project <doc_creating_and_importing_projects>` to
  28. start with a clean slate. Your project should contain one picture: the Godot
  29. icon, which we often use for prototyping in the community.
  30. .. image:: img/scripting_first_script_icon.svg
  31. We need to create a Sprite2D node to display it in the game. In the Scene dock,
  32. click the **Other Node** button.
  33. .. image:: img/scripting_first_script_click_other_node.webp
  34. Type "Sprite2D" in the search bar to filter nodes and double-click on Sprite2D
  35. to create the node.
  36. .. image:: img/scripting_first_script_add_sprite_node.webp
  37. Your Scene tab should now only have a Sprite2D node.
  38. .. image:: img/scripting_first_script_scene_tree.webp
  39. A Sprite2D node needs a texture to display. In the Inspector on the right, you
  40. can see that the **Texture** property says ``<empty>``. To display the Godot icon,
  41. click and drag the file ``icon.svg`` from the FileSystem dock onto the Texture
  42. slot.
  43. .. image:: img/scripting_first_script_setting_texture.webp
  44. .. note::
  45. You can create Sprite2D nodes automatically by dragging and dropping images
  46. on the viewport.
  47. Then, click and drag the icon in the viewport to center it in the game view.
  48. .. image:: img/scripting_first_script_centering_sprite.webp
  49. Creating a new script
  50. ---------------------
  51. To create and attach a new script to our node, right-click on Sprite2D in the
  52. Scene dock and select **Attach Script**.
  53. .. image:: img/scripting_first_script_attach_script.webp
  54. The **Attach Node Script** window appears. It allows you to select the script's
  55. language and file path, among other options.
  56. Change the **Template** field from ``Node: Default`` to ``Object: Empty`` to
  57. start with a clean file. Leave the other options set to their default values and
  58. click the **Create** button to create the script.
  59. .. image:: img/scripting_first_script_attach_node_script.webp
  60. .. note::
  61. C# script names need to match their class name. In this case, you should name the
  62. file ``MySprite2D.cs``.
  63. The Script workspace should appear with your new ``sprite_2d.gd`` file open and
  64. the following line of code:
  65. .. tabs::
  66. .. code-tab:: gdscript GDScript
  67. extends Sprite2D
  68. .. code-tab:: csharp C#
  69. using Godot;
  70. using System;
  71. public partial class MySprite2D : Sprite2D
  72. {
  73. }
  74. Every GDScript file is implicitly a class. The ``extends`` keyword defines the
  75. class this script inherits or extends. In this case, it's ``Sprite2D``, meaning
  76. our script will get access to all the properties and functions of the Sprite2D
  77. node, including classes it extends, like ``Node2D``, ``CanvasItem``, and
  78. ``Node``.
  79. .. note:: In GDScript, if you omit the line with the ``extends`` keyword, your
  80. class will implicitly extend :ref:`RefCounted <class_RefCounted>`, which
  81. Godot uses to manage your application's memory.
  82. Inherited properties include the ones you can see in the Inspector dock, like
  83. our node's ``texture``.
  84. .. note::
  85. By default, the Inspector displays a node's properties in "Title Case", with
  86. capitalized words separated by a space. In GDScript code, these properties
  87. are in "snake_case", which is lowercase with words separated by an underscore.
  88. You can hover over any property's name in the Inspector to see a description and
  89. its identifier in code.
  90. Hello, world!
  91. -------------
  92. Our script currently doesn't do anything. Let's make it print the text "Hello,
  93. world!" to the Output bottom panel to get started.
  94. Add the following code to your script:
  95. .. tabs::
  96. .. code-tab:: gdscript GDScript
  97. func _init():
  98. print("Hello, world!")
  99. .. code-tab:: csharp C#
  100. public MySprite2D()
  101. {
  102. GD.Print("Hello, world!");
  103. }
  104. Let's break it down. The ``func`` keyword defines a new function named
  105. ``_init``. This is a special name for our class's constructor. The engine calls
  106. ``_init()`` on every object or node upon creating it in memory, if you define
  107. this function.
  108. .. note:: GDScript is an indent-based language. The tab at the start of the line
  109. that says ``print()`` is necessary for the code to work. If you omit
  110. it or don't indent a line correctly, the editor will highlight it in
  111. red and display the following error message: "Indented block expected".
  112. Save the scene as ``sprite_2d.tscn`` if you haven't already, then press :kbd:`F6` (:kbd:`Cmd + R` on macOS)
  113. to run it. Look at the **Output** bottom panel that expands.
  114. It should display "Hello, world!".
  115. .. image:: img/scripting_first_script_print_hello_world.webp
  116. Delete the ``_init()`` function, so you're only left with the line ``extends
  117. Sprite2D``.
  118. Turning around
  119. --------------
  120. It's time to make our node move and rotate. To do so, we're going to add two
  121. member variables to our script: the movement speed in pixels per second and the
  122. angular speed in radians per second. Add the following after the ``extends Sprite2D`` line.
  123. .. tabs::
  124. .. code-tab:: gdscript GDScript
  125. var speed = 400
  126. var angular_speed = PI
  127. .. code-tab:: csharp C#
  128. private int _speed = 400;
  129. private float _angularSpeed = Mathf.Pi;
  130. Member variables sit near the top of the script, after any "extends" lines,
  131. but before functions. Every node
  132. instance with this script attached to it will have its own copy of the ``speed``
  133. and ``angular_speed`` properties.
  134. .. note:: Angles in Godot work in radians by default,
  135. but you have built-in functions and properties available if you prefer
  136. to calculate angles in degrees instead.
  137. To move our icon, we need to update its position and rotation every frame in the
  138. game loop. We can use the ``_process()`` virtual function of the ``Node`` class.
  139. If you define it in any class that extends the Node class, like Sprite2D, Godot
  140. will call the function every frame and pass it an argument named ``delta``, the
  141. time elapsed since the last frame.
  142. .. note::
  143. Games work by rendering many images per second, each called a frame, and
  144. they do so in a loop. We measure the rate at which a game produces images in
  145. Frames Per Second (FPS). Most games aim for 60 FPS, although you might find
  146. figures like 30 FPS on slower mobile devices or 90 to 240 for virtual
  147. reality games.
  148. The engine and game developers do their best to update the game world and
  149. render images at a constant time interval, but there are always small
  150. variations in frame render times. That's why the engine provides us with
  151. this delta time value, making our motion independent of our framerate.
  152. At the bottom of the script, define the function:
  153. .. tabs::
  154. .. code-tab:: gdscript GDScript
  155. func _process(delta):
  156. rotation += angular_speed * delta
  157. .. code-tab:: csharp C#
  158. public override void _Process(double delta)
  159. {
  160. Rotation += _angularSpeed * (float)delta;
  161. }
  162. The ``func`` keyword defines a new function. After it, we have to write the
  163. function's name and arguments it takes in parentheses. A colon ends the
  164. definition, and the indented blocks that follow are the function's content or
  165. instructions.
  166. .. note:: Notice how ``_process()``, like ``_init()``, starts with a leading
  167. underscore. By convention, Godot's virtual functions, that is to say,
  168. built-in functions you can override to communicate with the engine,
  169. start with an underscore.
  170. The line inside the function, ``rotation += angular_speed * delta``, increments
  171. our sprite's rotation every frame. Here, ``rotation`` is a property inherited
  172. from the class ``Node2D``, which ``Sprite2D`` extends. It controls the rotation
  173. of our node and works with radians.
  174. .. tip:: In the code editor, you can :kbd:`Ctrl + Click` (:kbd:`Cmd + Click` on
  175. macOS) on any built-in property or function like ``position``,
  176. ``rotation``, or ``_process`` to open the corresponding documentation
  177. in a new tab.
  178. Run the scene to see the Godot icon turn in-place.
  179. .. image:: img/scripting_first_script_godot_turning_in_place.gif
  180. .. note:: In C#, notice how the ``delta`` argument taken by ``_Process()`` is a
  181. ``double``. We therefore need to convert it to ``float`` when we apply
  182. it to the rotation.
  183. Moving forward
  184. ~~~~~~~~~~~~~~
  185. Let's now make the node move. Add the following two lines inside of the ``_process()``
  186. function, ensuring the new lines are indented the same way as the ``rotation += angular_speed * delta`` line before
  187. them.
  188. .. tabs::
  189. .. code-tab:: gdscript GDScript
  190. var velocity = Vector2.UP.rotated(rotation) * speed
  191. position += velocity * delta
  192. .. code-tab:: csharp C#
  193. var velocity = Vector2.Up.Rotated(Rotation) * _speed;
  194. Position += velocity * (float)delta;
  195. As we already saw, the ``var`` keyword defines a new variable. If you put it at
  196. the top of the script, it defines a property of the class. Inside a function, it
  197. defines a local variable: it only exists within the function's scope.
  198. We define a local variable named ``velocity``, a 2D vector representing both a
  199. direction and a speed. To make the node move forward, we start from the Vector2
  200. class's constant ``Vector2.UP``, a vector pointing up, and rotate it by calling the
  201. Vector2 method ``rotated()``. This expression, ``Vector2.UP.rotated(rotation)``,
  202. is a vector pointing forward relative to our icon. Multiplied by our ``speed``
  203. property, it gives us a velocity we can use to move the node forward.
  204. We add ``velocity * delta`` to the node's ``position`` to move it. The position
  205. itself is of type :ref:`Vector2 <class_Vector2>`, a built-in type in Godot
  206. representing a 2D vector.
  207. Run the scene to see the Godot head run in circles.
  208. .. image:: img/scripting_first_script_rotating_godot.gif
  209. .. note:: Moving a node like that does not take into account colliding with
  210. walls or the floor. In :ref:`doc_your_first_2d_game`, you will learn
  211. another approach to moving objects while detecting collisions.
  212. Our node currently moves by itself. In the next part,
  213. :ref:`doc_scripting_player_input`, we'll use player input to control it.
  214. Complete script
  215. ---------------
  216. Here is the complete ``sprite_2d.gd`` file for reference.
  217. .. tabs::
  218. .. code-tab:: gdscript GDScript
  219. extends Sprite2D
  220. var speed = 400
  221. var angular_speed = PI
  222. func _process(delta):
  223. rotation += angular_speed * delta
  224. var velocity = Vector2.UP.rotated(rotation) * speed
  225. position += velocity * delta
  226. .. code-tab:: csharp C#
  227. using Godot;
  228. using System;
  229. public partial class MySprite2D : Sprite2D
  230. {
  231. private int _speed = 400;
  232. private float _angularSpeed = Mathf.Pi;
  233. public override void _Process(double delta)
  234. {
  235. Rotation += _angularSpeed * (float)delta;
  236. var velocity = Vector2.Up.Rotated(Rotation) * _speed;
  237. Position += velocity * (float)delta;
  238. }
  239. }