Développement XNA pour la XBox et le PC 234

Développement XNA pour la XBox et le PC 234

Le mode multijoueur

Jouer à plusieurs sur le même écran Il existe deux types de jeux vidéo qui offrent une expérience multijoueur sur le même écran : ceux où les joueurs apparaissent les uns à côté des autres dans la même vue et ceux où l’écran est partagé en plusieurs parties. Dans cette première partie, nous allons voir comment créer un jeu multijoueur utilisant le principe du partage d’écran. Un jeu en écran partagé, aussi appelé jeu en écran « splitté » (de l’anglais to split, qui signifie séparer), est un jeu où l’écran est divisé en plusieurs zones, généralement de même taille, chacune étant réservée à un joueur. =Labat FM.book Page 231 Vendredi, 19. juin 2009 4:01 16 Développement XNA pour la XBox et le PC 232 Avec XNA, la division de l’écran en plusieurs parties se fera grâce à des objets de type Viewport. Il est possible de fixer la taille de ces objets, ainsi que leur point d’origine, chacun d’entre eux disposera de son propre repère cartésien. Du mode solo au multijoueur : la gestion des caméras Au chapitre 3, nous avons vu ce que sont les jeux dits tile-based et nous les avons employés pour l’application de l’algorithme A* au chapitre 9. Dans ce chapitre, nous irons encore plus loin avec ce type de jeu et nous allons créer un système de caméra, le but étant de ne pas afficher toute la carte à l’écran, mais d’obtenir un effet de scrolling (en français, défilement). Nous avons déjà abordé le scrolling au chapitre 6 : il s’agit de faire défiler l’écran sur une carte en fonction des déplacements du joueur. Créer un jeu solo avec effet de scrolling Commencez par créer un nouveau projet et récupérez, des précédents projets, les fichiers IKeyboardService.cs, KeyboardService.cs, ServiceHelper.cs, Map.cs, Sprite.cs et Tile.cs. Tout d’abord, modifiez l’interface IKeyboardService et ajoutez-lui la signature d’une méthode KeyHasBeenPressed. Le but de cette méthode est de détecter si le joueur a pressé une touche, puis l’a relâchée. Ainsi, le personnage ne se déplacera d’une case qu’à chaque fois que le joueur pressera une touche. Modifiez ensuite la classe KeyboardService de manière à ce qu’elle prenne en compte cette nouvelle méthode. interface IKeyboardService { bool IsKeyDown(Keys key); bool KeyHasBeenPressed(Keys key); } Il n’y a aucune difficulté ici, d’autant plus que vous avez déjà fait la même chose dans un précédent chapitre pour le bouton gauche de la souris. class KeyboardService : GameComponent, IKeyboardService { KeyboardState lastKBState; KeyboardState KBState; public KeyboardService(Game game) : base(game) { ServiceHelper.Add(this); } public bool IsKeyDown(Keys key) { return KBState.IsKeyDown(key); } =Labat FM.book   public bool KeyHasBeenPressed(Keys key) { return lastKBState.IsKeyDown(key) && KBState.IsKeyUp(key); } public override void Update(GameTime gameTime) { lastKBState = KBState; KBState = Keyboard.GetState(); base.Update(gameTime); } } Intéressez-vous maintenant au système de caméra. La figure 11-1 représente votre objectif. Vous avez une carte (celle représentée ici est tirée du chapitre 9), et le carré aux bords noirs autour du joueur représente son champ de vision, c’est-à-dire la caméra. Sur cet exemple, le joueur voit l’environnement qui l’entoure sur une distance de deux cases, la caméra est donc un carré de 5 ¥ 5 cases. La position de la caméra sur la carte sera déterminée par un couple de coordonnées (x, y). Vous pouvez donc utiliser un objet de type Rectangle qui dispose de toutes ces caractéristiques. Le sprite représentant le joueur doit toujours être placé au milieu de l’écran. Lorsque le joueur appuie sur les touches de déplacement, ce n’est pas la position à l’écran du sprite qui est modifiée, mais sa position sur la carte et les coordonnées de l’origine de la caméra. Modifiez maintenant la méthode Draw() de la classe Map afin qu’elle ne dessine que les cases qui sont dans le champ de vision de la caméra. Parcourez le tableau tileList en bouclant sur les dimensions de l’objet Rectangle, puis positionnez les sprites à l’écran en fonction de leur position dans le rectangle de la caméra et appelez leur méthode Draw().

Adapter les caméras au multijoueur

