Interactions avec le joueur
Utiliser les périphériques
Cette première partie va vous présenter les différents périphériques compatibles avec XNA et leur utilisation. N’oubliez pas que, pour la Xbox 360, la souris et le clavier ne constituent pas des périphériques de base, vous devrez alors plutôt vous concentrer sur la gestion de la manette. En revanche, la situation est inversée si vous développez pour Windows. Toutefois, vous allez constater que les périphériques se gèrent très facilement avec XNA. Le portage de votre code d’une machine vers une autre est, de ce fait, un jeu d’enfant ! Le clavier Le clavier est un périphérique de base pour un jeu sur PC. Il est beaucoup utilisé dans les jeux de tirs ou de course. Commencez par créer un nouveau projet basé sur XNA. Importez votre classe Sprite, ajoutez une image au projet puis utilisez-la en créant un nouveau sprite. =Labat FM.book Page 67 Vendredi, 19. juin 2009 4:01 16 Développement XNA pour la XBox et le PC 68 Comme les classes qui vont être utilisées ici font partie de l’espace de noms Microsoft .Xna.Framework.Input, n’oubliez pas d’ajouter une directive using, cela simplifiera l’écriture du code. Le framework met à votre disposition l’objet Keyboard qui possède la méthode GetState() et – comble de bonheur – il dispose également de la classe KeyboardState. Une fois l’état du clavier récupéré, vous aurez accès à l’ensemble des touches pressées au moment de l’appel à la méthode et pourrez également déterminer si une touche donnée est pressée ou non. L’ensemble des touches de votre clavier (et même certaines touches auxquelles vous n’avez jamais fait attention) sont disponibles via l’énumération Keys. Rappelons qu’une énumération est un type de données constitué d’un ensemble de constantes. Voici un exemple de déclaration d’énumération : enum CouleurDesYeux { bleu, marron, vert, gris }; L’accès à une valeur de l’énumération se fait en écrivant le nom de l’énumération suivi d’un point et de la valeur voulue : CouleurDesYeux.bleu; Figure 4-1 Récupérez facilement une classe écrite précédemment Pense-bête Lorsque vous récupérerez une classe créée dans un précédent projet pour l’utiliser dans un nouveau, n’oubliez pas de modifier la déclaration de l’espace de noms pour pouvoir l’utiliser sans devoir ajouter de directive using au nouveau projet. =Labat FM.book Page 68 Vendredi, 19. juin 2009 4:01 16 Interactions avec le joueur CHAPITRE 4 69 Dans l’exemple suivant, l’utilisateur a maintenant la possibilité de quitter le jeu en appuyant sur la touche Échap de son clavier (à laquelle nous accédons via Keys.Escape) : protected override void Update(GameTime gameTime) { KeyboardState KState = Keyboard.GetState(); if (KState.IsKeyDown(Keys.Escape)) this.Exit(); base.Update(gameTime); } Vous pouvez également écrire une forme plus contractée, qui n’utilise pas de variable pour stocker l’état du clavier. Il faut alors faire intervenir l’objet Keyboard comme suit :
if (Keyboard.GetState().IsKeyDown(Keys.Escape)) this.Exit();
Voyons à présent comment déplacer notre sprite. Ajoutons une variable qui contiendra sa vitesse de déplacement. float speed = 0.1f; Le reste est très simple. Selon la touche fléchée sur laquelle il appuie, l’utilisateur déplace le sprite dans la direction qu’il souhaite, tout en modulant cette translation par le temps qui s’est écoulé depuis la dernière frame, comme vous l’avez vu au chapitre 3. protected override void Update(GameTime gameTime) { KeyboardState KState = Keyboard.GetState();
if (KState.IsKeyDown(Keys.Left)) sprite.Update(new Vector2(-1 * gameTime.ElapsedGameTime.Milliseconds * ➥speed, 0)); if (KState.IsKeyDown(Keys.Right)) sprite.Update(new Vector2(1 * gameTime.ElapsedGameTime.Milliseconds * speed, ➥0)); if (KState.IsKeyDown(Keys.Up)) sprite.Update(new Vector2(0, -1 * gameTime.ElapsedGameTime.Milliseconds * ➥speed)); if (KState.IsKeyDown(Keys.Down)) sprite.Update(new Vector2(0, 1 * gameTime.ElapsedGameTime.Milliseconds * ➥speed)); base.Update(gameTime); }
Pour traiter une combinaison de touches, utilisez la méthode GetPressedKeys() qui renvoie un tableau de Keys. L’exemple suivant affiche la liste des touches sur lesquelles le joueur a appuyé à la place du titre de la fenêtre
La souris
Il est temps à présent d’étudier la souris. Ce périphérique est particulièrement adapté aux jeux de tir et de gestion. Cette fois-ci encore, vous pouvez utiliser un objet MouseState de manière à récupérer l’état de la souris mis à disposition par l’objet Mouse. De la même manière que pour le clavier, vous pouvez grâce à cet objet connaître l’état de la souris : les boutons utilisés, la position de la souris ou encore le nombre d’interventions sur la molette. Dans un premier temps, il faut modifier votre classe Sprite. Jusqu’à présent, vous ne pouviez qu’appliquer des translations à votre Sprite or, dans l’exemple suivant, vous souhaitez pouvoir modifier directement sa position. Ajoutez donc une propriété en lecture et en écriture concernant la position de votre sprite. Vector2 position; public Vector2 Position { get { return position; } set { position = value; } } Figure 4-2 Le joueur peut maintenant déplacer son sprite où bon lui semble. =Labat FM.book Page 70 Vendredi, 19. juin 2009 4:01 16 Interactions avec le joueur CHAPITRE 4 71 À présent, vous avez tous les outils en main pour transformer votre sprite en curseur. À chaque appel de la méthode Update(), il suffit de remplacer la position du sprite par celle de la souris. protected override void Update(GameTime gameTime) { MouseState MState = Mouse.GetState(); sprite.Position = new Vector2(MState.X, MState.Y); base.Update(gameTime); } Notez que, comme pour le clavier, vous n’êtes pas obligé de stocker l’état de la souris et pouvez l’exploiter directement. sprite.Position = new Vector2(Mouse.GetState().X, Mouse.GetState().Y); En ce qui concerne les clics de la souris, vous les détectez en utilisant l’énumération ButtonState qui prend deux états : Pressed ou Released. if (MState.LeftButton == ButtonState.Pressed) this.Window.Title = « Gauche »; if (MState.MiddleButton == ButtonState.Pressed) this.Window.Title = « Milieu »;
if (MState.RightButton == ButtonState.Pressed) this.Window.Title = « Droit »;
Pour finir, vous pouvez récupérer les mouvements qu’effectue l’utilisateur avec sa molette via la propriété ScrollWheelValue. Celle-ci retourne une valeur entière qui s’incrémentera si l’utilisateur fait tourner la molette vers le haut et qui se décrémentera dans le cas contraire.
this.Window.Title = MState.ScrollWheelValue.ToString();
La manette de la Xbox 360
La manette de la Xbox 360 est le contrôleur de base que tous les joueurs de la console possèdent. Si vous développez un jeu pour la console, vous devrez donc adapter son fonctionnement à cette manette. Le fonctionnement de la manette est similaire à celui du clavier et de la souris. Vous stockez son état dans un objet de type GamePadState que vous récupérerez de l’objet GamePad. Cependant, comme il peut y avoir plusieurs manettes connectées à la console, il faut spécifier celle qui vous intéresse grâce à l’énumération PlayerIndex. GamePadState GPState = GamePad.GetState(PlayerIndex.One); Tout d’abord, vous pouvez vérifier qu’une manette est bien connectée à la console en utilisant la propriété IsConnected. GamePadState GPState = GamePad.GetState(PlayerIndex.Two); if (GPState.IsConnected) this.Window.Title = « La manette 2 n’est pas connectée à la console »; =Labat FM.book Page 71 Vendredi, 19. juin 2009 4:01 16 Développement XNA pour la XBox et le PC 72 Vous avez accès à deux méthodes classiques, l’une permettant de savoir si un bouton est pressé, l’autre s’il ne l’est pas. Le choix du bouton se fait grâce à l’énumération Buttons, laquelle vous permet également d’accéder à l’intégralité des boutons d’une manette Xbox 360. if (GPState.IsButtonDown(Buttons.A)) this.Exit(); if (GPState.IsButtonUp(Buttons.B)) this.Window.Title = « Le bouton B n’est pas pressé »; Comme d’habitude, il est tout à fait possible de s’affranchir du stockage de l’état de la manette. if (GamePad.GetState(PlayerIndex.One).IsButtonDown(Buttons.A)) this.Exit(); Vous pourriez également estimer l’état d’un bouton avec l’énumération ButtonState. Un bouton a soit l’état Pressed, soit l’état Released. if (GPState.Buttons.A == ButtonState.Pressed) this.Exit(); De la même manière, vous pourrez récupérer l’état du pad directionnel. Le cas des diagonales est géré, il peut donc y avoir deux directions pressées. if (GPState.DPad.Down == ButtonState.Pressed) Window.Title = « Vers le haut »; L’état des gâchettes analogiques gauche et droite peut aussi être récupéré. La propriété renverra un float, compris entre 0 et 1, 1 signifiant que la gâchette est complètement enfoncée. Cette variation de valeur pour être utilisée, par exemple, pour l’accélération ou la décélération dans un jeu de course. this.Window.Title = GPState.Triggers.Left.ToString(); En ce qui concerne les sticks analogiques, il est possible de récupérer un objet de type Vector2 correspondant à la distance qui les sépare de la position initiale des sticks. this.Window.Title = GPState.ThumbSticks.Left.X + » ; » + GPState.ThumbSticks.Left.Y; Enfin, la fonction SetVibration de l’objet GamePad permet de faire vibrer la manette. Elle attend comme paramètres la manette concernée, la vitesse à appliquer au moteur gauche et celle à appliquer au moteur droit. Notez également que la fonction renvoie un booléen vous indiquant si les vibrations ont eu lieu. Lorsque vous souhaitez arrêter les vibrations, il vous suffira de passer une vitesse nulle en paramètre de la fonction..