Partie 3

Aperçu cette partie

Dans cette partie, nous allons limité les armes du joueur en lui ajoutant un nombre de munitions. Nous allons également donner a notre joueur l’aptitude de recharger, et nous allons ajouter les bruitages des tirs quand l’arme est utilisée.

../../../_images/PartThreeFinished.png

Note

Vous êtes supposez avoir fini Partie 2 avant de commencer cette partie du tutoriel. Le projet final de Partie 2 sera le projet de départ pour la troisième partie

Commençons tout de suite !

Changement des niveaux

Maintenant que nous avons un FPS qui fonctionne totalement, passons à un niveau ressemblant plus a un FPS (FPS-like).

Ouvrez Space_Level.tscn (assets/Space_Level_Objects/Space_Level.tscn) et/ou Ruins_Level.tscn (assets/Ruin_Level_Objects/Ruins_Level.tscn).

Space_Level.tscn et Ruins_Level.tscn sont des niveaux FPS complètement customisés créés pour les besoins de ce tutoriel. Appuyez sur F6 pour jouer la scène d’entrée, ou appuyez sur le bouton play current scene button, et essayez chaque méthode.

Avertissement

Space_Level.tscn``est plus demandant graphiquement sur le GPU que ``Ruins_Level.tscn. Si votre PC n’arrive pas à donner un rendu stable, essayez ``Ruins_Level.tscn``à la place.

Vous avez peut-être remarqué qu’il y a plusieurs nœuds RigidBody placés à travers tout le niveau. Nous pouvons placer des RigidBody_hit_test.gd au sein du niveau afin qu’ils puissent réagissent au fait d’être touché par des balles, c’est parti !

Suivez l’instruction en dessous pour une (ou les deux) des scènes que vous voulez utiliser

Expand "Other_Objects" and then expand "Physics_Objects".

Expand one of the "Barrel_Group" nodes and then select "Barrel_Rigid_Body" and open it using
the "Open in Editor" button.
This will bring you to the "Barrel_Rigid_Body" scene. From there, select the root node and
scroll the inspector down to the bottom.
Select the drop down arrow under the "Node" tab, and then select "Load". Navigate to
"RigidBody_hit_test.gd" and select "Open".

Return back to "Space_Level.tscn".

Expand one of the "Box_Group" nodes and then select "Crate_Rigid_Body" and open it using the
"Open in Editor" button.
This will bring you to the "Crate_Rigid_Body" scene. From there, select the root node and
scroll the inspector down to the bottom.
Select the drop down arrow under the "Node" tab, and then select "Load". Navigate to
"RigidBody_hit_test.gd" and select "Open".

Return to "Space_Level.tscn".
Expand "Misc_Objects" and then expand "Physics_Objects".

Select all the "Stone_Cube" RigidBodies and then in the inspector scroll down to the bottom.
Select the drop down arrow under the "Node" tab, and then select "Load". Navigate to
"RigidBody_hit_test.gd" and select "Open".

Return to "Ruins_Level.tscn".

Maintenant vous pouvez tirer sur tout les « rigid bodies » dans n’importe quel niveau et ils réagiront aux balles les touchant !

Ajout des munitions

Maintenant que notre joueur possède des armes à feu, donnons leurs un nombre de munitions limité.

Tout d’abord, nous devons définir quelques variables dans chacun de nos scripts d’armes à feu.

Ouvrez Weapon_Pistol.gd et ajoutez les variables de classe suivantes :

var ammo_in_weapon = 10
var spare_ammo = 20
const AMMO_IN_MAG = 10
  • ammo_in_weapon: Le nombre de munitions actuellement dans le pistolet
  • spare_ammo: Le nombre de munitions que nous avons en réserve (disponible pour le rechargement de l’arme) pour le pistolet
  • AMMO_IN_MAG: Le nombre de munitions dans une arme ou un chargeur, quand il/elle est entièrement chargé de munitions

Tout ce qu’il reste à faire est d’ajouter une ligne de code à fire_weapon.

Ajoutez ce qui suit juste en dessous : Clone.BULLET_DAMAGE = DAMAGE: ammo_in_weapon -= 1

