Dans ce chapitre, nous allons voir comment générer des objets à la volée. Typiquement, c'est le cas du gorille qui lance toutes les 10 secondes un tonneau vers notre héros, des caisses de munitions que l'on retrouve à intervalle régulier dans l'arène, ou des lemmings qui arrivent par groupe de 20 dans notre grotte, etc. En somme, il n'y avait rien, puis soudainement, quelque chose est là.
Le fait de créer un objet ou un personnage en direct et en cours de jeu est ce que l'on appelle, dans le jargon du jeu vidéo, du spawning. Le spawning est donc le fait de typiquement faire apparaître un élément de jeu comme s'il venait d'être créé. Ces éléments existent donc bien dans l'univers du jeu et ont été créés par les concepteurs, mais ils n'apparaissent à l'écran et n’interagissent avec l’environnement du jeu qu'à partir du moment où la logique du jeu le nécessite. L'avantage des méthodes de spawning, c'est que l'on peut faire apparaître tout le temps de nouvelles copies d'objets, indéfiniment ou tant que c'est nécessaire.
Dans un jeu de survie par exemple, dont le but est de rester en vie le plus longtemps possible devant une attaque de zombies, peu importe combien de zombies tuera le héros, il y aura toujours de nouveaux zombies qui apparaîtront à l'horizon. En pratique, le créateur de jeu aura donc défini plusieurs modèles de zombies possibles (avec des apparences, des capacités et des modes de déplacement différents). Puis la logique de jeu ira pêcher dans cette bibliothèque d’ennemis pour créer cette invasion constante de morts-vivants.
Ce qu'il faut comprendre ici, c'est que nous avons donc un modèle, un objet de référence, et le spawning est la technique qui va permettre de créer des copies de ce modèle aux bons endroits du jeu. Toutes les copies, qu'on peut comprendre comme des clones, ou qu'on appelle aussi des instances, ont leur vie propre à partir du moment où elles sont créées. Ces instances, bien qu'elles partagent les mêmes propriétés lors de leur création, évoluent de façon indépendantes une fois dans le jeu.
Pour ce chapitre, nous utiliserons un exemple très simple d'un canon qui tire des boulets lorsque le joueur appuie sur la barre d'espace. Le nombre de boulets est infini. Le joueur peut en tirer autant qu'il veut.
Préparons notre scène de manière à être plus à l'aise au moment de la génération. Créons les objets de base et organisons les de manière à y accéder facilement sans qu'ils gênent le jeu. De plus, il est impossible pour le BGE d'ajouter à la volée des objets présents dans un calque actif, il faudra en tenir compte.
Nous allons attacher à notre objet canon la logique qui permet de tirer des boulets de canon lorsque le joueur appuie sur la barre d'espace.
1. Sélectionnons le canon et ajoutons un sensor de type keyboard que l'on configure pour s'activer lorsque l'on appuie sur la barre d'espace.
2. Relions-le à un controller de type And que l'on relie ensuite à un actuator de type Edit Object.
3. Par défaut, cet actuatorest configuré pour ajouter des objets à la scène. C'est le mode Add Object. Nous devons ensuite lui spécifier le nom de l'objet qu'il doit ajouter à la scène. En cliquant dans la case après Object:, nous retrouvons facilement notre Boulet, nommé précédemment. Nous rappelons que cet objet doit être sur un calque invisible pour que cela fonctionne.
Une instance sera toujours générée aux coordonnées d'origine de l'objet qui la crée. Dans ce cas-ci, nos boulets seront générés au milieu de notre canon.
4. Si besoin, replaçons l'origine pour que les boulet partent bien de l'emplacement souhaité (pour cela, nous pouvons positionner correctement le boulet dans le canon, y caler le curseur 3D avec Maj + s > Cursor to selected, puis sur le canon, utiliser Set Origin > Origin to 3D cursor de la boîte à outil.
5. Nous pouvons donner une vitesse de départ à nos instances en modifiant les paramètres Linear Velocity. Dans notre exemple, nous allons appliquer une vitesse de 8.00 en y selon les coordonnées locales du canon en cochant le bouton L en bout de ligne. Pour bien choisir les axes, passez la vue 3D en mode local également.
Nous avons choisi la coordonnée locale du canon parce que nous pourrions ensuite placer ce canon sur une tourelle qui tourne sur elle-même ou faire tenir ce canon par un personnage se déplaçant. Nous nous assurons ainsi que les boulets sortiront toujours par le bon côté du canon et iront dans la direction vers laquelle il pointe.
<lien vers blend>
Toujours dans cet actuator, nous voyons l'option Time. Il s'agit de la durée de vie que nous allons donner à chaque instance que nous allons générer. Au delà de cette durée, l'instance est détruite. Cela peut servir dans plusieurs cas comme simplement celui de limiter dans la durée la présence de cette instance dans le jeu. Mais, au delà des règles du jeu, limiter cette présence peut devenir réellement important si l'on compte, par exemple, générer un très grand nombre d'instances. Parce que si aucun autre mécanisme ne vient les détruire, elles resteront présentes dans le moteur de jeu tant qu'on n'est pas sorti du jeu ou qu'on a pas changé de scène. Cela peut donc devenir rapidement très lourd pour le moteur physique de gérer autant d'objets. Donner une durée de vie limite permet ainsi de conserver un nombre d'instances raisonnable par rapport aux performances de la machine.
Par défaut, l'actuator a une valeur de Time égale à 0. Cela veut dire que l'instance générée aura par défaut une durée de vie infinie.
Le spawningpeut bien évidemment se faire en Python. Gardons notresensor Keyboarddéfini précédemment mais relions le plutôt à un controller de type Python pointant vers un script nommé tirer_un_boulet.py. Dans ce script nous écrirons.
from bge import logic
# Recuperer la scene
scene = logic.getCurrentScene()
# Recuperer le canon
canon = scene.objects["Canon"]
# Recuperer le boulet sur son calque invisible
boulet = scene.objectsInactive["Boulet"]
# Creer une instance de boulet
instance = scene.addObject(boulet, canon, 0)
# Donner une vitesse à l'instance
instance.localLinearVelocity.y = 8.0
Après import du module logic
et récupération de la scène active, nous créons deux variables qui représentent nos objets "canon" et "boulet" présents dans la scène. Remarquons qu'on accède différemment à des objets se trouvant dans un calque non visible : scene.objectsInactive["Boulet"]
qu'à des objets présents dans un calque visible : scene.objects["Canon"]
. Dans les deux manières, nous utilisons le nom le l'objet précédemment défini.
Nous créons ensuite des instances de notre objet Boulet qui apparaîtront aux coordonnées de l'origine de notre objet canon de cette façon :
instance = scene.addObject(boulet, canon, 0)
Le troisième paramètre, ici mis à 0, est la durée de vie de l'objet. Observez aussi que cette méthode addObject()
renvoie l'objet nouvellement créé. Nous conservons ceci dans une variable nommée instance afin de pouvoir lui appliquer des fonctions supplémentaires, comme dans ce cas-ci lui ajouter une vitesse.
instance.localLinearVelocity.y = 8.0
L'avantage d'utiliser Python ici par rapport aux briques logiques, c'est que l'on pourrait dynamiquement changer la durée de vie de nos instances, générer des instances différentes pêchées aléatoirement dans une liste d'objets cachés, ou encore la faire apparaître à des endroits différents de la scène en utilisant comme point de génération des objets vides (empty) placés à des endroits clés de notre scène de jeu.
Il y a une erreur de communication avec le serveur Booktype. Nous ne savons pas actuellement où est le problème.
Vous devriez rafraîchir la page.