Tutoriel FPS - Partie 3 : Les munitions et les sons

Répondre
Avatar du membre
keltwookie
Admin du site
Messages : 81
Enregistré le : mer. avr. 04, 2018 5:42 pm
Localisation : Kashyyyk
Contact :

Tutoriel FPS - Partie 3 : Les munitions et les sons

Message par keltwookie » jeu. mai 03, 2018 1:27 am

Apercu de la partie 3

Dans cette partie, nous limiterons nos armes en leur donnant des munitions. Nous donnerons également au joueur la possibilité de recharger, et nous ajouterons des sons lorsque les armes tireront.


Image
A la fin de cette partie, le joueur aura des munitions limitées, la possibilité de recharger, et des sons seront joués quand le joueur tirera et changera d'armes.

Remarque :Vous êtes supposé avoir terminé Tutoriel FPS - Partie 2 : Les armes avant de passer à cette partie du tutoriel. Le projet terminé de la partie 2 sera le projet de départ de la partie 3.

Commençons !



Changements de niveau


Maintenant que nous avons un FPS pleinement fonctionnel, rapprochons nous encore de ce qu’il devrait être réellement.
Ouvrez Space_Level.tscn (assets/Space_Level_Objects/Space_Level/Space_Level.tscn) et/ou Ruins_Level.tscn (assets/Ruin_Level_Objects/Ruins_Level_Level.tscn).
Space_Level.tscn et Ruins_Level.tscn sont des niveaux FPS personnalisés complets créés dans le but de ce tutoriel. Appuyez sur F6 pour lire la scène ouverte, ou appuyez sur le bouton de lecture de la scène en cours, et faîtes un essai.

Attention :
Space_Level.tscn est plus exigeant, en terme d’utilisation GPU que Ruins_Level.tscn. Si votre ordinateur a du mal à rendre Space_Level.tscn, essayez d'utiliser Ruins_Level.tscn à la place.


Vous avez peut-être remarqué qu'il y a plusieurs nœuds RigidBody inclus dans le niveau. Nous pouvons placer RigidBody_hit_test.gd dessus pour que ces nœuds réagissent à l’impact des balles, alors faisons cela !
Suivez les instructions ci-dessous pour l'une ou l'autre (ou les deux) des scènes que vous voulez utiliser :

Développez "Other_Objects", ensuite "Turrets_And_Physics_Objects".

Développez l'un des nœuds "Barrel_Group", puis sélectionnez "Barrel_Rigid_Body" et ouvrez-le à l'aide du bouton "Open in Editor". Cela vous amènera à la scène "Barrel_Rigid_Body". A partir de là, sélectionnez le nœud racine et faire défiler l'inspecteur jusqu'en bas.
Sélectionnez la flèche déroulante sous l'onglet "Node", puis sélectionnez "Load". Naviguer jusqu'à "RigidBody_hit_test.gd" et sélectionnez "Open".

Retournez à "Space_Level.tscn" :

Développez l'un des nœuds "Box_Group", puis sélectionnez "Box_Rigid_Body" et ouvrez-le à l'aide du bouton "Open in Editor".
Cela vous amènera à la scène "Box_Rigid_Body". De là, sélectionnez le nœud racine et faites défiler l'inspecteur vers le bas.
Sélectionnez la flèche déroulante sous l'onglet "Node", puis sélectionnez "Load". Naviguez jusqu'à "RigidBody_hit_test.gd" et sélectionnez "Open».

Pour Ruins_Level.tscn:

développez "Misc_Objects" puis "Physics_Objects".
Sélectionnez tous les RigidBodies "Stone_Cube", puis dans l'inspecteur, faites défiler vers le bas.
Sélectionnez la flèche déroulante sous l'onglet "Node", puis sélectionnez "Load". Naviguez jusqu'à "RigidBody_hit_test.gd" et sélectionnez "Open".

Retournez à "Ruins_Level.tscn".