Cela va décrémenter de un la variable ammo_in_weapon à chaque fois que le joueur tire. Notez que nous ne vérifions pas si le joueur a assez de munitions ou non dans fire_weapon. Nous allons plutôt vérifier si le joueur a assez de munitions dans Player.gd.


Maintenant nous allons devoir ajouter des munitions pour le fusil et le couteau.

Note

Vous vous demandez peut-être pourquoi nous ajoutons des munitions pour le couteau étant donné qu’il ne consomme pas de munitions. Nous voulons en ajouter pour avoir une interface consistante pour toutes nos armes.

Si nous n’ajoutons pas de munitions au couteau, nous allons devoir ajouter des vérifications pour le couteau. En ajoutant une variable munitions pour le couteau, nous n’aurons pas à nous préoccuper de si oui ou non toute nos armes ont les mêmes variables.

Ajoutez la variable de classe suivante à « Weapon_Rifle.gd » :

var ammo_in_weapon = 50
var spare_ammo = 100
const AMMO_IN_MAG = 50

Puis ajoutez la ligne suivante à fire_weapon : ammo_in_weapon -= 1. Assurez-vous que ammo_in_weapon -= 1 soit hors de la vérification``if ray.is_colliding()`` pour que le joueur perdent des munitions qu’importe si il touche quelque chose ou non.

Maintenant il ne nous reste que le couteau. Ajoutez l’élément suivant à Weapon_Knife.gd :

var ammo_in_weapon = 1
var spare_ammo = 1
const AMMO_IN_MAG = 1

Comme le couteau ne consomme pas de munitions c’est tout ce que nous avons besoin d’ajouter.


Maintenant nous avons besoin de changer une chose dans Player.gd, c’est-à-dire,

comment nous faisons feu avec les armes dans process_input . Changez le code pour faire feu avec des armes par le suivant :

# ----------------------------------
# Firing the weapons
if Input.is_action_pressed("fire"):
    if changing_weapon == false:
        var current_weapon = weapons[current_weapon_name]
        if current_weapon != null:
            if current_weapon.ammo_in_weapon > 0:
                if animation_manager.current_state == current_weapon.IDLE_ANIM_NAME:
                    animation_manager.set_animation(current_weapon.FIRE_ANIM_NAME)
# ----------------------------------

Maintenant, les armes ont une quantité limitée de munitions et celles-ci arrêterons de faire feu lorsque le joueur n’en aura plus.


Idéalement, nous aimerions que le joueur puisse savoir combien de munitions il lui reste. Faisons une nouvelle fonction appelé process_UI.

Premièrement, ajoutez process_UI(delta) à _physics_process.

Maintenant ajoutez ce qui suit à Player.gd :

func process_UI(delta):
    if current_weapon_name == "UNARMED" or current_weapon_name == "KNIFE":
        UI_status_label.text = "HEALTH: " + str(health)
    else:
        var current_weapon = weapons[current_weapon_name]
        UI_status_label.text = "HEALTH: " + str(health) + \
                "\nAMMO: " + str(current_weapon.ammo_in_weapon) + "/" + str(current_weapon.spare_ammo)

Regardons ce qui ce passe :

Premièrement, nous vérifions si l’arme actuelle est soit UNARMED ou KNIFE. Si c’est le cas, nous changeons le texte de``UI_status_label`` pour afficher uniquement la vie du joueur étant donné que UNARMED et KNIFE ne consomment pas de munitions.

Si le joueur utilise une arme qui consomme des munitions, nous allons d’abord récupérer le nœud de l’arme.

Puis nous changeons le texte UI_status_label pour afficher la vie du joueur, tout en affichant combien de munitions il reste au joueur dans son arme et combien de munitions il possède dans son inventaire pour cette arme.

Maintenant nous pouvons voir combien de munitions le joueur possède au travers du HUD.

Ajout du rechargement des armes

Maintenant que le joueur peut arriver à court de munitions, nous devons lui donner un moyen de recharger. Ajoutons le rechargement maintenant !

Pour recharger, nous avons besoin d’ajouter quelque variables en plus et une fonction pour chaque arme.

