I. La Théorie

Je précise manette Xbox, car la structure qui est générée lors de la récupération des informations de l'état de la manette correspond surtout aux boutons de celle-ci. Je n'ai malheureusement pas pu tester avec d'autres manettes, car je ne dispose que d'une manette Xbox sans fil.

I-A. Récupérer les informations

Comme pour le clavier, il faut tout d'abord récupérer l'état du périphérique pour savoir s'il est utilisé ou pas. Nous faisons cela en utilisant la classe statique GamePad et ses méthodes. Vu que nous pouvons brancher jusqu'à quatre manettes, il faut également déterminer sur quelle manette faire nos actions. Pour la manette numéro un, nous récupérons son état comme suit :

 
Sélectionnez
GamePad.GetState(PlayerIndex.One)

La méthode statique GetState() nous permet d'accéder aux différents boutons de la manette :

Buttons
  • A
  • B
  • X
  • Y
  • Back
  • BigButton
  • Start
  • LeftShoulder
  • LeftStick
  • RightShoulder
  • RightStick
DPad
  • Left
  • Right
  • Up
  • Down
Triggers
  • Left
  • Right
ThumbSticks
  • Left
  • Right

Elle permet également de contrôler l'état des boutons et de la manette en général avec les méthodes suivantes :

  • IsConnected() (détermine si la manette est connectée) ;
  • PacketNumber() (récupère le numéro de la manette en cours) ;
  • IsButtonDown()(détermine si un bouton est enfoncé) ;
  • IsButtonUp() (détermine si un bouton est relâché).

Les constantes ThumbSticks, LeftStick et RightStick correspondent toutes aux deux sticks de la manette sauf que, la première permet de déterminer la direction et les deux autres sont plutôt utilisées pour l'appui sur les sticks vu qu'il est possible d'appuyer dessus au même titre qu'un autre bouton.

Il y a également la méthode GamePad.GetCapabilities() qui peut être utilisée pour savoir si la manette est équipée de tel bouton ou tel vibreur, etc. Ça peut être pratique par exemple de savoir si la manette est équipée d'un bouton spécial avant d'essayer de l'utiliser.

I-B. L'emplacement des boutons

Image non disponible
Image non disponible

I-C. Les sticks et les triggers

Ces deux types de boutons ont une utilisation un peu particulière. En effet, il est possible, outre le fait de savoir qu'on appuie dessus, par exemple pour les Triggers, de savoir avec quelle force on appuie sur le bouton.

I-C-1. Les sticks

Les sticks sont un peu différents du DPad, car ils utilisent un Vector2 contenant deux valeurs X et Y. Voici comment on peut déterminer les directions :

  • X(0), Y(1) = haut ;
  • X(0), Y(-1) = bas ;
  • X(-1), Y(0) = gauche ;
  • X(1), Y(0) = droite ;
  • X(0), Y(0) = centre (position neutre).

Par exemple pour aller vers la gauche, on ferait un test de cette sorte :

 
Sélectionnez
if (GamePad.GetState(PlayerIndex.One).ThumbSticks.Left.X == -1)

On peut également utiliser toutes les directions possibles du stick :

 
Sélectionnez
Position += GamePad.GetState(PlayerIndex.One).ThumbSticks.Left * new Vector2(1, -1);

Ici on multiplie par un vecteur dont sa valeur Y a été mise sur la valeur -1, car sinon il faut baisser le stick pour monter, comme dans un simulateur de vol. Si vous voulez prendre en compte une vitesse dans le déplacement des sprites, vous pouvez faire comme ceci :

 
Sélectionnez
Position += GamePad.GetState(PlayerIndex.One).ThumbSticks.Left * new Vector2(1, -1) * vitesse;

I-C-2. Les triggers

Les triggers sont des boutons encore plus spéciaux. En effet, ils n'ont pas qu'un simple état appuyé ou non, car ce sont des gâchettes. On peut donc définir le taux d'enfoncement des boutons. L'état non enfoncé/enfoncé est représenté respectivement par les valeurs 0 et 1, les valeurs intermédiaires sont représentées par un nombre flottant se situant entre les deux valeurs précédentes. Par exemple, pour déterminer si le trigger de droite est enfoncé, on fait ainsi :

 
Sélectionnez
if (GamePad.GetState(PlayerIndex.One).Triggers.Right == 1)

II. La pratique

Maintenant que vous connaissez un peu mieux la manette et comment la gérer, voyons comment l'intégrer dans notre exemple Pacman. Ouvrez le projet et allez sur la classe Player. Il faut commencer par importer un espace de noms en plus :

 
Sélectionnez
using Microsoft.Xna.Framework;

Ceci pour avoir accès à l'énumération PlayerIndex. Ensuite, dans notre méthode, nous devons changer les tests au niveau des directions (dans cet exemple, on utilise simplement le DPad) :

 
Sélectionnez
public void Move(KeyboardState state)
{
    if (state.IsKeyDown(Keys.Z)
        || GamePad.GetState(PlayerIndex.One).DPad.Up == ButtonState.Pressed)
    {
        direction = Collision.Direction.TOP;

        if (!Collision.Collided(this, world))
        {
            if (collidedDirection != Collision.Direction.TOP)
            {
                collidedDirection = Collision.Direction.NONE;
                Position.Y -= 1;
            }
        }
    }
    if (state.IsKeyDown(Keys.Q)
        || GamePad.GetState(PlayerIndex.One).DPad.Left == ButtonState.Pressed)
    {
        direction = Collision.Direction.LEFT;

        if (!Collision.Collided(this, world))
        {
            if (collidedDirection != Collision.Direction.LEFT)
            {
                collidedDirection = Collision.Direction.NONE;
                Position.X -= 1;
            }
        }
    }
    if (state.IsKeyDown(Keys.S)
        || GamePad.GetState(PlayerIndex.One).DPad.Down == ButtonState.Pressed)
    {
        direction = Collision.Direction.BOTTOM;

        if (!Collision.Collided(this, world))
        {
            if (collidedDirection != Collision.Direction.BOTTOM)
            {
                collidedDirection = Collision.Direction.NONE;
                Position.Y += 1;
            }
        }
    }
    if (state.IsKeyDown(Keys.D)
        || GamePad.GetState(PlayerIndex.One).DPad.Right == ButtonState.Pressed)
    {
        direction = Collision.Direction.RIGHT;

        if (!Collision.Collided(this, world))
        {
            if (collidedDirection != Collision.Direction.RIGHT)
            {
                collidedDirection = Collision.Direction.NONE;
                Position.X += 1;
            }
        }
    }
}

Il est tout à fait possible d'ajouter d'autres conditions comme pour utiliser le stick de gauche pour la direction droite :

 
Sélectionnez
if (state.IsKeyDown(Keys.D)
    || GamePad.GetState(PlayerIndex.One).DPad.Right == ButtonState.Pressed
    || GamePad.GetState(PlayerIndex.One).ThumbSticks.Left.X == 1)

Je vous laisse vous amuser à modifier le reste des directions pour compléter l'ajout du stick gauche.

III. Conclusion

Nous en avons fini avec la gestion de la manette, vous êtes maintenant en mesure de l'utiliser pleinement dans vos projets.

IV. Code source

Vous pouvez télécharger ci-après, le code source de la solution complète en relation avec cette seconde partie du tutoriel : http://franckh.developpez.com/tutoriels/csharp/monogame/part-III/fichiers/Pacman.zip

V. Remerciements

Un grand merci à LittleWhite pour la relecture et ses remarques lors de l'écriture de ce tutoriel et merci également à ClaudeLELOUP pour sa relecture et correction.