Maintenant vous pouvez tirer sur tous les RigidBodies dans l'un ou l'autre niveau !



Ajouter les munitions


Maintenant que nous avons des armes en état de marche, donnons-leur une quantité limitée de munitions.

Nous devons d'abord définir quelques variables dans chacun de nos scripts d'armes.
Ouvrez Weapon_Pistol.gd et ajoutez les variables globales suivantes :

Code : Tout sélectionner

var ammo_in_weapon = 10
var spare_ammo = 20
const AMMO_IN_MAG = 10
ammo_in_weapon : La quantité de munitions actuellement dans le pistolet.
spare_ammo : La quantité de munitions que nous avons laissé en réserve pour le pistolet.
AMMO_IN_MAG : La quantité de munitions dans une arme entièrement rechargée.

Maintenant, tout ce que nous avons à faire est d'ajouter une seule ligne de code à fire_weapon.

Ajouter la ligne suivante sous clone.BULLET_DAMAGE = DAMAGE :

Code : Tout sélectionner

ammo_in_weapon -= 1
Cela enlèvera une unité ammo_in_weapon à chaque fois que nous tirons. Notez que nous ne vérifions pas si nous avons un compte de munitions de 0 ou plus dans fire_weapon. Au lieu de cela, nous allons vérifier le nombre de munitions dans Player.gd.

Maintenant, nous devons ajouter des munitions pour le fusil et le couteau.

Remarque :
Vous vous demandez peut-être pourquoi nous ajoutons des munitions pour le couteau étant donné qu'il ne consomme pas de munitions. La raison est que nous voulons une interface cohérente pour toutes nos armes.
Si nous n'ajoutions pas de variables de munitions pour le couteau, nous devrions ajouter des vérifications pour le couteau. En ajoutant les variables de munitions au couteau, nous n'avons pas à nous inquiéter de savoir si toutes nos armes ont les mêmes variables.


Ajouter les variables globales suivantes à Weapon_Rifle.gd :

Code : Tout sélectionner

var ammo_in_weapon = 50
var spare_ammo = 100
const AMMO_IN_MAG = 50
Et puis ajouter ce qui suit à fire_weapon :

Code : Tout sélectionner

ammo_in_weapon -= 1.
Assurez-vous que ammo_in_weapon -= 1 est à l'extérieur de la vérification if ray.is_colliding() afin que nous perdions des munitions, que nous ayons touché quelque chose ou non.

Il ne reste plus que le couteau. Ajoutez ce qui suit à Weapon_Knife.gd :

Code : Tout sélectionner

var ammo_in_weapon = 1
var spare_ammo = 1
const AMMO_IN_MAG = 1
Et parce que notre couteau ne consomme pas de munitions, c'est tout ce que nous avons besoin d'ajouter.

Maintenant, tout ce que nous avons à faire est de changer une chose dans Player.gd et c'est la façon dont nous tirons avec nos armes dans process_input. Modifier le code comme suit :

Code : Tout sélectionner

# ----------------------------------
# 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, nos armes ont une quantité limitée de munitions et cesseront de tirer lorsque nous serons à court .

Idéalement, nous aimerions pouvoir voir combien de munitions il nous reste. Etablissons une nouvelle fonction appelée process_ui.

Tout d'abord, ajoutez la fonction process_UI(delta) à _physics_process.

Maintenant, ajoutez ce qui suit à Player.gd :

Code : Tout sélectionner

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)
Voyons ce qui se passe :

Nous vérifions d'abord si l'arme actuelle est UNARMED ou KNIFE. Si c'est le cas, nous changeons le texte de l'étiquette UI_status_label pour ne montrer que notre santé, puisque UNARMED et KNIFE ne consomment pas de munitions.

Maintenant nous pouvons voir combien de munitions nous avons depuis le HUD.



Ajouter le rechargement des armes


