part_three.rst 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. .. _doc_fps_tutorial_part_three:
  2. Part 3
  3. ======
  4. Part Overview
  5. -------------
  6. In this part we will be limiting our weapons by giving them ammo. We will also
  7. be giving the player the ability to reload, and we will be adding sounds when the
  8. weapons fire.
  9. .. image:: img/PartThreeFinished.png
  10. By the end of this part, the player will have limited ammo, the ability to reload,
  11. and sounds will play when the player fires and changes weapons.
  12. .. note:: You are assumed to have finished :ref:`doc_fps_tutorial_part_two` before moving on to this part of the tutorial.
  13. The finished project from :ref:`doc_fps_tutorial_part_two` will be the starting project for part 3
  14. Let's get started!
  15. Changing levels
  16. ---------------
  17. Now that we have a fully working FPS, let's move to a more FPS like level.
  18. Open up ``Space_Level.tscn`` (``assets/Space_Level_Objects/Space_Level.tscn``) and/or ``Ruins_Level.tscn`` (``assets/Ruin_Level_Objects/Ruins_Level.tscn``).
  19. ``Space_Level.tscn`` and ``Ruins_Level.tscn`` are complete custom FPS levels created for the purpose of this tutorial. Press ``F6`` to
  20. play the open scene, or press the ``play current scene button``, and give it them a whirl.
  21. .. warning:: ``Space_Level.tscn`` is more graphically demanding of the GPU than ``Ruins_Level.tscn``. If your computer is struggling to render
  22. ``Space_Level.tscn``, try using ``Ruins_Level.tscn`` instead.
  23. You might have noticed there are several :ref:`RigidBody <class_RigidBody>` nodes placed throughout the level.
  24. We can place ``RigidBody_hit_test.gd`` on them and then they will react to being hit with bullets, so let's do that!
  25. Follow the instructions below for either (or both) of the scenes you want to use
  26. .. tabs::
  27. .. code-tab:: gdscript Space_Level
  28. Expand "Other_Objects" and then expand "Turrets_And_Physics_Objects".
  29. Expand one of the "Barrel_Group" nodes and then select "Barrel_Rigid_Body" and open it using
  30. the "Open in Editor" button.
  31. This will bring you to the "Barrel_Rigid_Body" scene. From there select the root node and
  32. scroll the inspector down to the bottom.
  33. Select the drop down arrow under the "Node" tab, and then select "Load". Navigate to
  34. "RigidBody_hit_test.gd" and select "Open".
  35. Return back to "Space_Level.tscn".
  36. Expand one of the "Box_Group" nodes and then select "Box_Rigid_Body" and open it using the
  37. "Open in Editor" button.
  38. This will bring you to the "Box_Rigid_Body" scene. From there select the root node and
  39. scroll the inspector down to the bottom.
  40. Select the drop down arrow under the "Node" tab, and then select "Load". Navigate to
  41. "RigidBody_hit_test.gd" and select "Open".
  42. Return back to "Space_Level.tscn".
  43. .. code-tab:: gdscript Ruins_Level
  44. Expand "Misc_Objects" and then expand "Physics_Objects".
  45. Select all of the "Stone_Cube" RigidBodies and then in the inspector scroll down to the bottom.
  46. Select the drop down arrow under the "Node" tab, and then select "Load". Navigate to
  47. "RigidBody_hit_test.gd" and select "Open".
  48. Return back to "Ruins_Level.tscn".
  49. Now you can fire at all of the rigid bodies in either level!
  50. Adding ammo
  51. -----------
  52. Now that we've got working guns, let's give them a limited amount of ammo.
  53. First we need to define a few variables in each of our weapon scripts.
  54. Open up ``Weapon_Pistol.gd`` and add the following global variables:
  55. ::
  56. var ammo_in_weapon = 10
  57. var spare_ammo = 20
  58. const AMMO_IN_MAG = 10
  59. * ``ammo_in_weapon``: The amount of ammo currently in the pistol
  60. * ``spare_ammo``: The amount of ammo we have left in reserve for the pistol
  61. * ``AMMO_IN_MAG``: The amount of ammo in a fully reload weapon/magazine
  62. Now all we need to do is add a single line of code to ``fire_weapon``.
  63. Add the following right under ``Clone.BULLET_DAMAGE = DAMAGE``: ``ammo_in_weapon -= 1``
  64. This will remove one from ``ammo_in_weapon`` every time we fire. Notice we're not checking to see
  65. if we have ammo count of ``0`` or greater in ``fire_weapon``. Instead we're going to check that the ammo count in ``Player.gd``.
  66. _______
  67. Now we need to add ammo for both the rifle and the knife.
  68. .. note:: You may be wondering why we are adding ammo for the knife given it does not consume any ammunition.
  69. The reason we want to add ammo to the knife is so we have a consistent interface for all of our weapons.
  70. If we did not add ammo variables for the knife, we would have to add checks for the knife. By adding the ammo
  71. variables to the knife, we don't need to worry about whether or all our weapons have the same variables.
  72. Add the following global variables to ``Weapon_Rifle.gd``:
  73. ::
  74. var ammo_in_weapon = 50
  75. var spare_ammo = 100
  76. const AMMO_IN_MAG = 50
  77. And then add the following to ``fire_weapon``: ``ammo_in_weapon -= 1``. Make sure that ``ammo_in_weapon -= 1`` is outside of the ``if ray.is_colliding()`` check so
  78. we lost ammo regardless of whether we've hit something or not.
  79. Now all that's left is the knife. Add the following to ``Weapon_Knife.gd``:
  80. ::
  81. var ammo_in_weapon = 1
  82. var spare_ammo = 1
  83. const AMMO_IN_MAG = 1
  84. And because our knife does not consume ammo, that is all we need to add.
  85. _______
  86. Now all we need to do is change a one thing in ``Player.gd``.
  87. All we need to change how we're firing our weapons in ``process_input``. Change the code for firing weapons to the following:
  88. ::
  89. # ----------------------------------
  90. # Firing the weapons
  91. if Input.is_action_pressed("fire"):
  92. if changing_weapon == false:
  93. var current_weapon = weapons[current_weapon_name]
  94. if current_weapon != null:
  95. if current_weapon.ammo_in_weapon > 0:
  96. if animation_manager.current_state == current_weapon.IDLE_ANIM_NAME:
  97. animation_manager.set_animation(current_weapon.FIRE_ANIM_NAME)
  98. # ----------------------------------
  99. Now our weapons have a limited amount of ammo, and will stop firing when we run out.
  100. _______
  101. Ideally we'd like to be able to see how much ammo we have left. Let's make a new function called ``process_ui``.
  102. First, add ``process_UI(delta)`` to ``_physics_process``.
  103. Now add the following to ``Player.gd``:
  104. ::
  105. func process_UI(delta):
  106. if current_weapon_name == "UNARMED" or current_weapon_name == "KNIFE":
  107. UI_status_label.text = "HEALTH: " + str(health)
  108. else:
  109. var current_weapon = weapons[current_weapon_name]
  110. UI_status_label.text = "HEALTH: " + str(health) + \
  111. "\nAMMO:" + str(current_weapon.ammo_in_weapon) + "/" + str(current_weapon.spare_ammo)
  112. Let's go over what's happening:
  113. First we check to see if the current weapon is either ``UNARMED`` or ``KNIFE``. If it is, we
  114. change the ``UI_status_label``'s text to only show our health, since ``UNARMED`` and ``KNIFE`` do not consume ammo.
  115. If we are using a weapon that does consume ammo, we first get the weapon node.
  116. Then change ``UI_status_label``'s text to show our health, how much ammo we have in the weapon,
  117. along with how much spare ammo we have for that weapon.
  118. Now we can see how much ammo we have through the HUD.
  119. Adding reloading to the weapons
  120. -------------------------------
  121. Now that we can run our weapons out of ammo, we need a way to fill them back up. Let's add reloading next!
  122. For reloading we need to add a few more variables and a function to every weapon.
  123. Open up ``Weapon_Pistol.gd`` and add the following global variables:
  124. ::
  125. const CAN_RELOAD = true
  126. const CAN_REFILL = true
  127. const RELOADING_ANIM_NAME = "Pistol_reload"
  128. * ``CAN_RELOAD``: A boolean to track whether this weapon has the ability to reload
  129. * ``CAN_REFIL``: A boolean to track whether we can refill this weapon's spare ammo. We will not be using ``CAN_REFIL`` in this part, but we will in the next part!
  130. * ``RELOADING_ANIM_NAME``: The name of the reloading animation for this weapon.
  131. Now we need to add a function for handling reloading. Add the following function to ``Weapon_Pistol.gd``:
  132. ::
  133. func reload_weapon():
  134. var can_reload = false
  135. if player_node.animation_manager.current_state == IDLE_ANIM_NAME:
  136. can_reload = true
  137. if spare_ammo <= 0 or ammo_in_weapon == AMMO_IN_MAG:
  138. can_reload = false
  139. if can_reload == true:
  140. var ammo_needed = AMMO_IN_MAG - ammo_in_weapon
  141. if spare_ammo >= ammo_needed:
  142. spare_ammo -= ammo_needed
  143. ammo_in_weapon = AMMO_IN_MAG
  144. else:
  145. ammo_in_weapon += spare_ammo
  146. spare_ammo = 0
  147. player_node.animation_manager.set_animation(RELOADING_ANIM_NAME)
  148. return true
  149. return false
  150. Let's go over what's happening:
  151. First we define a variable to see whether or not we can reload.
  152. We first check to see if we are in this weapon's idle animation state because we only want to be able to reload when we are not
  153. firing. equipping, or unequipping.
  154. Next we check to see if we have spare ammo, and if the ammo already in our weapon is equal to a fully reloaded weapon.
  155. This way we can assure we're not going to reload when we have no ammo or when the weapon is already full of ammo.
  156. If we still can reload, then we calculate the amount of ammo needed to reload the weapon.
  157. If we have enough ammo to fill the weapon, we remove the ammo needed from ``spare_ammo`` and then set ``ammo_in_weapon`` to a full weapon/magazine.
  158. If we do not have enough ammo, we add all of the ammo left in ``spare_ammo``, then set ``spare_ammo`` to ``0``.
  159. Next we play the reloading animation for this weapon, and then return ``true``.
  160. If we could not reload, we return ``false``.
  161. _______
  162. Now we need to add reloading to the rifle. Open up ``Weapon_Rifle.gd`` and add the following global variables:
  163. ::
  164. const CAN_RELOAD = true
  165. const CAN_REFILL = true
  166. const RELOADING_ANIM_NAME = "Rifle_reload"
  167. These variables are exactly the same as the pistol, just with ``RELOADING_ANIM_NAME`` changed to the rifle's reloading animation.
  168. Now we need to add ``reload_weapon`` to ``Weapon_Rifle.gd``:
  169. ::
  170. func reload_weapon():
  171. var can_reload = false
  172. if player_node.animation_manager.current_state == IDLE_ANIM_NAME:
  173. can_reload = true
  174. if spare_ammo <= 0 or ammo_in_weapon == AMMO_IN_MAG:
  175. can_reload = false
  176. if can_reload == true:
  177. var ammo_needed = AMMO_IN_MAG - ammo_in_weapon
  178. if spare_ammo >= ammo_needed:
  179. spare_ammo -= ammo_needed
  180. ammo_in_weapon = AMMO_IN_MAG
  181. else:
  182. ammo_in_weapon += spare_ammo
  183. spare_ammo = 0
  184. player_node.animation_manager.set_animation(RELOADING_ANIM_NAME)
  185. return true
  186. return false
  187. This code is exactly the same as the pistol.
  188. _______
  189. The last bit we need to do for the weapons is add 'reloading' to the knife. Add the following global variables to ``Weapon_Knife.gd``:
  190. ::
  191. const CAN_RELOAD = false
  192. const CAN_REFILL = false
  193. const RELOADING_ANIM_NAME = ""
  194. Since we both cannot reload or refill a knife, we set both constants to ``false``. We also define ``RELOADING_ANIM_NAME`` as an empty string, since the knife
  195. has no reloading animation.
  196. Now we need to add ``reloading_weapon``:
  197. ::
  198. func reload_weapon():
  199. return false
  200. Since we cannot reload a knife, we always return ``false``.
  201. Adding reloading to the player
  202. ------------------------------
  203. Now we need to add a few things to ``Player.gd``. First we need to define a new global variable:
  204. ::
  205. var reloading_weapon = false
  206. * ``reloading_weapon``: A variable to track whether or not we are currently trying to reload.
  207. Next we need to add another function call to ``_physics_process``.
  208. Add ``process_reloading(delta)`` to ``_physics_process``. Now ``_physics_process`` should look something like this:
  209. ::
  210. func _physics_process(delta):
  211. process_input(delta)
  212. process_movement(delta)
  213. process_changing_weapons(delta)
  214. process_reloading(delta)
  215. process_UI(delta)
  216. Now we need to add ``process_reloading``. Add the following function to ``Player.gd``:
  217. ::
  218. func process_reloading(delta):
  219. if reloading_weapon == true:
  220. var current_weapon = weapons[current_weapon_name]
  221. if current_weapon != null:
  222. current_weapon.reload_weapon()
  223. reloading_weapon = false
  224. Let's go over what's happening here.
  225. First we check to make sure we are trying to reload.
  226. If we are, we then get the current weapon. If the current weapon does not equal ``null``, we call its ``reload_weapon`` function.
  227. .. note:: If the current weapon is equal to ``null``, then the current weapon is ``UNARMED``.
  228. Finally, we set ``reloading_weapon`` to ``false``, because regardless of whether we've successfully reloaded, we've tried reloading
  229. and no longer need to keep trying.
  230. _______
  231. Before we can reload, we need to change a few things in ``process_input``.
  232. The first thing we need to change is in the code for changing weapons. We need to add a additional check (``if reloading_weapon == false:``) to see if we are reloading:
  233. ::
  234. if changing_weapon == false:
  235. # New line of code here!
  236. if reloading_weapon == false:
  237. if WEAPON_NUMBER_TO_NAME[weapon_change_number] != current_weapon_name:
  238. changing_weapon_name = WEAPON_NUMBER_TO_NAME[weapon_change_number]
  239. changing_weapon = true
  240. This makes it where we cannot change weapons if we are reloading.
  241. Now we need to add the code to trigger a reload when the player pushes the ``reload`` action. Add the following code to ``process_input``:
  242. ::
  243. # ----------------------------------
  244. # Reloading
  245. if reloading_weapon == false:
  246. if changing_weapon == false:
  247. if Input.is_action_just_pressed("reload"):
  248. var current_weapon = weapons[current_weapon_name]
  249. if current_weapon != null:
  250. if current_weapon.CAN_RELOAD == true:
  251. var current_anim_state = animation_manager.current_state
  252. var is_reloading = false
  253. for weapon in weapons:
  254. var weapon_node = weapons[weapon]
  255. if weapon_node != null:
  256. if current_anim_state == weapon_node.RELOADING_ANIM_NAME:
  257. is_reloading = true
  258. if is_reloading == false:
  259. reloading_weapon = true
  260. # ----------------------------------
  261. Let's go over what's happening here.
  262. First we make sure we're not reloading already, nor are we trying to change weapons.
  263. Then we check to see if the ``reload`` action has been pressed.
  264. If we have pressed ``reload``, we then get the current weapon and check to make sure it is not ``null``. Then we check to see if the
  265. weapon can reload or not using its ``CAN_RELOAD`` constant.
  266. If the weapon can reload, we then get the current animation state, and make a variable for tracking whether we are already reloading or not.
  267. We then go through every weapon to make sure we're not already playing that weapon's reloading animation.
  268. If we are not reloading with any weapon, we set ``reloading_weapon`` to ``true``.
  269. _______
  270. One thing I like to add is where the weapon will reload itself if you try to fire it when it's out of ammo.
  271. We also need to add a additional if check (``is_reloading_weapon == false:``) so we cannot fire the current weapon while
  272. reloading.
  273. Let's change our firing code in ``process_input`` so it reloads when trying to fire an empty weapon:
  274. ::
  275. # ----------------------------------
  276. # Firing the weapons
  277. if Input.is_action_pressed("fire"):
  278. if reloading_weapon == false:
  279. if changing_weapon == false:
  280. var current_weapon = weapons[current_weapon_name]
  281. if current_weapon != null:
  282. if current_weapon.ammo_in_weapon > 0:
  283. if animation_manager.current_state == current_weapon.IDLE_ANIM_NAME:
  284. animation_manager.set_animation(current_weapon.FIRE_ANIM_NAME)
  285. else:
  286. reloading_weapon = true
  287. # ----------------------------------
  288. Now we check to make sure we're not reloading before we fire out weapon, and when we have ``0`` or less ammo in our weapon
  289. we set ``reloading_weapon`` to ``true`` if we try to fire.
  290. This will make it where we will try to reload when we try to fire a empty weapon.
  291. _______
  292. With that we can reload our weapons! Give it a try! Now you can fire all of the spare ammo for each weapon.
  293. Adding sounds
  294. -------------
  295. Finally, let's add some sounds that play when we are reloading, changing guns, and when we
  296. are firing them.
  297. .. tip:: There are no game sounds provided in this tutorial (for legal reasons).
  298. https://gamesounds.xyz/ is a collection of **"royalty free or public domain music and sounds suitable for games"**.
  299. I used Gamemaster's Gun Sound Pack, which can be found in the Sonniss.com GDC 2017 Game Audio Bundle.
  300. Open up ``SimpleAudioPlayer.tscn``. It is simply a :ref:`Spatial <class_Spatial>` with a :ref:`AudioStreamPlayer <class_AudioStreamPlayer>` as it's child.
  301. .. note:: The reason this is called a 'simple' audio player is because we are not taking performance into account
  302. and because the code is designed to provide sound in the simplest way possible.
  303. If you want to use 3D audio, so it sounds like it's coming from a location in 3D space, right click
  304. the :ref:`AudioStreamPlayer <class_AudioStreamPlayer>` and select "Change type".
  305. This will open the node browser. Navigate to :ref:`AudioStreamPlayer3D <class_AudioStreamPlayer3D>` and select "change".
  306. In the source for this tutorial, we will be using :ref:`AudioStreamPlayer <class_AudioStreamPlayer>`, but you can optionally
  307. use :ref:`AudioStreamPlayer3D <class_AudioStreamPlayer3D>` if you desire, and the code provided below will work regardless of which
  308. one you chose.
  309. Create a new script and call it ``SimpleAudioPlayer.gd``. Attach it to the :ref:`Spatial <class_Spatial>` in ``SimpleAudioPlayer.tscn``
  310. and insert the following code:
  311. ::
  312. extends Spatial
  313. # All of the audio files.
  314. # You will need to provide your own sound files.
  315. var audio_pistol_shot = preload("res://path_to_your_audio_here")
  316. var audio_gun_cock = preload("res://path_to_your_audio_here")
  317. var audio_rifle_shot = preload("res://path_to_your_audio_here")
  318. var audio_node = null
  319. func _ready():
  320. audio_node = $Audio_Stream_Player
  321. audio_node.connect("finished", self, "destroy_self")
  322. audio_node.stop()
  323. func play_sound(sound_name, position=null):
  324. if audio_pistol_shot == null or audio_rifle_shot == null or audio_gun_cock == null:
  325. print ("Audio not set!")
  326. queue_free()
  327. return
  328. if sound_name == "Pistol_shot":
  329. audio_node.stream = audio_pistol_shot
  330. elif sound_name == "Rifle_shot":
  331. audio_node.stream = audio_rifle_shot
  332. elif sound_name == "Gun_cock":
  333. audio_node.stream = audio_gun_cock
  334. else:
  335. print ("UNKNOWN STREAM")
  336. queue_free()
  337. return
  338. # If you are using a AudioPlayer3D, then uncomment these lines to set the position.
  339. # if position != null:
  340. # audio_node.global_transform.origin = position
  341. audio_node.play()
  342. func destroy_self():
  343. audio_node.stop()
  344. queue_free()
  345. .. tip:: By setting ``position`` to ``null`` by default in ``play_sound``, we are making it an optional argument,
  346. meaning ``position`` doesn't necessarily have to be passed in to call the ``play_sound``.
  347. Let's go over what's happening here:
  348. _________
  349. In ``_ready`` we get the :ref:`AudioStreamPlayer <class_AudioStreamPlayer>` and connect its ``finished`` signal to ourselves.
  350. It doesn't matter if it's a :ref:`AudioStreamPlayer <class_AudioStreamPlayer>` or :ref:`AudioStreamPlayer3D <class_AudioStreamPlayer3D>` node,
  351. as they both have the finished signal. To make sure it is not playing any sounds, we call ``stop`` on the :ref:`AudioStreamPlayer <class_AudioStreamPlayer>`.
  352. .. warning:: Make sure your sound files are **not** set to loop! If it is set to loop
  353. the sounds will continue to play infinitely and the script will not work!
  354. The ``play_sound`` function is what we will be calling from ``Player.gd``. We check if the sound
  355. is one of the three possible sounds, and if it is we set the audio stream for our :ref:`AudioStreamPlayer <class_AudioStreamPlayer>`
  356. to the correct sound.
  357. If it is an unknown sound, we print an error message to the console and free ourselves.
  358. If you are using a :ref:`AudioStreamPlayer3D <class_AudioStreamPlayer3D>`, remove the ``#`` to set the position of
  359. the audio player node so it plays at the correct position.
  360. Finally, we tell the :ref:`AudioStreamPlayer <class_AudioStreamPlayer>` to play.
  361. When the :ref:`AudioStreamPlayer <class_AudioStreamPlayer>` is finished playing the sound, it will call ``destroy_self`` because
  362. we connected the ``finished`` signal in ``_ready``. We stop the :ref:`AudioStreamPlayer <class_AudioStreamPlayer>` and free ourself
  363. to save on resources.
  364. .. note:: This system is extremely simple and has some major flaws:
  365. One flaw is we have to pass in a string value to play a sound. While it is relatively simple
  366. to remember the names of the three sounds, it can be increasingly complex when you have more sounds.
  367. Ideally we'd place these sounds in some sort of container with exposed variables so we do not have
  368. to remember the name(s) of each sound effect we want to play.
  369. Another flaw is we cannot play looping sounds effects, nor background music easily with this system.
  370. Because we cannot play looping sounds, certain effects like footstep sounds are harder to accomplish
  371. because we then have to keep track of whether or not there is a sound effect and whether or not we
  372. need to continue playing it.
  373. One of the biggest flaws with this system is we can only play sounds from ``Player.gd``.
  374. Ideally we'd like to be able to play sounds from any script at any time.
  375. _________
  376. With that done, let's open up ``Player.gd`` again.
  377. First we need to load the ``SimpleAudioPlayer.tscn``. Place the following code in your global variables:
  378. ::
  379. var simple_audio_player = preload("res://Simple_Audio_Player.tscn")
  380. Now we need to instance the simple audio player when we need it, and then call its
  381. ``play_sound`` function and pass the name of the sound we want to play. To make the process simpler,
  382. let's create a ``create_sound`` function:
  383. ::
  384. func create_sound(sound_name, position=null):
  385. var audio_clone = simple_audio_player.instance()
  386. var scene_root = get_tree().root.get_children()[0]
  387. scene_root.add_child(audio_clone)
  388. audio_clone.play_sound(sound_name, position)
  389. Lets walk through what this function does:
  390. _________
  391. The first line instances the ``Simple_Audio_Player.tscn`` scene and assigns it to a variable,
  392. named ``audio_clone``.
  393. The second line gets the scene root, using one large assumption. We first get this node's :ref:`SceneTree <class_SceneTree>`,
  394. and then access the root node, which in this case is the :ref:`Viewport <class_Viewport>` this entire game is running under.
  395. Then we get the first child of the :ref:`Viewport <class_Viewport>`, which in our case happens to be the root node in
  396. ``Test_Area.tscn`` or any of the other provided levels. We are making a huge assumption that the first child of the root
  397. is the root node that our player is under, which could not always be the case.
  398. If this doesn't make sense to you, don't worry too much about it. The second line of code only doesn't work
  399. reliably if you have multiple scenes loaded as children to the root node at a time, which will rarely happen for most projects.
  400. This is only potentially a issue depending on how you handle scene loading.
  401. The third line adds our newly created ``SimpleAudioPlayer`` scene to be a child of the scene root. This
  402. works exactly the same as when we are spawning bullets.
  403. Finally, we call the ``play_sound`` function and pass in the arguments we're given. This will call
  404. ``SimpleAudioPlayer.gd``'s ``play_sound`` function with the passed in arguments.
  405. _________
  406. Now all that is left is playing the sounds when we want to. Let's add sound to the pistol first!
  407. Open up ``Weapon_Pistol.gd``.
  408. Now, we want to make a noise when we fire the pistol, so add the following to the end of the ``fire_weapon`` function:
  409. ::
  410. player_node.create_sound("pistol_shot", self.global_transform.origin)
  411. Now when we fire our pistol, we'll play the ``pistol_shot`` sound.
  412. To make a sound when we reload, we need to add the following right under ``player_node.animation_manager.set_animation(RELOADING_ANIM_NAME)`` in the
  413. ``reload_weapon`` function:
  414. ::
  415. player_node.create_sound("gun_cock", player_node.camera.global_transform.origin)
  416. Now when we reload we'll play the ``gun_cock`` sound.
  417. _________
  418. Now let's add sounds to the rifle.
  419. Open up ``Weapon_Rifle.gd``.
  420. To play sounds when the rifle is fired, add the following to the end of the ``fire_weapon`` function:
  421. ::
  422. player_node.create_sound("rifle_shot", ray.global_transform.origin)
  423. Now when we fire our rifle, we'll play the ``rifle_shot`` sound.
  424. To make a sound when we reload, we need to add the following right under ``player_node.animation_manager.set_animation(RELOADING_ANIM_NAME)`` in the
  425. ``reload_weapon`` function:
  426. ::
  427. player_node.create_sound("gun_cock", player_node.camera.global_transform.origin)
  428. Now when we reload we'll play the ``gun_cock`` sound.
  429. Final notes
  430. -----------
  431. .. image:: img/PartThreeFinished.png
  432. Now you have weapons with limited ammo that play sounds when you fire them!
  433. At this point we have all of the basics of a FPS working.
  434. There's still a few things that would be nice to add, and we're going to add them in the next three parts!
  435. For example, right now we have no way to add ammo to our spares, so we'll eventually run out. Also, we don't
  436. have anything to shoot at outside of the :ref:`RigidBody <class_RigidBody>` nodes.
  437. In In :ref:`doc_fps_tutorial_part_four` we'll add some targets to shoot at, along with some health and ammo pick ups!
  438. We're also going to add joypad support, so we can play with wired Xbox 360 controllers!
  439. .. warning:: If you ever get lost, be sure to read over the code again!
  440. You can download the finished project for this part here: :download:`Godot_FPS_Part_3.zip <files/Godot_FPS_Part_3.zip>`