Générer des monstres

Dans cette partie, nous allons faire apparaître des monstres aléatoirement le long d'un chemin. D'ici la fin, vous aurez des monstres qui parcourront le plateau de jeu.

image0

Doublez-cliquez sur Main.tscn dans le dock Système de fichiers pour ouvrir la scène Main.

Avant de tracer le chemin, nous allons changer la définition du jeu. Notre jeu a une taille de fenêtre par défaut de 1024x600. Nous allons la définir à 720x540, une belle petite boîte.

Allez dans Projet -> Paramètres du projet.

image1

Dans le menu de gauche, naviguez jusqu'à Display -> Window. À droite, mettez la Width à 720 et la Height à 540.

image2

Création du chemin d'apparition

Comme vous l'avez fait dans le tutoriel du jeu 2D, vous allez tracer un chemin et utiliser un nœud PathFollow pour échantillonner des emplacements aléatoires dessus.

Cependant, en 3D, c'est un peu plus compliqué de dessiner le chemin. Nous voulons qu'il soit autour de la vue du jeu pour que les monstres apparaissent à l'extérieur de l'écran. Mais si nous traçons un chemin, nous ne le verrons pas dans l'aperçu de la caméra.

Pour trouver les limites de la vue, nous pouvons utiliser des modèles temporaires. Votre fenêtre d'affichage devrait toujours être divisée en deux parties, avec l'aperçu de la caméra en bas. Si ce n'est pas le cas, appuyez sur Ctrl + 2 (Cmd + 2 sur MacOS) pour diviser la vue en deux. Sélectionnez le nœud Camera et cochez la case Aperçu dans la vue du bas.

image3

Ajout de cylindres génériques

Ajoutons les modèles temporaires. Ajoutez un nouveau nœud Spatial comme enfant du nœud Main, et nommez-le Cylinders. Nous l'utiliserons pour regrouper les cylindres. Comme enfant de ce nœud, ajoutez un nœud MeshInstance.

image4

Dans l'Inspecteur, assignez un CylinderMesh à la propriété Mesh.

image5

Définissez la vue du haut sur la vue de dessus orthogonale en utilisant le menu dans le coin supérieur gauche de la fenêtre d'affichage. Vous pouvez également appuyer sur la touche 7 du pavé numérique.

image6

La grille est un peu gênante pour moi. Vous pouvez la désactiver en allant dans le menu Affichage de la barre d'outils et en cliquant sur Afficher la grille.

image7

Vous voulez maintenant déplacer le cylindre le long du plan du sol, en regardant l'aperçu dans la vue du bas. Je recommande d'utiliser l'accrochage à la grille pour ce faire. Vous pouvez l'activer en cliquant sur l'icône d'aimant dans la barre d'outils ou en appuyant sur Y.

image8

Placez le cylindre de façon à ce qu'il soit juste en dehors du champ de vision de la caméra dans le coin supérieur gauche.

image9

Nous allons créer des copies du maillage et les placer autour de la zone de jeu. Appuyez sur Ctrl + D (Cmd + D sur MacOS) pour dupliquer le nœud. Vous pouvez également faire un clic droit sur le nœud dans le dock Scène et sélectionner Dupliquer. Déplacez la copie vers le bas le long de l'axe Z bleu jusqu'à ce qu'elle soit juste en dehors de l'aperçu de la caméra.

Sélectionnez les deux cylindres en maintenant la touche Shift et en cliquant sur celui qui n'est pas sélectionné, et dupliquez-les.

image10

Déplacez-les vers la droite en faisant glisser l'axe X rouge.

image11

Ils sont un peu difficiles à voir en blanc, n'est-ce pas ? Faisons-les ressortir en leur donnant un nouveau matériau.

En 3D, les matériaux définissent les propriétés visuelles d'une surface, comme sa couleur, comment elle reflète la lumière, etc. Nous pouvons les utiliser pour modifier la couleur d'un modèle.

Nous pouvons mettre à jour les quatre cylindres en même temps. Sélectionnez toutes les instances de modèles dans le dock Scène. Pour ce faire, vous pouvez cliquer sur la première et faire un shift-clic sur la dernière.

image12

Dans l'Inspecteur, développez la section Material et assignez un SpatialMaterial à l'emplacement 0.

image13

Cliquez sur l'icône de sphère pour ouvrir la ressource du matériau. Vous obtenez un aperçu du matériau et une longue liste de sections remplies de propriétés. Vous pouvez les utiliser pour créer toutes sortes de surfaces, allant du métal jusqu'à la roche ou l'eau.

Développez la section Albedo et définissez une couleur qui contraste avec le fond, comme un orange vif.

image14

Nous pouvons maintenant utiliser les cylindres comme des guides. Repliez-les dans le dock Scène en cliquant sur la flèche grise à côté d'eux. À l'avenir, vous pourrez également modifier leur visibilité en cliquant sur l'icône d'œil à côté de Cylinders.