Maintenant que nous sommes à court de munitions, nous avons vraiment besoin d'un moyen de remplir notre arme à nouveau. Ajoutons le rechargement !
Pour recharger, nous devons ajouter quelques variables supplémentaires et une fonction à chaque arme.

Ouvrez Weapon_Pistol.gd et ajoutez les variables globales suivantes :
  • CAN_RELOAD : Un booléen pour savoir si cette arme a la capacité de se recharger.
  • CAN_REFIL : Un booléen pour savoir si nous pouvons recharger les munitions de rechange de cette arme. Nous n'utiliserons pas CAN_REFIL dans cette partie, mais nous le ferons dans la partie suivante !
  • RELOADING_ANIM_NAME : Le nom de l'animation de rechargement pour cette arme.
Nous devons maintenant ajouter une fonction pour gérer le rechargement dans Weapon_Pistol.gd :

Code : Tout sélectionner

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
Voyons ce qui se passe :

Tout d'abord, nous définissons une variable pour voir si nous pouvons recharger ou non.

Nous vérifions d'abord si nous sommes dans l'état d'animation de cette arme parce que nous ne voulons pouvoir recharger que lorsque nous ne tirons pas.

Ensuite, nous vérifions si nous avons des munitions de rechange, et si les munitions déjà dans notre arme sont égales à une arme entièrement rechargée. De cette façon, nous pouvons nous assurer que nous n'allons pas recharger lorsque nous n'avons pas de munitions ou lorsque l'arme est déjà pleine.

Si nous pouvons encore recharger, nous calculons la quantité de munitions nécessaires pour recharger l'arme.

Si nous avons assez de munitions pour remplir l'arme, nous enlevons les munitions nécessaires de spare_ammo, puis nous réglons ammo_in_weapon sur une arme complètement chargée.

Si nous n'avons pas assez de munitions, nous ajoutons toutes les munitions qui restent dans spare_ammo, puis le mettons à 0.

Ensuite, nous jouons l'animation de rechargement pour cette arme, puis nous retournons true.
Si nous n'avons pas pu recharger, nous renvoyons false.

Maintenant nous devons ajouter le rechargement de la carabine. Ouvrez Weapon_Rifle.gd et ajoutez les variables globales suivantes :

Code : Tout sélectionner

const CAN_RELOAD = true
const CAN_REFILL = true

const RELOADING_ANIM_NAME = "Rifle_reload"
Ces variables sont exactement les mêmes que le pistolet, juste avec RELOADING_ANIM_NAMEdésignant l'animation de rechargement du fusil.

Il ne nous reste plus qu'à ajouter reload_weapon à Weapon_Rifle.gd :

Code : Tout sélectionner

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 du pistolet.

La dernière chose que nous devons faire pour les armes est d'ajouter "rechargement" au couteau. Ajoutez les variables globales suivantes à Weapon_Knife.gd :

Code : Tout sélectionner

const CAN_RELOAD = false
const CAN_REFILL = false

const RELOADING_ANIM_NAME = ""
Puisque nous ne pouvons « recharger » un couteau, nous avons mis les deux constantes à false. Nous définissons aussi RELOADING_ANIM_NAME comme une chaîne vide, puisque le couteau n'a pas d'animation de rechargement.

Maintenant nous avons juste besoin d'ajouter reloading_weapon, et heureusement c'est vraiment simple :

Code : Tout sélectionner

func reload_weapon():
    return false
Comme nous ne pouvons pas recharger un couteau, nous retournons toujours false.



Ajouter le rechargement au joueur


Maintenant nous avons juste besoin d'ajouter quelques choses à Player.gd. Tout d'abord, nous devons définir une nouvelle variable globale :

Code : Tout sélectionner

var reloading_weapon = false
  • reloading_weapon: C’est une variable pour savoir si oui ou non nous essayons actuellement de recharger.
Ensuite, nous devons ajouter un autre appel de fonction à _physics_process.