À présent, nous allons modifier le jeu de manière à ce qu’il puisse accueillir deux joueurs en simultané sur le même écran. Dans le code source de cet ouvrage, le projet correspondant est nommé Chapitre 11_2. La première chose à faire est de vous occuper des objets Viewport. Créez-en deux, un pour chaque joueur. Ici, ils seront appelés viewportA pour la portion supérieure de l’écran et viewportB pour la portion inférieure de l’écran. Spécifiez les dimensions des deux vues en définissant leurs propriétés Width et Height. Dans le programme exemple lié à ce chapitre, la largeur d’une vue est la même que la largeur de la fenêtre de jeu, et sa hauteur correspond à la moitié de celle de la fenêtre de jeu. Pensez donc à augmenter la hauteur de la fenêtre de jeu si vous voulez que les deux vues soient des carrés. Enfin, décalez la deuxième vue en hauteur grâce à sa propriété Y. Les deux vues seront donc alignées verticalement ; pour les aligner horizontalement, vous modifierez simplement la propriété X. viewportA.Width = graphics.PreferredBackBufferWidth; viewportA.Height = graphics.PreferredBackBufferHeight / 2; Figure 11-2 Votre jeu en mode solo =Labat FM.book Page 237 Vendredi, 19. juin 2009 4:01 16 Développement XNA pour la XBox et le PC 238 viewportB.Y = graphics.PreferredBackBufferHeight / 2; viewportB.Width = graphics.PreferredBackBufferWidth; viewportB.Height = graphics.PreferredBackBufferHeight / 2; Déclarez un nouvel objet Tile qui représentera le deuxième joueur, ainsi qu’un nouvel objet Rectangle pour la caméra du deuxième joueur et faites-les bouger lorsque des touches du clavier seront utilisées (ici les touches Z-Q-S-D). Enfin, vous n’avez plus qu’à dessiner dans les deux vues. Pour vous placer sur une vue, modifiez la propriété Viewport de l’objet GraphicsDevice. Le dessin des sprites se fait de manière classique. La classe principale du jeu multijoueur public class   : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; Map map; Tile herosA; Tile herosB; Rectangle cameraA; Rectangle cameraB; Viewport viewportA; Viewport viewportB; public Chapitre11_2() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = « Content »; ServiceHelper.Game = this; Components.Add(new KeyboardService(this)); graphics.PreferredBackBufferWidth = 160; graphics.PreferredBackBufferHeight = 320; } protected override void Initialize() { Xbox 360 Dans l’exemple de jeu qui vous est proposé ici, les deux joueurs utilisent le clavier. Vous pouvez modifier le projet pour qu’il soit utilisable avec les manettes de la Xbox 360, vous différencierez les entrées utilisateur grâce à l’énumération PlayerIndex. Sur Xbox 360, les manettes peuvent être complétées par des claviers. L’état de ces claviers se récupère de la manière suivante : Keyboard.GetState(PlayerIndex.Two); =Labat; cameraA = new Rectangle(0, 0, 5, 5); cameraB = new Rectangle(1, 1, 5, 5); herosA = new Tile(cameraA.X + 2, cameraA.Y + 2, 4); herosA.Position = new Vector2(64, 64); herosB = new Tile(cameraB.X + 2, cameraB.Y + 2, 4); herosB.Position = new Vector2(64, 64); viewportA.Width = graphics.PreferredBackBufferWidth; viewportA.Height = graphics.PreferredBackBufferHeight / 2; viewportB.Y = graphics.PreferredBackBufferHeight / 2; viewportB.Width = graphics.PreferredBackBufferWidth; viewportB.Height = graphics.PreferredBackBufferHeight / 2; base.Initialize(); } protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice); foreach (Tile tile in map.TileList) { tile.LoadContent(Content, « tile »); } herosA.LoadContent(Content, « tile »); herosB.LoadContent(Content, « tile »); } protected override void Update(GameTime gameTime) { if (ServiceHelper.Get().KeyHasBeenPressed(Keys.Up)) { if (map.TileList[herosA.Y – 1, herosA.X].Type >= 0) { cameraA.Y -= 1; =Labat FM.book Page 239 Vendredi, 19. juin 2009 4:01 16 Développement XNA pour la XBox et le PC 240 herosA.Y -= 1; } } if (ServiceHelper.Get().KeyHasBeenPressed(Keys.Right)) { if (map.TileList[herosA.Y, herosA.X + 1].Type >= 0) { cameraA.X += 1; herosA.X += 1; } } if (ServiceHelper.Get().KeyHasBeenPressed(Keys.Down)) { if (map.TileList[herosA.Y + 1, herosA.X].Type >= 0) { cameraA.Y += 1; herosA.Y += 1; } } if (ServiceHelper.Get().KeyHasBeenPressed(Keys.Left)) { if (map.TileList[herosA.Y, herosA.X – 1].Type >= 0) { cameraA.X -= 1; herosA.X -= 1; } } if (ServiceHelper.Get().KeyHasBeenPressed(Keys.Z)) { if (map.TileList[herosB.Y – 1, herosB.X].Type >= 0) { cameraB.Y -= 1; herosB.Y -= 1; } } if (ServiceHelper.Get().KeyHasBeenPressed(Keys.D)) { if (map.TileList[herosB.Y, herosB.X + 1].Type >= 0) { cameraB.X += 1; herosB.X += 1; } } if (ServiceHelper.Get().KeyHasBeenPressed(Keys.S)) { if (map.TileList[herosB.Y + 1, herosB.X].Type >= 0) { cameraB.Y += 1; herosB.Y += 1; } } if (ServiceHelper.Get().KeyHasBeenPressed(Keys.Q)) { =Labat FM.book Page 240 Vendredi, 19. juin 2009 4:01 16 Le mode multijoueur CHAPITRE 11 241 if (map.TileList[herosB.Y, herosB.X – 1].Type >= 0) { cameraB.X -= 1; herosB.X -= 1; } } base.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.Black); GraphicsDevice.Viewport = viewportA; spriteBatch.Begin(); map.Draw(spriteBatch, cameraA); herosA.Draw(spriteBatch); spriteBatch.End(); GraphicsDevice.Viewport = viewportB; spriteBatch.Begin(); map.Draw(spriteBatch, cameraB); herosB.Draw(spriteBatch); spriteBatch.End(); base.Draw(gameTime); } }

Formation et coursTélécharger le document complet

Télécharger aussi :

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *