Sites


Blender pour le jeu video

Collisions

Un espace 3D virtuel est constitué de points, lignes et surfaces qui n'ont pas d’existence physique. Des surfaces peuvent donc s'interpénétrer sans autre conséquence, et notre univers 3D peut sembler être, sur ce point, passablement irréel, fantomatique.

Pour permettre l'interaction entre les éléments du jeu, le moteur de physique intégré de Blender (Bullet*) est utilisé. Il permet de prendre en compte les volumes et surfaces des objets pour déclencher des événements lorsque ceux-ci entrent en collision (virtuelle), en s'interpénétrant.

La détection de collision se fait par le sensor Collision, très simple d'utilisation. Par défaut, toute collision le déclenchera, mais l'option property permet de filtrer quels objets déclencheront le sensor en se limitant seulement à ceux possédant une propriété du nom choisi (le type de la propriété n'a pas d'importance). Le bouton M/P permet de filtrer les objets collisionnant selon un matériau donné plutôt qu'une propriété. Si un objet possède plusieurs matériaux, il suffit alors que le matériau choisi apparaisse au moins une fois sur l'objet pour qu'il réagisse.

Il est aussi possible de gérer les objets qui collisionnent avec des groupes de collision tels que décrits dans la section Comportement des objets et personnages au chapitre intitulé Comportement des objets de notre monde.

Nous en profiterons pour introduire un nouvel actuator, Edit Object. Il permet d'effectuer différentes actions sur l'objet : le détruire, ajouter un nouvel objet, etc. et sera extrêmement utile dans les jeux.

Améliorons notre jeu en ajoutant une fonctionnalité très simple : le joueur doit ramasser des bonus, que nous représenterons par des cylindres aplatis jaunes. Nous allons devoir détecter la collision entre le bonus et le joueur, et faire disparaître le bonus.

Scene de préparation pour la collision dans le Blender Game Engine

Sélectionnons notre objet joueur et dans le Logic Editor, cliquons sur Add Game Property. Nous détaillerons son utilisation dans le chapitre Compter et afficher le score. Pour le moment elle sert simplement d'étiquette pour l'actuator Collision : préoccupons-nous donc simplement de lui donner le nom player (joueur).

Dans le Logic Editor ajoutons cette configuration de Logic Brick sur nos objets bonus :

  1. un sensor de type Collision, avec dans le champ Property, la valeur qui identifie le joueur (player) ;
  2. lié à un controller And ;
  3. lié à un actuator de type Edit Object, réglé via sa liste déroulante pour être en mode End Object.

Logic Brick necessaire pour créer une collision sur le bonus

Pour aller vite, faisons l'opération sur un objet, sélectionnons tous les bonus et utilisons le menu Object > Game > Copy Logic Bricks pour recopier les briques existantes sur tous les objets sélectionnés.

En appuyant sur Pet en déplaçant le joueur sur le bonus, nous constatons que ça ne fonctionne pas. C'est normal, la détection des collisions étant une fonction coûteuse en ressource, elle n'est pas activée par défaut, par souci d'optimisation. Cette option est à activer uniquement quand cela est nécessaire.

Sélectionnons notre objet joueur et rendons-nous dans l'onglet Physicset son panneauPhysics. Assurez-vous de bien avoir sélectionné le mode Blender Game sinon le panneau Physics n'affichera pas les mêmes options que dans la copie d'écran ci-dessous. Dans Physics Type, sélectionnons Character, qui convient très bien pour un personnage. Cette fois, en appuyant sur P, le joueur est capable de ramasser le bonus !
On remarquera également quelque chose d'important, le joueur est à présent soumis à la gravité (il tombe) et aux collisions avec les objets statiques (il ne passe pas à travers le sol et les murs de la salle).

A l'inverse des murs, les bonus ne doivent pas empêcher le joueur d'avancer. Néanmoins, ils doivent être capables de détecter les collisions (pour déclencher une action). Il existe un type de physique dédié à ce cas, le type Sensor.