Ajouter process_reloading(delta) à _physics_process. Cela devrait ressembler à ceci :

Code : Tout sélectionner

func _physics_process(delta):
    process_input(delta)
    process_movement(delta)
    process_changing_weapons(delta)
    process_reloading(delta)
    process_UI(delta)
Nous devons maintenant ajouter process_reloading. Ajoutez la fonction suivante à Player.gd :

Code : Tout sélectionner

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 se passe ici :

Nous vérifions d'abord pour nous assurer que nous essayons de recharger.

Si c'est le cas, nous obtenons l'arme actuelle. Si l'arme courante n'est pas égale à null, nous appelons sa fonction reload_weapon.

Remarque :
Si l'arme actuelle est égale à null, alors l'arme actuelle est sur UNARMED.


Enfin, nous avons mis reloading_weapon à false, parce que peu importe si nous avons rechargé avec succès, nous avons essayé de recharger et nous n'avons plus besoin de continuer à essayer.

Avant de pouvoir recharger, nous devons modifier certaines choses dans process_input.

La première chose que nous devons changer, c'est le code de changement d'armes. Nous devons ajouter une vérification supplémentaire (si reloading_weapon == false :) pour voir si nous rechargeons :

Code : Tout sélectionner

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
C'est pourquoi nous ne pouvons pas changer d'armes si nous rechargeons.

Nous devons maintenant ajouter le code pour déclencher une recharge lorsque le joueur appuie sur l'action correspondante. Ajoutez le code suivant à process_input :

Code : Tout sélectionner

# ----------------------------------
# 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 se passe ici :

D'abord, nous nous assurons que nous ne rechargeons pas déjà, et que nous n'essayons pas non plus de changer d'armes.

Ensuite, nous vérifions si l'action de rechargement a été activée.

Si nous avons activé le rechargement, nous obtenons alors l'arme actuelle et vérifions qu'elle n'est pas nulle. Ensuite, nous vérifions si l'arme peut se recharger ou non à l'aide de sa constante CAN_RELOAD.

Si l'arme peut être rechargée, on obtient alors l'état actuel de l'animation, et on fait une variable pour savoir si on est déjà en train de recharger ou non.

Nous passons ensuite en revue toutes les armes pour nous assurer que nous ne jouons pas déjà l'animation de rechargement de cette arme.

Si nous ne rechargeons pas avec une arme, nous réglons rechargement_weapon à true.

Une chose que j'aime ajouter est que l'arme se rechargera d'elle-même si vous essayez de tirer quand il n'y a plus de munitions.

Nous devons aussi ajouter une vérification supplémentaire (is_reloading_weapon == false :) afin que nous ne puissions pas tirer avec l'arme en cours pendant le rechargement.

Changeons notre code de tir dans process_input pour qu'il se recharge quand on essaie de tirer avec une arme vide :

Code : Tout sélectionner

# ----------------------------------
# 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 vérifions pour nous assurer que nous ne rechargeons pas avant de tirer, et lorsque nous avons 0 ou moins de munitions dans notre arme, nous réglons reloading_weapon à true si nous essayons de tirer.

Cela en fera l'endroit où nous essaierons de recharger lorsque nous tenterons de tirer avec une arme vide.

Avec cela, nous pouvons recharger nos armes ! Essayez-le ! Maintenant, vous pouvez tirer toutes les munitions de rechange pour chaque arme.



Ajouter des sons


Enfin, ajoutons quelques sons qui se jouent lorsque nous rechargeons, changeons les armes et lorsque nous tirons.

Astuce:
Il n'y a pas de sons de jeu fournis dans ce tutoriel (pour des raisons légales). https://gamesounds.xyz/ est une collection de musiques et sons adaptés aux jeuxlibres de droits ou du domaine public. J'ai utilisé Gamemaster's Gun Sound Pack, qui se trouve dans Sonniss.com GDC 2017 Game Audio Bundle. (ndt : voir ici)


