Work in progress

The content of this page was not yet updated for Godot 4.2 and may be outdated. If you know how to improve this page or you can confirm that it's up to date, feel free to open a pull request.

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

Double-click on main.tscn in the FileSystem dock to open the Main scene.

Before drawing the path, we're going to change the game resolution. Our game has a default window size of 1152x648. We're going to set it to 720x540, a nice little box.

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

Like you did in the 2D game tutorial, you're going to design a path and use a PathFollow3D node to sample random locations on it.

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 Camera3D et cochez la case Aperçu dans la vue du bas.

image3

Ajout de cylindres génériques

Let's add the placeholder meshes. Add a new Node3D as a child of the Main node and name it Cylinders. We'll use it to group the cylinders. Select Cylinders and add a child node MeshInstance3D

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

The grid may be distracting. You can toggle it by going to the View menu in the toolbar and clicking View Grid.

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

Move the cylinder so it's right outside the camera's view in the top-left corner.

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

In the Inspector, expand the Material section and assign a StandardMaterial3D to slot 0.

image13

../../_images/standard_material.webp

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.

Expand the Albedo section.

../../_images/albedo_section.webp

Set the color to something that contrasts with the background, like a bright orange.

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

Add a child node Path3D to Main node. In the toolbar, four icons appear. Click the Add Point tool, the icon with the green "+" sign.

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

To sample random positions on it, we need a PathFollow3D node. Add a PathFollow3D as a child of the Path3D. Rename the two nodes to SpawnPath and SpawnLocation, respectively. It's more descriptive of what we'll use them for.

image19

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

Faire apparaître des monstres au hasard

Right-click on the Main node and attach a new script to it.

We first export a variable to the Inspector so that we can assign mob.tscn or any other monster to it.

extends Node

@export var mob_scene: PackedScene

We want to spawn mobs at regular time intervals. To do this, we need to go back to the scene and add a timer. Before that, though, we need to assign the mob.tscn file to the mob_scene property above (otherwise it's null!)

Head back to the 3D screen and select the Main node. Drag mob.tscn from the FileSystem dock to the Mob Scene slot in the Inspector.

image20

Add a new Timer node as a child of Main. Name it 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.

With the MobTimer still selected, head to the Node dock on the right, and double-click the timeout signal.

image23

Connectez-le au noeud Main.

image24

This will take you back to the script, with a new empty _on_mob_timer_timeout() function.

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_mob_timer_timeout():
    # Create a new instance of the Mob scene.
    var mob = mob_scene.instantiate()

    # 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.progress_ratio = randf()

    var player_position = $Player.position
    mob.initialize(mob_spawn_location.position, player_position)

    # Spawn the mob by adding it to the Main scene.
    add_child(mob)

Above, randf() produces a random value between 0 and 1, which is what the PathFollow node's progress_ratio expects: 0 is the start of the path, 1 is the end of the path. The path we have set is around the camera's viewport, so any random value between 0 and 1 is a random position alongside the edges of the viewport!

Here is the complete main.gd script so far, for reference.

extends Node

@export var mob_scene: PackedScene


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

    # 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.progress_ratio = randf()

    var player_position = $Player.position
    mob.initialize(mob_spawn_location.position, player_position)

    # Spawn the mob by adding it to the Main scene.
    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.