image15

Ajoutez un nœud Path comme enfant de Main. Dans la barre d'outils, quatre icônes apparaissent. Cliquez sur l'outil Ajouter un point, symbolisé par un "+" vert.

image16

Note

Vous pouvez survoler n'importe quelle icône pour voir une info-bulle décrivant l'outil.

Cliquez au centre de chaque cylindre pour créer un point. Ensuite, cliquez sur l'icône Fermer la courbe dans la barre d'outils pour fermer le chemin. Si un point est un peu décalé, vous pouvez le glisser pour le repositionner.

image17

Votre chemin devrait ressembler à ceci.

image18

Pour échantillonner des positions aléatoires sur le chemin, nous avons besoin d'un nœud PathFollow. Ajoutez un PathFollow comme enfant du Path. Renommez les deux nœuds en SpawnPath et SpawnLocation, respectivement. C'est plus descriptif de ce pour quoi nous allons les utiliser.

image19

Avec ça, nous sommes prêts à coder le mécanisme d'apparition.

Faire apparaître des monstres au hasard

Faites un clic droit sur le nœud Main et attachez-y un nouveau script.

Nous exportons d'abord une variable vers l'Inspecteur afin que nous puissions lui attribuer Mob.tscn ou n'importe quel autre monstre.

Ensuite, comme nous allons faire apparaître les monstres de manière procédurale, nous voulons que les numéros soient aléatoires à chaque fois que nous jouons. Sinon, les monstres apparaîtront toujours selon la même séquence.

extends Node

export (PackedScene) var mob_scene


func _ready():
    randomize()

Nous voulons faire apparaître les mobs à des intervalles de temps réguliers. Pour ça, nous devons revenir à la scène et ajouter un timer. Mais avant cela, nous devons affecter le fichier Mob.tscn à la propriété mob_scene.

Revenez à l'écran 3D et sélectionnez le nœud Main. Faîtes glisser Mob.tscn depuis le dock Système de fichiers vers l'emplacement Mob Scene dans l'Inspecteur.

image20

Ajoutez un nouveau nœud Timer comme enfant de Main. Nommez-le MobTimer.

image21

Dans l'Inspecteur, réglez son Wait Time à 0.5 secondes et activez l'Autostart pour qu'il commence automatiquement au lancement du jeu.

image22

Les timers émettent un signal timeout à chaque fois qu'ils atteignent la fin de leur Wait Time. Par défaut, ils redémarrent automatiquement, en émettant le signal dans un cycle. Nous pouvons nous connecter à ce signal depuis le nœud Main pour faire apparaître des monstres toutes les 0.5 secondes.

En gardant le MobTimer sélectionné, allez dans le dock Nœud à droite, et double-cliquez sur le signal timeout.

image23

Connectez-le au noeud Main.

image24

Cela vous ramènera au script, avec une nouvelle fonction vide _on_MobTimer_timeout().

Codons la logique d'apparition des mobs. Nous allons :

  1. Instancier la scène du mob.

  2. Échantillonner une position aléatoire sur le chemin d'apparition.

  3. Récupérer la position du joueur.

  4. Appeler la méthode initialize() du mob, en lui passant la position aléatoire et la position du joueur.

  5. Ajouter le mob comme enfant du nœud Main.

func _on_MobTimer_timeout():
    # Create a new instance of the Mob scene.
    var mob = mob_scene.instance()

    # Choose a random location on the SpawnPath.
    # We store the reference to the SpawnLocation node.
    var mob_spawn_location = get_node("SpawnPath/SpawnLocation")
    # And give it a random offset.
    mob_spawn_location.unit_offset = randf()

    var player_position = $Player.transform.origin
    mob.initialize(mob_spawn_location.translation, player_position)

    add_child(mob)

Ci-dessus, randf() produit une valeur aléatoire entre 0 et 1, ce qui est ce que le unit_offset du nœud PathFollow attend.

Voici le script complet Main.gd jusqu'à présent, pour référence.

extends Node

export (PackedScene) var mob_scene


func _ready():
    randomize()


func _on_MobTimer_timeout():
    var mob = mob_scene.instance()

    var mob_spawn_location = get_node("SpawnPath/SpawnLocation")
    mob_spawn_location.unit_offset = randf()
    var player_position = $Player.transform.origin
    mob.initialize(mob_spawn_location.translation, player_position)

    add_child(mob)

Vous pouvez tester la scène en appuyant sur F6. Vous devriez voir les monstres apparaître et se déplacer en ligne droite.

image25

Pour l'instant, ils se heurtent et glissent les uns contre les autres lorsque leurs chemins se croisent. Nous aborderons ce problème dans la prochaine partie.