Ouvrez SimpleAudioPlayer.tscn. Il s'agit simplement d'un Spatial avec un AudioStreamPlayer comme nœud-enfant.

Remarque :
La raison pour laquelle on appelle cela un lecteur audio' simple' est que nous ne prenons pas en compte les performances et parce que le code est conçu pour fournir le son de la manière la plus simple possible.
Si vous voulez utiliser de l'audio 3D, de sorte qu'il semble provenir d'un emplacement dans l'espace 3D, faites un clic droit sur le AudioStreamPlayer et sélectionnez "Change type".
Cela ouvrira le navigateur de nœuds. Naviguez jusqu'à AudioStreamPlayer3D et sélectionnez "change". Dans la source de ce tutoriel, nous utiliserons AudioStreamPlayer, mais vous pouvez éventuellement utiliser AudioStreamPlayer3D si vous le souhaitez, le code fourni ci-dessous fonctionnera quel que soit celui que vous avez choisi.


Créez un nouveau script et appelez-le SimpleAudioPlayer.gd. Attachez-le au nœud Spatial dans SimpleAudioPlayer.tscn et insérez le code suivant :

Code : Tout sélectionner

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 a AudioPlayer3D, then uncomment these lines to set the position.
    # if position != null:
    #       audio_node.global_transform.origin = position

    audio_node.play()


func destroy_self():
    audio_node.stop()
    queue_free()
Astuce :
En réglant la position à null par défaut dans play_sound, nous en faisons un argument optionnel, ce qui signifie que la position n'a pas nécessairement besoin d'être passée pour l'appeler.


Voyons ce qui se passe ici :

Dans _ready nous obtenons le AudioStreamPlayer et nous connectons son signal fini à nous-mêmes. Peu importe s'il s'agit d'un noeud AudioStreamPlayer3D, car ils ont tous les deux le signal fini. Pour s'assurer qu'il ne joue aucun son, nous appelons stop sur le AudioStreamPlayer.

Attention :
Assurez-vous que vos fichiers son ne sont pas mis en boucle ! S'il sont réglés en boucle, les sons continueront à jouer à l'infini et le script ne fonctionnera pas !


La fonction play_sound est ce que nous appellerons depuis Player.gd. Nous vérifions si le son est l'un des trois sons possibles, et si c'est le cas, nous réglons le flux audio pour notre AudioStreamPlayer sur le son correct.

S'il s'agit d'un son inconnu, nous imprimons un message d'erreur sur la console et envoyons le signal de fin de script ( queue_free).

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 terminé de jouer le son, il appellera destroy_self parce que nous avons connecté le signal fini dans _ready. Nous arrêtons le AudioStreamPlayer et nous envoyons queue_free pour économiser les ressources.

Remarque :
Ce système est extrêmement simple mais présente des défauts majeurs :
Un premier défaut est que nous devons passer une valeur de chaîne de caractères pour jouer un son. Bien qu'il soit relativement simple de se rappeler les noms des trois sons, il peut être de plus en plus complexe lorsque vous avez plus de sons. Idéalement, nous placerions ces sons dans une sorte de conteneur avec des variables exposées afin que nous n'ayons pas à nous souvenir du nom de chaque effet sonore que nous voulons jouer.
Un autre défaut est que nous ne pouvons pas jouer des effets sonores en boucle, ni de la musique de fond facilement avec ce système. Parce que nous ne pouvons pas jouer des sons en boucle, certains effets comme les bruits de pas sont plus difficiles à réaliser parce que nous devons alors garder une trace de l'existence ou non d'un effet sonore et de la nécessité ou non de continuer à le jouer.
L'une des plus grandes failles de ce système est que nous ne pouvons jouer que les sons de Player.gd. Idéalement, nous aimerions pouvoir jouer des sons de n'importe quel script à n'importe quel moment.