Ouvrez Weapon_Pistol.gd et ajoutez les variables de classe suivantes :

const CAN_RELOAD = true
const CAN_REFILL = true

const RELOADING_ANIM_NAME = "Pistol_reload"
  • « CAN_RELOAD » : Un booléen pour savoir si oui ou non l’arme à la capacité de recharger
  • « CAN_REFILL » : Un booléen pour savoir si oui ou non nous pouvons recharger l’arme avec des munitions de l’inventaire. Nous n’utiliserons pas « CAN_REFILL » dans cette partie, mais nous le ferons dans la prochaine partie !
  • « RELOADING_ANIM_NAME » : Le nom de l’animation de chargement pour cette arme.

Maintenant nous devons ajouter une fonction pour gérer le rechargement de l’arme. Ajoutez la fonction suivante à « Weapon_Pistol.gd » :

func reload_weapon():
    var can_reload = false

    if player_node.animation_manager.current_state == IDLE_ANIM_NAME:
        can_reload = true

    if spare_ammo <= 0 or ammo_in_weapon == AMMO_IN_MAG:
        can_reload = false

    if can_reload == true:
        var ammo_needed = AMMO_IN_MAG - ammo_in_weapon

        if spare_ammo >= ammo_needed:
            spare_ammo -= ammo_needed
            ammo_in_weapon = AMMO_IN_MAG
        else:
            ammo_in_weapon += spare_ammo
            spare_ammo = 0

        player_node.animation_manager.set_animation(RELOADING_ANIM_NAME)

        return true

    return false

Regardons ce qui ce passe :

Premièrement nous définissons une variable pour voir si on peut recharger notre arme ou non.

Puis nous vérifions si l’arme du joueur est dans « idle » animation car on ne veut pouvoir recharger que si le joueur ne tire pas, ne l’équipe pas et ne la déséquipe pas.

Ensuite nous vérifions si le joueur a assez de munitions dans l’inventaire, et si les munitions présente dans l’arme sont équales à l’arme rechargée au maximum. De cette façon nous nous assurons que le joueur ne peut pas recharger si il n’a plus de munitions ou si il est déjà au maximum.

Si nous pouvons encore recharger, alors nous calculons la quantité de munitions nécessaire pour recharger l’arme.

Si le joueur a assez de munitions pour remplir l’arme, nous enlevons les munitions nécessaires de spare_ammo et ensuite nous réglons ammo_in_weapon sur un chargeur d’arme complet.

Si le joueur n’a pas assez de munitions, nous ajoutons toutes les munitions restantes dans spare_ammo, puis réglons spare_ammo sur 0.

Ensuite nous jouons l’animation de rechargement de cette arme, puis true est retourné.

Si le joueur ne peux pas recharger, nous retournons false.


Maintenant nous avons besoin d’ajouter le rechargement du fusil. Ouvrez Weapon_Rifle.gd et ajouter les variables de classe suivantes :

const CAN_RELOAD = true
const CAN_REFILL = true

const RELOADING_ANIM_NAME = "Rifle_reload"

Ces variables sont exactement les mêmes que celles du pistolet, seul RELOADING_ANIM_NAME change pour l’animation de rechargement du fusil.

Maintenant nous devons ajouter reload_weapon à Weapon_Rifle.gd :

func reload_weapon():
    var can_reload = false

    if player_node.animation_manager.current_state == IDLE_ANIM_NAME:
        can_reload = true

    if spare_ammo <= 0 or ammo_in_weapon == AMMO_IN_MAG:
        can_reload = false

    if can_reload == true:
        var ammo_needed = AMMO_IN_MAG - ammo_in_weapon

        if spare_ammo >= ammo_needed:
            spare_ammo -= ammo_needed
            ammo_in_weapon = AMMO_IN_MAG
        else:
            ammo_in_weapon += spare_ammo
            spare_ammo = 0

        player_node.animation_manager.set_animation(RELOADING_ANIM_NAME)

        return true

    return false

Ce code est exactement le même que celui pour le pistolet.