Sélectionnons donc un objets bonus et dans le panneau Physics, et dans Physics Type, choisissons Sensor.
Utilisons le menu Object > Game > Copy Physics Properties pour recopier ce Physics Type sur tous les autres objets bonus.

À présent, le bonus disparaît bien lorsque le joueur le touche ! C'est un bon début, mais un tel bonus n'est pas franchement motivant. Dans le chapitre suivant, nous verrons comment récompenser le joueur en ajoutant des points à son score.

Collisions fonctionnelles dans notre scène

Scrypthon !

Il est parfois plus utile et plus facile de mettre en place du Python pour remplacer un controller ou un actuator. Il peut par contre être intéressant d'avoir un sensor simple en brique logique auquel on ajoutera un controller Python qui fera des traitements plus fins que ce qu'aurait pu faire un sensor seul .

Voici un exemple de code qui fonctionne ainsi. Pour le tester, vous pouvez créer un controller Python que vous pourrez accrocher au sensor Collision de l'objet bonus.

from bge import logic

# Recupere le controller
cont = logic.getCurrentController()

# Recupere le premier sensor attache au controller
sensor = cont.sensors[0]
 
# Si le Player se trouve dans la liste des objets entrés en collision
if "Player" in [obj.name for obj in sensor.hitObjectList]:
    # Destruction de l'objet bonus
    cont.owner.endObject()

Nous commençons par importer le module logic du Blender Game Engine. Nous récupérons ensuite le controller Python courant que nous plaçons dans une variable cont. Tous les controllers permettent de récupérer la liste des sensors qui leurs sont rattachés grâce à leur attribut sensors.

sensor = cont.sensors[0]

Par cette commande, nous récupérons le premier sensor, dans notre cas le seul des sensors, celui qui détecte les collisions.

La condition qui suit est un peu plus technique au niveau Python.

if "Player" in [obj.name for obj in sensor.hitObjectList]:
    co.owner.endObject()

Nous parcourons la totalité des éléments de sensor.hitObjectList. Cette liste contient tous les éléments qui sont en collisions avec l'objet auquel est rattaché le sensor. À partir de cette liste, nous construisons une liste ne contenant que les noms des objets (les noms étant stockés dans l'attribut name des objets). Nous testons ensuite grâce au mot-clé in si un des objets a pour nom Player. Si c'est le cas nous effectuerons alors le code qui se trouve dans le if, à savoir, lancer la fonction endObject() de l'objet auquel est attaché le sensor Collison. C'est-à-dire que nous allons le faire disparaître.

L'utilisation des Lists Comprehension (compréhension de liste) est à la fois courante et recommandée en Python. Si vous n'avez pas l'habitude de les utiliser, voici une version plus explicite.
# Nous créons une variable temporaire
del_object = False

# Nous bouclons sur la liste des objets en collision
for obj in sensor.hitObjectList:
    # Si un objet porte le nom Player
    if obj.name == "Player" :
        # La variable temporaire est changée
        del_object = True
        # Et on peut quitter la boucle
        break

# Si la variable temporaire a été changée
if del_object:
    # Destruction de l'objet bonus
    cont.owner.endObject()

Gestion des listes, les spécificités de Blender

Un bon nombre des listes d'objets, que va vous fournir Blender, ne sont pas des listes classiques Python. Ce sont des listes, mais légèrement modifiées par Blender. On les appelle des CListValue. On peut, avec une CListValue, récupérer un objet par son index (liste_test[0]) mais aussi en utilisant son nom(list_test["Player"]). En utilisant cette spécificité Blender, notre code d'exemple devient beaucoup plus court.

from bge import logic 

cont = logic.getCurrentController()

sensor = cont.sensors[0]

if "Player" in sensor.hitObjectList:
     cont.owner.endObject()

 

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.