Cela fait, ouvrons à nouveau Player.gd. Nous devons d'abord charger le fichier SimpleAudioPlayer.tscn. Placez le code suivant dans vos variables globales :

Code : Tout sélectionner

var simple_audio_player = preload("res://Simple_Audio_Player.tscn")
Maintenant nous avons juste 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 :

Code : Tout sélectionner

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)
La première ligne instancie la scène Simple_Audio_Player.tscn et l'assigne à une variable, nommée audio_clone.

La deuxième ligne obtient la racine de la scène, en utilisant un postulat généraliste. Nous obtenons d'abord le SceneTree, puis nous accédons au noeud racine, qui dans ce cas est le Viewport du jeu en cours d'exécution. Ensuite, nous obtenons le premier enfant Viewport, qui dans notre cas se trouve être le noeud racine dans Test_Area.tscn ou n'importe lequel des autres niveaux fournis. Nous partons du principe que le premier enfant de la racine est le nœud racine sous lequel se trouve notre joueur, ce qui peut ne pas toujours être le cas.

Si cela n'a pas de sens pour vous, ne vous en faites pas trop. La deuxième ligne de code ne fonctionne de manière fiable que si vous avez plusieurs scènes chargées en tant qu'enfants dans le nœud racine en même temps, ce qui se produira rarement pour la plupart des projets. Ce n'est vraiment qu'un problème potentiel qui dépend de la façon dont vous gérez le chargement des scènes.

La troisième ligne ajoute notre scène SimpleAudioPlayer nouvellement créée pour être un enfant de la scène racine. Cela fonctionne exactement de la même façon que lorsque nous générons des balles.

Enfin, nous appelons la fonction play_sound et passons les arguments qui nous sont donnés. Ceci appellera la fonction play_sound de SimpleAudioPlayer.gd avec les arguments passés.

Maintenant, il ne nous reste plus qu'à jouer les sons quand nous le voulons. Ajoutons d'abord le son du pistolet !

Ouvrez Weapon_Pistol.gd.

Maintenant, nous voulons faire un son quand nous tirons au pistolet, alors ajoutez ce qui suit à la fin de la fonction fire_weapon :

Code : Tout sélectionner

player_node.create_sound("pistol_shot", self.global_transform.origin)
Maintenant, quand nous tirerons avec notre pistolet, nous jouerons le son pistol_shot.

Pour faire un son lors du rechargement, il suffit d'ajouter sous player_node.animation_manager.set_animation(RELOADING_ANIM_NAME) dans la fonction reload_weapon :

Code : Tout sélectionner

player_node.create_sound("gun_cock", player_node.camera.global_transform.origin)
Maintenant, quand on rechargera, on jouera le son gun_cock.


Remarques finales
Image
Maintenant vous avez des armes avec des munitions limitées qui jouent des sons quand vous les tirez !

A ce stade, nous avons toutes les bases d'un FPS qui fonctionne. Il y a encore quelques petites choses qu'il serait agréable d'ajouter, et nous allons les ajouter dans les trois prochaines parties !

Par exemple, à l'heure actuelle, nous n'avons aucun moyen d'ajouter des munitions à nos pièces de rechange. De plus, nous n'avons rien sur quoi tirer en dehors des nœuds RigidBody .

Dans Tutoriel FPS - partie 4, nous ajouterons des cibles sur lesquelles tirer, ainsi que des collectes de munitions et de santé ! Nous allons également ajouter le support des joypads, de sorte que nous pourrons jouer avec des manettes Xbox 360 !

Attention :
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

Tutoriel FPS - Partie 3 - Version PDF téléchargeable
- Le projet"XPlore"
- Tutos Blender
- Tutos Godot Game Engine

“ L'artiste est un malade qui essaie de se soigner en créant, mais plus il se soigne, plus il est malade. Et plus il est malade, plus il est content, vu qu'il n'a aucune envie de guérir." Philippe Geluck