Le dernier morceau que nous devons faire pour les armes est d’ajouter le “rechargement” du couteau. Ajoutez les variables de classe suivantes à Weapon_Knife.gd :

const CAN_RELOAD = false
const CAN_REFILL = false

const RELOADING_ANIM_NAME = ""

Comme nous ne pouvons recharger ou remplir un couteau, nous mettons à false les deux constantes. On définit aussi RELOADING_ANIM_NAME comme une chaîne vide, vu que le couteau n’a pas d’animation de rechargement.

Maintenant nous devons ajouter reloading_weapon :

func reload_weapon():
    return false

Comme nous ne pouvons pas recharger un couteau, nous retournons toujours false.

Ajout du rechargement au joueur

Maintenant nous devons ajouter quelques choses à Player.gd. D’abord nous devons définir une nouvelle variable de classe :

var reloading_weapon = false
  • reloading_weapon : Une variable pour traquer si le joueur essaie de recharger ou non.

Ensuite nous devons ajouter un nouvel appel de fonction à _physics_process.

Ajoutez process_reloading(delta) à _physics_process. Maintenant _physics_process devrait ressembler à ça :

func _physics_process(delta):
    process_input(delta)
    process_movement(delta)
    process_changing_weapons(delta)
    process_reloading(delta)
    process_UI(delta)

Maintenant nous devons ajouter process_reloading. Ajoutez la fonction suivante à Player.gd :

func process_reloading(delta):
    if reloading_weapon == true:
        var current_weapon = weapons[current_weapon_name]
        if current_weapon != null:
            current_weapon.reload_weapon()
        reloading_weapon = false

Voyons ce qui s’y passe.

D’abord, on s’assure que le joueur essaie de recharger.

Si le joueur essaie de recharger, on récupère ensuite l’arme actuelle. Si l’arme actuelle n’est pas à égale à null, on appelle sa fonction reload_weapon.

Note

Si l’arme actuelle est égale à null, alors l’arme actuelle est UNARMED.

Enfin, nous définissons reloading_weapon à false car, sans tenir compte du fait que le joueur aie correctement rechargé, nous avons essayé de recharger et nous n’avons plus besoin de continuer d’essayer.


Avant que l’on puisse laisser le joueur recharger, nous devons changer quelques choses dans process_input.

La première chose que nous devons modifier est dans le code pour changer d’armes. Nous avons besoin d’ajouter un autre test (if reloading_weapon == false:) pour voir si le joueur est en train de recharger :

if changing_weapon == false:
    # New line of code here!
    if reloading_weapon == false:
        if WEAPON_NUMBER_TO_NAME[weapon_change_number] != current_weapon_name:
            changing_weapon_name = WEAPON_NUMBER_TO_NAME[weapon_change_number]
            changing_weapon = true

Cela permet d’empêcher le joueur de changer d’arme lorsqu’il recharge.

Maintenant nous devons ajouter le code pour déclencher un rechargement lorsque le joueur appuie sur le bouton d’action reload. Ajoutez le code suivant à process_input :

# ----------------------------------
# Reloading
if reloading_weapon == false:
    if changing_weapon == false:
        if Input.is_action_just_pressed("reload"):
            var current_weapon = weapons[current_weapon_name]
            if current_weapon != null:
                if current_weapon.CAN_RELOAD == true:
                    var current_anim_state = animation_manager.current_state
                    var is_reloading = false
                    for weapon in weapons:
                        var weapon_node = weapons[weapon]
                        if weapon_node != null:
                            if current_anim_state == weapon_node.RELOADING_ANIM_NAME:
                                is_reloading = true
                    if is_reloading == false:
                        reloading_weapon = true
# ----------------------------------

Voyons ce qui s’y passe.

D’abord on s’assure que le joueur n’est pas déjà en train de recharger, ou que le joueur essaie de changer d’arme.

Ensuite on vérifie si l’action reload à été pressée.

