Sites


Blender pour le jeu video

Des personnages au bon comportement

Dans le Blender Game Engine, il est apparu que les contrôles de physique et d'animation classiques n'étaient pas efficaces pour des entités adaptées à certains comportements courants, ceux des personnages de jeux et ceux des séquences interactives. Des options spécifiques sont prévues à cet effet dans le BGE.

La physique des personnages

Comme nous l'avons vu dans le chapitre précédent, la physique plus ordinaire des objets statiques et dynamiques ne convient en général pas pour les personnages-joueurs. Les objets statiques sont insensibles aux forces et les objets dynamiques ont aussi leurs problèmes.

  • Ils peuvent être bloqués par de minuscules obstacles (par exemple un accroc dans le sol).
  • Ils peuvent parfois traverser les parois, y compris le sol, s'ils ont une vitesse élevée.
  • Les objets de type Rigid Body roulent et basculent facilement, ce qu'on peut vouloir faire pour un personnage, mais qu'il est plus facile de contrôler avec une animation.

Pour ces raisons, un type de physique dédié aux personnages a été spécialement prévu dans le moteur physique, le type Character. Ce type est semblable à Dynamic, car il n'a pas de rotation mais il résout les problèmes cités précédemment et permet un contrôle fin des mouvements du personnage joueur et des PNJ via des options spécifiques.

Step Height : hauteur de marche maximale que peut franchir le joueur dans son mouvement. Cela permet entre autres de grimper un escalier.

Attention, la capacité à franchir un obstacle dépend également de la vitesse du personnage face à cet obstacle, plus la vitesse est lente et plus le franchissement sera difficile.

Jump Force: Littéralement force de saut. Le nom de ce paramètre est mal choisi, car il s'agit en fait d'une vitesse verticale (dont l'unité est le mètre par seconde) appliquée au joueur quand l'action Jump est exécutée via l'Actuator spécialisé (voir juste après). Une fois propulsé, le joueur retombe sous l'effet de la gravité. 

Fall Speed Max: Ce paramètre règle la vitesse maximale que le joueur peut atteindre s'il tombe en chute libre, ce qui permet de simuler le frottement de l'air.

Usage de cette physique dans les briques logiques

Une brique logique spécifique est prévue pour déplacer un joueur de type Character, l'actuator Motion>Character Motion (Mouvement > Mouvement de personnage).

Il faut utiliser cet actuator de préférence en Motion>Simple Motion (mouvement simple) si nous voulons bénéficier de la physique Character. Les options sont identiques, excepté l'option Jumpqui applique l'impulsion spécifiée dans Jump Force (évoqué précédemment). Le Simple Motionfonctionne avec le type Character mais ne permet pas de franchir les obstacles.

Et attention, le Servo Control ne fonctionne pas avec le type Character.

Scrypthon !

La brique logique Motion ne permet qu'un contrôle assez grossier du personnage : la vitesse est définie en incrémentant la position et est appliquée instantanément (il n'y a pas de phase d'accélération ni de décélération). Pour un contrôle fin, il faut accéder par Python à l'objet et utiliser les API spécifiques du type Character.

from bge import logic, constraints 
# Recuper le controleur et son objet cont = logic.getCurrentController()
own = cont.owner

# Recupere le Character Physique
c = constraints.getCharacter(own)

Après import des modules nécessaires, nous récupérons le contrôleur courant (la brique logique qui a lancé le script). Ce contrôleur possède des sensors et des actuators reliés à lui mais surtout un owner (littéralement le propriétaire) : c'est l'objet qui possède la brique logique. Nous récupérons le owner de notre contrôleur dans une variable own car c'est lui qui contient tout notre objet, et donc aussi sa physique.

À la dernière ligne, nous récupérons l'expression python correspondante à la physique character de notre objet types.KX_CharacterWrapper, et nous avons ainsi accès à toutes ses méthodes et attributs.

  • onGround : un booléen indiquant si le personnage est actuellement sur le sol.
  • gravity : la valeur de la gravité utilisée par le personnage (par défaut : 29.4).
  • maxJumps : le nombre maximum de sauts autorisés au personnage avant de devoir retoucher le sol (par défaut : 1 ; 2 pour un double sauts, etc.).
  • jumpCount : le nombre de sauts en cours.
  • walkDirection : la vitesse et la direction des déplacements du personnage en coordonnées globales [x, y, z]. On ne doit pas utiliser les autres méthodes de déplacement des objets classiques (localPosition, worldPosition, applyMovement, etc.).
  • jump() : fait sauter le personnage.

Et voici un code complet de déplacement de personnage, avec une classe créée pour l'occasion :

from bge import logic, events, types, constraints 
from mathutils import Vector

def keyDown(kevt):
 return logic.keyboard.events[kevt] == logic.KX_INPUT_ACTIVE
 def keyHit(kevt):
 return logic.keyboard.events[kevt] == logic.KX_INPUT_JUST_ACTIVATED

class Panda(types.KX_GameObject):
 def __init__(self, own):
# facteur vitesse du personnage
 self.speed = .1
# facteur sqrt(2) pour les diagonales
self.factor = 0.70710678
self.KX_Char = constraints.getCharacter(self)
def main(self):
self.move()
def move(self):
# vecteur y = 0, 1 ou -1
 y = keyDown(events.UPARROWKEY) - keyDown(events.DOWNARROWKEY)
# vecteur x = 0, 1 ou -1
x = keyDown(events.RIGHTARROWKEY) - keyDown(events.LEFTARROWKEY) # diagonal
 if x and y:
self.KX_Char.walkDirection = [x*self.speed*self.factor, y*self.speed*self.factor, 0.0]
# Nord, Sud, Est, Ouest
elif x or y:
self.KX_Char.walkDirection = [x*self.speed, y*self.speed, 0.0]
else:
self.KX_Char.walkDirection = [0.0, 0.0, 0.0]
# vecteur representant la direction de deplacement du personnage
vec = Vector((x, y, 0.0))
if x != 0 or y != 0:
# on aligne le personnnage au vecteur
self.alignAxisToVect(vec, 0)

def main(cont):
own = cont.owner
if not "init" in own:
 own["init"] = True
Panda(own)
else:
own.main()
  1. Nous commençons, comme toujours, par importer nos modules.
  2. Nous définissons deux fonctions qui nous seront utiles pour simplifier le code par la suite. keyHit(events.AKEY) renverra True si A vient juste d'être pressée (KX_INPUT_JUST_ACTIVATED). De même, keyDown(events.AKEY) renverra True si la A est enfoncée (KX_INPUT_ACTIVE).
  3. Nous déclarons une classe Panda qui hérite de types.KX_GameObject (l'objet élémentaire du BGE).
  4. Dans le __init__  nous déclarons les attributs (nous récupèrons un KX_CharacterWrapper et nous le gardons dans le self.KX_Char).
  5. Nous définissons la méthode main, qui contiendra toutes les autres méthodes appelées (ici il n'y en a qu'une, mais nous pourrions en imaginer d'autres comme attack, anim, heal, etc.).
  6. Nous définissons la méthode move. Ici elle récupère les inputs (touches fléchées), déplace et oriente le joueur dans le bon vecteur correspondant. Arrive en dernier la fonction main, qui sera appelée par une brique logique.
  7. Nous récupérons le owner (KX_GameObject). Si celui-ci n'a pas été initialisé, nous le remplaçons par Panda(own), sinon le owner a maintenant été changé et on peut appeler sa méthode main.

Vous trouverez un exemple de fichier .blend de personnage animé à la fin du chapitre Animer des personnages dans le Game Engine de cette même section.

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.