Les aspects d’un jeu 2D avec XNA
10 December 2009 par Nicolas RocheNous allons étudier dans cet article toutes les étapes pour faire un jeu en 2D avec XNA. Pour cela nous allons voir le menu, le réseau, l'affichage de sprites, mais aussi la logique interne du jeu.
Explications générales
Pour tout ce que nous voulons faire, Microsoft nous simplifie la tâche. En effet, nous allons prendre un template qui gère par défaut le menu et l'initialisation du réseau. Il ne nous restera qu'à savoir l'utiliser, et à ajouter la logique interne du jeu.
Voici le lien : Cliquer ici
Si vous voulez faire un jeu qui ne nécessite pas de réseau, prenez ce projet.
Lorsque vous lancez le projet en mode Debug, il vous est demandé de vous identifier. Si vous avez un compte Xbox LIVE (payant), tant mieux, sinon, vous devrez vous limiter à créer un compte local en utilisant System Link (Vous ne pourrez alors que jouer en réseau local entre ordinateurs).
En regardant l'arborescence du projet, on peut voir 3 dossiers : Networking, ScreenManager et Screens. Nous allons d'abord étudier la façon dont le menu fonctionne (Screens, ScreenManager), puis nous passerons au réseau (Networking).
Le Menu
Avant de regarder le code, il est important que vous vous demandiez quelle sera l'architecture de votre menu. Voici un exemple simple :
- Menu principal -> Jouer, Options, Quitter
- Jouer-> Facile, Moyen, Difficile -> Lancer la partie
- Options -> Volume, Controles
- Quitter -> quitter le jeu
Pour chaque menu, il vous faudra créer une classe héritant de MenuScreen. Les textes sélectionnables sont appelés MenuEntry.
Voici l'exemple de menu principal du projet (dans le dossier Screens) :
class MainMenuScreen : MenuScreen { // Constructeur public MainMenuScreen() : base(Resources.MainMenu) { // Création des MenuEntry(ies) MenuEntry singlePlayerMenuEntry = new MenuEntry(Resources.SinglePlayer); MenuEntry liveMenuEntry = new MenuEntry(Resources.PlayerMatch); MenuEntry systemLinkMenuEntry = new MenuEntry(Resources.SystemLink); MenuEntry exitMenuEntry = new MenuEntry(Resources.Exit); // On met en place les pointeurs sur fonction (fonctions appelees //lorsque l'on sélectionne le MenuEntry correspondant) singlePlayerMenuEntry.Selected += SinglePlayerMenuEntrySelected; liveMenuEntry.Selected += LiveMenuEntrySelected; systemLinkMenuEntry.Selected += SystemLinkMenuEntrySelected; exitMenuEntry.Selected += OnCancel; // On ajoute les MenuEntry MenuEntries.Add(singlePlayerMenuEntry); MenuEntries.Add(liveMenuEntry); MenuEntries.Add(systemLinkMenuEntry); MenuEntries.Add(exitMenuEntry); } // On ajoute les fonctions de gestion de sélection void SinglePlayerMenuEntrySelected(object sender, PlayerIndexEventArgs e) { LoadingScreen.Load(ScreenManager, true, e.PlayerIndex, new GameplayScreen(null, this.ScreenManager)); } void LiveMenuEntrySelected(object sender, PlayerIndexEventArgs e) { CreateOrFindSession(NetworkSessionType.PlayerMatch, e.PlayerIndex); } void SystemLinkMenuEntrySelected(object sender, PlayerIndexEventArgs e) { CreateOrFindSession(NetworkSessionType.SystemLink, e.PlayerIndex); } void CreateOrFindSession(NetworkSessionType sessionType, PlayerIndex playerIndex) { // Logique de gestion des sessions ici } protected override void OnCancel(PlayerIndex playerIndex) { MessageBoxScreen confirmExitMessageBox = new MessageBoxScreen(Resources.ConfirmExitSample); confirmExitMessageBox.Accepted += ConfirmExitMessageBoxAccepted; ScreenManager.AddScreen(confirmExitMessageBox, playerIndex); } void ConfirmExitMessageBoxAccepted(object sender, PlayerIndexEventArgs e) { ScreenManager.Game.Exit(); }
Dans cet exemple, chaque MenuEntry est géré dans une fonction qui lui est propre, mais vous pouvez aussi tout gérer en une seule fonction :
// entryIndex est l'index du MenuEntry dans la liste des menuEntries // playerIndex est l'index du joueur qui a sélectionné ce MenuEntry protected override void OnSelectEntry(int entryIndex, PlayerIndex playerIndex) { base.OnSelectEntry(entryIndex, playerIndex); }
Le Réseau
Les topologies
Vous devez savoir qu'il y a plusieurs façons de communiquer en réseau. On les appelle les topologies. Deux d'entre elles sont beaucoup utilisées :
- Peer to peer
Chaque machine envoie ses données à toutes les autres machines du réseau. Cette topologie a la particularité d'être très gourmande en bande passante.
- Client / Serveur
Une machine appelée serveur sert de point central sur le réseau. Il envoie les données à toutes les autres machines, et elles lui envoient leurs données, et à lui seul.
L'envoie d'information
Sachez que la bande passante n'est pas illimitée, et il convient de n'envoyer que les informations vraiment utiles, et de préférence compressées. XNA propose ici l'utilisation de PacketWriter et de PacketReader.
Nous allons maintenant nous occuper de la classe GameplayScreen, dont voici le constructeur :
// networkSession est la session de la partie en cours // screenManager est l'objet gérant les divers écrans public GameplayScreen(NetworkSession networkSession, ScreenManager screenManager) { this.networkSession = networkSession; }
Plusieurs attributs sont interressants :
networkSession.AllGamers // tous les joueurs networkSession.LocalGamers // les joueurs sur cette machine networkSession.RemoteGamers // les joueurs qui sont sur les autres machines
Pour l'envoie de données :
// envoyer des données provenant du joueur local LocalGamers[i] vers le joueur RemoteGamers[j] PacketWriter pw = new PacketWriter(); pw.Write("test"); networkSession.LocalGamers[i].SendData(pw, SendDataOptions.Reliable, networkSession.RemoteGamers[j]);
Pour la réception de données :
// recevoir des données du NetworkGamer "sender" destinée a LocalGamers[i] PacketReader pr = new PacketReader(); networkSession.LocalGamers[i].ReceiveData(pr, out sender); Console.WriteLine("Packet Received: " + pr.BaseStream.ToString());
Maintenant que vous savez envoyer des informations, il ne vous reste plus qu'à définir la façon dont vous allez les envoyer en suivant la logique de votre topologie de réseau.
Exemple
Pour prendre un exemple simple, si vous faites un réseau entre 2 ordinateurs, à chaque fois que vous faites une action, envoyer l'information comme cela :
networkSession.LocalGamers[0].SendData(pw, SendDataOptions.Reliable, networkSession.RemoteGamers[0]);
Et surveillez en permanence l'arrivée de paquets :
Gamer sender = RemoteGamers[0]; networkSession.LocalGamers[0].ReceiveData(pr, out sender);
L'affichage
Passons à l'affichage. Chargeons dans le Content du projet une image (de préférence une .png car ce format gère la transparence) :
Voici un exemple d'image :
Dans GamePlayScreen, ajoutez l'attribut :
Texture2D myTexture;et dans content :
// charge l'image myPicture.png qui se situe dans le Content du projet. myTexture = content.Load<Texture2D>("myPicture");
L'affichage de cette image se fait très facilement grâce à un outil appelé SpriteBatch.
SpriteBatch spritebatch = new SpriteBatch(device); // device est votre GraphicsDevice
Après, ajoutez dans votre méthode Draw :
// Affichage d'images (x, y: position ; w, h: largeur et hauteur de l'image) spriteBatch.Begin(); spriteBatch.Draw(myTexture1, new Rectangle(x, y, w, h), Color.White); spriteBatch.Draw(myTexture2, new Vector2(x, y), Color.White); spriteBatch.End();
Bien entendu vous pouvez mettre toutes vos textures à la suite.
Pour ma balle, voici ce que ca donne :
Si vous ne spécifiez pas la hauteur et la largeur, l'image prendra sa taille d'origine. Color.White est la teinte que vous voulez donner à l'image, ici aucune.
La logique interne
Vous aurez à gérer beaucoup de choses dans la classe GamePlayScreen. Pour ne pas vous emmêler les pinceaux, créer des classes qui gèrent elles-mêmes chaque partie. Par exemple :
- L'envoi et la réception de paquets, et le parsing des informations
- La collision
- Les règles du jeu (conditions de début/fin, ajouts de points...)
- l'IA (ou intelligence articificielle)
- L'affichage (Interface, joueurs, autres éléments...)
Conclusion
Vous disposez maintenant de tous les outils pour créer un jeu en 2D avec XNA.
Je vous invite à regarder les offres de Microsoft sur les comptes LIVE. En effet il est possible de partager son propre jeu sur internet, et même d'être rémunéré !