Si le joueur a appuyé sur reload`, on regarde quel est l’arme courante et on vérifie qu’elle n’est pas null. Ensuite on utilise la constante CAN_RELOAD de l’arme pour savoir si celle-ci peut recharger ou non.

Si l’arme peut être rechargée, on récupère alors l’état d’animation courant, et faisons une variable pour traquer si le joueur est déjà en train de recharger ou pas.

On fait ensuite le tour de chaque arme pour s’assurer que le joueur n’est pas déjà en train de jouer l’animation de recharge de l’arme.

Si le joueur n’est pas en train de recharger une arme, nous mettons la variable reloading_weapon à true.


Une chose que j’aime ajouter est le rechargement automatique de l’arme lorsque l’on essaye de tirer alors qu’elle est déchargée.

On a besoin d’ajouter une nouvelle condition (is_reloading_weapon == false:) pour que le joueur ne puisse pas tirer avec son arme actuelle lorsqu’il recharge.

Transformons notre code de tir en process_input afin que l’arme se recharge quand on essaye de tirer sans munitions dans le chargeur :

# ----------------------------------
# Firing the weapons
if Input.is_action_pressed("fire"):
    if reloading_weapon == false:
        if changing_weapon == false:
            var current_weapon = weapons[current_weapon_name]
            if current_weapon != null:
                if current_weapon.ammo_in_weapon > 0:
                    if animation_manager.current_state == current_weapon.IDLE_ANIM_NAME:
                        animation_manager.set_animation(current_weapon.FIRE_ANIM_NAME)
                else:
                    reloading_weapon = true
# ----------------------------------

Maintenant, nous allons nous assurer que le joueur n’est pas en train de recharger au moment de tirer. Lorsque nous avons 0 munitions ou moins dans l’arme actuelle, nous assignons true à la variable reloading_weapon si le joueur essaye de tirer.

De cette manière, le joueur va recharger lorsqu’il tentera de tirer avec une arme vide.


Ceci fait, le joueur peut maintenant recharger ! Essayez ! Maintenant, vous pouvez tirer toutes les munitions de rechange de l’arme.

Ajouter des sons

Enfin, ajoutons quelques sons qui vont accompagner le rechargement, le tir et le changement d’arme.

Astuce

Nous ne proposons aucun assets de sons dans ce tutoriel (pour des raisons légales). https://gamesounds.xyz/ est une collection de « sons et musiques du domaine public qui conviennent aux jeux video ». J’ai utilisé le Gamemaster’s Gun Sound Pack qui peut être trouvé dans le Sonniss.com GDC 2017 Game Audio Bundle.

Ouvrez Simple_Audio_Player.tscn. Il s’agit simplement d’un Spatial avec un AudioStreamPlayer comme enfant.

Note

La raison pour laquelle cela est appelé un « simple » lecteur audio est du fait que nous ne prenons pas en compte les performances et parce que le code est conçu pour fournir du son de la manière la plus simple possible.

Si vous souhaitez utiliser de l’audio 3D, de sorte qu’il semble que cela vient d’un espace 3D, cliquez droit sur le AudioStreamPlayer et sélectionnez « Change type ».

Cela ouvrira le navigateur de nœud. Naviguez vers AudioStreamPlayer3D et sélectionnez « change ». Dans les sources de ce tutoriel, nous allons utiliser AudioStreamPlayer, mais vous pouvez utiliser AudioStreamPlayer3D si vous le souhaitez. Le code fourni ci-dessous fonctionnera indépendamment duquel vous choisirez.

Créez un nouveau script et appelez-le Simple_Audio_Player.gd. Attachez-le à Spatial dans Simple_Audio_Player.tscn et insérez le code suivant :

extends Spatial

# All of the audio files.
# You will need to provide your own sound files.
var audio_pistol_shot = preload("res://path_to_your_audio_here")
var audio_gun_cock = preload("res://path_to_your_audio_here")
var audio_rifle_shot = preload("res://path_to_your_audio_here")

var audio_node = null

func _ready():
    audio_node = $Audio_Stream_Player
    audio_node.connect("finished", self, "destroy_self")
    audio_node.stop()


func play_sound(sound_name, position=null):

    if audio_pistol_shot == null or audio_rifle_shot == null or audio_gun_cock == null:
        print ("Audio not set!")
        queue_free()
        return

    if sound_name == "Pistol_shot":
        audio_node.stream = audio_pistol_shot
    elif sound_name == "Rifle_shot":
        audio_node.stream = audio_rifle_shot
    elif sound_name == "Gun_cock":
        audio_node.stream = audio_gun_cock
    else:
        print ("UNKNOWN STREAM")
        queue_free()
        return

    # If you are using an AudioStreamPlayer3D, then uncomment these lines to set the position.
    #if audio_node is AudioStreamPlayer3D:
    #    if position != null:
    #        audio_node.global_transform.origin = position

    audio_node.play()


func destroy_self():
    audio_node.stop()
    queue_free()

Astuce

En mettant position à null par défaut dans play_sound, nous en faisons un argument facultatif, signifiant que position n’a pas nécessairement besoin d’être passé en paramètre pour appeler play_sound.

Voyons ce qui se passe ici :


Dans _ready, nous récupérons le AudioStreamPlayer et connectons son signal finished à la fonction destroy_self. Peu importe qu’il s’agisse d’un nœud AudioStreamPlayer ou d’un nœud AudioStreamPlayer3D, car ils ont tous deux le signal finished. Pour s’assurer qu’il ne joue pas de sons, nous appelons stop sur le AudioStreamPlayer.

Avertissement

Assurez vous que vos fichiers sons ne sont pas réglés sur boucle ! Si c’est le cas, les sons continueront de jouer à l’infini et ne script ne marchera pas !

La fonction play_sound est celle que nous appellerons de Player.gd. Nous vérifions si le son correspond à l’un des trois sons possibles et si c’est l’un des trois sons, nous réglons le flux audio dans AudioStreamPlayer au son correct.

Si c’est un son inconnu, nous affichons un message d’erreur dans la console et on libère le lecteur audio.

Si vous utilisez un AudioStreamPlayer3D, supprimez le # pour définir la position du nœud du lecteur audio afin qu’il joue à la bonne position.

Enfin, nous disons au AudioStreamPlayer de jouer.

Lorsque le AudioStreamPlayer a fini de jouer le son, il va appeler destroy_self parce que nous avons connecté le signal finished dans _ready. Nous arrêtons le AudioStreamPlayer et libérons le lecteur audio pour économiser des ressources.

Note

Ce système est extrêmement simple et présente quelques défauts majeurs :

Un des défaut est que nous devons passer une chaîne de caractère en paramètre pour jouer un son. Bien qu’il soit relativement simple de retenir le nom de trois sons, cela peut devenir de plus en plus complexe quand nous avons plus de sons. Idéalement, nous placerions ces trois sons dans un conteneur avec des variables exposés afin de ne pas avoir à retenir le(s) nom(s) de chaque son que nous voulons jouer.

Un des autres défauts est que nous ne pouvons pas jouer des effets sonores en boucle, ni de musique de fond facilement avec ce système. Parce que nous ne pouvons pas jouer de sons en boucle, certains effets comme les sons de pas sont plus difficiles à réaliser car nous devons alors garder une trace de si oui ou non il y a un effet sonore et si oui ou non nous avons besoin de continuer à le jouer.

L’un des plus gros défauts de ce système est que nous ne pouvons jouer que des sons provenant du Player.gd. Idéalement, nous aimerions pouvoir jouer des sons provenant de n’importe quel script à tout moment.


Ceci fait, ouvrons Player.gd à nouveau. Nous devons d’abord charger Simple_Audio_Player.tscn. Placez le code suivant dans la section des variables de classe du script :

var simple_audio_player = preload("res://Simple_Audio_Player.tscn")

Maintenant, nous avons besoin d’instancier le lecteur audio simple quand nous en avons besoin, puis appeler sa fonction play_sound et passer le nom du son que nous voulons jouer. Pour simplifier le processus, créons une fonction create_sound dans Player.gd :

func create_sound(sound_name, position=null):
    var audio_clone = simple_audio_player.instance()
    var scene_root = get_tree().root.get_children()[0]
    scene_root.add_child(audio_clone)
    audio_clone.play_sound(sound_name, position)

Passons en revue ce que cette fonction fait :


La première ligne instancie la scène Simple_Audio_Player.tscn``et l'assigne à une variable appelée ``audio_clone.

La seconde ligne récupère la racine de la scène et fait une grosse (bien que sûre) supposition.

Nous récupérons d’abord la SceneTree sur laquelle le jeu tourne. Ensuite, nous allons chercher le premier enfant de la Viewport, qui dans notre cas s’avère être le nœud source de Test_Area.tscn ou n’importe quel autre niveau fournis. Nous faisons une énorme hypothèse ici en assumant que le premier enfant du nœud source est la scène source sur laquelle se situe le joueur, ce qui n’est pas tout le temps le cas.

Si cela n’a pas de sens à vos yeux, ne vous en faites pas trop. La seconde ligne de code ne fonctionne pas de façon fiable si vous avez plusieurs scènes chargées en tant qu’enfant du nœud source à la fois, ce qui n’arrive que rarement dans la plupart des projets et qui n’arrivera pas dans cette série de tutoriels. C’est un potentiel problème suivant la façon dont vous gérez le chargement de scène.

La troisième ligne ajoute notre scène nouvellement créé Simple_Audio_Player comme enfant de la scène source. Cela fonctionne exactement de la même façon que l’apparition des balles.

Enfin, nous appelons la fonction play_sound et on lui passe les arguments passés dans create_sound. Cela va appeler la fonction play_sound de ``Simple_Audio_Player.gd``avec les arguments passés en paramètre.


Maintenant, tout ce qu’il reste à faire c’est de jouer les sons quand nous le voulons. Ajoutons d’abord du son pour le pistolet d’abord !

Ouvrez Weapon_Pistol.gd.

Le but maintenant est de faire du bruit quand le joueur tire au pistolet. Ajoutez donc ce qui suit à la fin de la fonction fire_weapon :

player_node.create_sound("Pistol_shot", self.global_transform.origin)

Désormais, quand le joueur va tirer au pistolet, nous jouerons le son Pistol_shot.

Pour émettre un son quand le joueur recharge, nous devons ajouter ce qui suit juste en dessous de player_node.animation_manager.set_animation(RELOADING_ANIM_NAME)``dans la fonction ``reload_weapon :

player_node.create_sound("Gun_cock", player_node.camera.global_transform.origin)

Désormais, quand le joueur rechargera, nous jouerons le son Gun_cock.


Ajoutons maintenant du son pour le fusil. Ouvrez Weapon_Rifle.gd.

Afin de jouer un son quand le fusil tire, ajoutez ce qui suit à la fin de la fonction fire_weapon :

player_node.create_sound("Rifle_shot", ray.global_transform.origin)

Désormais, quand le joueur tire au fusil, nous jouerons le son Rifle_shot.

Pour émettre un son quand le joueur recharge, nous devons ajouter ce qui suit juste en dessous de player_node.animation_manager.set_animation(RELOADING_ANIM_NAME)``dans la fonction ``reload_weapon :

player_node.create_sound("Gun_cock", player_node.camera.global_transform.origin)

Désormais, quand le joueur rechargera, nous jouerons le son Gun_cock.

Notes finales

../../../_images/PartThreeFinished.png

Maintenant, vous avez des armes avec des munitions limités qui jouent des sons quand vous tirez avec !

À ce stade, nous avons toutes les bases fonctionnelles d’un jeu en vue FPS. Nous pourrions cependant ajouter quelques améliorations, et c’est ce que nous allons faire dans les trois prochaines parties !

Par exemple, il n’y a à l’heure actuelle aucun moyen d’ajouter des munitions à notre stock, nous allons donc finir par en manquer. aussi, nous rien sur quoi tirer à part les nœuds RigidBody.

Dans Partie 4, nous ajoutons quelques cibles sur lesquelles tirer accompagnées de quelques items permettant de regagner de la vie et des munitions ! Nous allons également ajouter le support des manettes afin que nous puissions jouer avec des manettes Xbox 360 filaires !

Avertissement

Si jamais vous vous perdez, n’oubliez pas de relire le code !

Vous pouvez télécharger le projet terminé pour cette partie ici : Godot_FPS_Part_3.zip