I. Introduction▲
Avant de commencer à programmer pour la XBox, il est important d'utiliser les bons outils. Voici les outils qui seront rapidement nécessaires :
- Visual C# Express Edition ;
- XNA Game Studio Express ;
- DirectX Software Development Kit.
Pour le dernier élément de la liste, son installation n'est pas obligatoire, mais il permet d'utiliser certains outils dédiés pour DirectX comme nous le montrons plus loin dans cet article. Par contre, il n'y a pas de lien direct, vous allez donc devoir utiliser votre moteur de recherche préféré pour obtenir la dernière version.
Pour l'ordre d'installation, commencez par Visual C# Express et ensuite installez le module XNA.
Pour l'instant, une version française n'existe pas encore, donc les menus, et l'aide, seront en anglais. Il faut le prendre comme un exercice de langue en même temps que l'apprentissage de l'informatique !
Dernière remarque, pour toutes les installations, la suite de ce tutoriel suppose que vous avez effectué une installation complète des composants. En principe, cela installera donc aussi l'aide MSDN.
II. Premier lancement▲
Une fois que tout est installé correctement vous allez pouvoir lancer le lien XNA Game Studio Express qui se trouve dans le menu Démarrer. Celui-ci lance en fait Visual C# Express.
Vous pouvez maintenant créer un nouveau projet et obtenir une fenêtre proposant Windows Game (XNA). Dans le nom du projet, vous pouvez mettre le titre du jeu ou comme le montre l'exemple, simplement Essai.
Ceci ouvre une nouvelle fenêtre, dans lequel vous avez les composants à gauche (un seul composant graphique pour le moment) et à droite les fichiers liés au projet, à droite. Avant toute chose, il faut penser à sauvegarder le projet : allez dans le menu et choisissez l'option Save all (pensez à cliquer sur la création de répertoire pour le projet).
III. Le code▲
En cliquant sur la partie gauche de la fenêtre, vous allez avoir l'option View Code. Ceci vous permet de voir le code de base d'un programme XNA. Normalement vous devriez avoir ceci :
Pour faciliter la lecture et voir tout le code, voici une copie du code :
using
System;
using
System.Collections.Generic;
using
Microsoft.Xna.Framework;
using
Microsoft.Xna.Framework.Audio;
using
Microsoft.Xna.Framework.Components;
using
Microsoft.Xna.Framework.Graphics;
using
Microsoft.Xna.Framework.Input;
using
Microsoft.Xna.Framework.Storage;
namespace
Essai
{
///
<
summary
>
///
This is the main type for your game
///
<
/summary
>
partial class
Game1 : Microsoft.Xna.Framework.Game
{
public
Game1()
{
InitializeComponent();
}
protected
override
void
Update()
{
// The time since Update was called last
float
elapsed =
(float
)ElapsedTime.TotalSeconds;
// TODO: Add your game logic here
// Let the GameComponents update
UpdateComponents();
}
protected
override
void
Draw()
{
// Make sure we have a valid device
if
(!
graphics.EnsureDevice())
return
;
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
graphics.GraphicsDevice.BeginScene();
// TODO: Add your drawing code here
// Let the GameComponents draw
DrawComponents();
graphics.GraphicsDevice.EndScene();
graphics.GraphicsDevice.Present();
}
}
}
Sans faire un cours sur les différentes parties de ce code, le début commence avec les traditionnelles inclusions nécessaires pour le programme. Ensuite vient la déclaration d'un espace de nom et enfin la classe pour le jeu.
Le constructeur initialise les composants pour le jeu. Et cette classe contient deux autres fonctions membres :
- Update : fonction qui permet de mettre à jour les informations concernant le jeu, gérer la logique de jeu, l'intelligence artificielle, le réseau, le son, l'entrée utilisateur, les collisions entre les objets ;
- Draw : fonction qui permet de gérer le rendu du programme, c'est ici que vous mettrez ce qui doit être dessiner, comment et où ;
Comme vous le voyez, la fonction Update commence par donner le temps écoulé depuis la dernière mise à jour. Cette information est très importante dans la programmation d'un jeu. Elle permet de calculer la distance que doit parcourir un objet, décider de l'image à dessiner pour l'animation d'un objet…
IV. Création et ajout d'une balle▲
IV-A. Création▲
Si vous compilez les codes (F6 pour compiler et Ctrl-F5 pour lancer le programme), vous devriez obtenir une fenêtre vide. Bien sûr, nous voulons faire plus ! Le premier endroit pour chercher des informations se trouve dans l'aide associée avec l'EDI. En appuyant sur F1, vous allez obtenir quelque chose de similaire à ceci :
Dans la partie de gauche, vous avez une partie XNA, la suite (y compris le code) de ce tutoriel puise ses informations de cette aide très bien faite. Pour avoir plus de détails, je vous invite à étudier cette aide (bien qu'elle soit en anglais, c'est abordable). Je ne peux que vous encourager d'y faire un tour !
En suivant donc cette première aide de la MSDN, nous allons ajouter une texture de balle pour le jeu et la faire rebondir sur les bords de la fenêtre. Il va donc falloir commencer par créer l'image de balle.
En utilisant votre programme de dessin préféré, vous pouvez créer une image qui ressemblera à ceci :
C'est une image blanche ! Bien sûr, nous voulons voir une balle, mais nous voulons que, lors du rendu, seul un rond apparaisse. Ceci se fait facilement en ajoutant un canal supplémentaire nommé Alpha. En effet, toute image possède des pixels de 3 couleurs (rouge, vert et bleu) et on ajoute généralement un dernier canal alpha pour la transparence. Puisque nous voulons que la balle soit opaque, mais que le reste soit transparent, il suffira de dessiner un cercle noir sur fond noir :
En utilisant un outil de la SDK DirectX nommé Texture Tool, nous allons créer une texture DirectX. Cet outil possède une simple fenêtre et lorsque nous voulons créer une texture (option New Texture), nous obtenons cette sous-fenêtre :
La seule chose à changer ici est la taille de l'image si vous souhaitez une image plus petite. Mais vous pouvez aussi le laisser tel quel en appuyant directement sur OK.
Enfin, il vous suffit d'ajouter l'image de la balle en utilisant Open Onto this Surface, et en utilisant Open Onto Alpha Channel Of This Surface pour l'image du canal alpha.
Remarquons que Texture Tool redimensionne les images pour qu'elles soient entièrement dans la texture. Bien sûr, il vaut mieux avoir la même taille que les images créées précédemment, mais cela n'est pas nécessaire.
Ceci terminé, nous pouvons sauvegarder la texture (l'extension du fichier sera .dds) dans le répertoire du projet, la suite de l'article supposera que le fichier de la texture est balle.dds.
IV-B. Ajout▲
Pour ajouter un fichier image à un projet, il suffit de demander d'inclure un objet existant au projet, comme le montre l'image suivant :
Cela permettra lors de la création du programme de copier le fichier de la balle en même temps que le programme. Pour dire à Visual C# Express de copier la texture lors de la compilation du projet, il faut aller dans les propriétés de la texture :
Ceci ouvre une fenêtre dans laquelle on peut spécifier la copie du fichier lors de la compilation (mettre l'option à Copy always) :
On termine donc la partie sur la création d'une texture et son ajout dans le projet. Nous allons maintenant modifier le code pour qu'il prenne en compte l'objet et qu'il le dessine à l'écran.
V. Retour sur le code▲
Remarque : encore une fois, le code présenté ici est une copie (à part pour les commentaires) du code trouvé dans l'aide MSDN. Je ne fais que le présenter d'une autre manière et en français !
V-A. Les nouveaux membres et fonctions▲
Pour terminer ce premier petit programme, nous devons tout d'abord compléter la classe principale du programme. En effet, nous avons besoin d'un objet pour contenir la texture de la balle, deux champs pour sa position et un objet qui s'occupera du rendu de la balle.
Il faut donc ajouter dans la classe ceci :
//Ceci contient la texture de la balle
Texture2D m_textureBalle;
//Position de la balle
int
m_balleX =
0
;
int
m_balleY =
0
;
//La vitesse de la balle
int
m_vx =
3
;
int
m_vy =
3
;
//L'objet qui dessinera la balle
SpriteBatch m_spriteBatch;
La seule chose différente de ce qu'on a l'habitude de voir est l'objet de type SpriteBatch. Cette classe permet de gérer le rendu des objets de votre jeu. Sinon nous avons un objet pour contenir la texture de la balle et quatre entiers pour la position et la vitesse courante de la balle.
Nous devons maintenant charger la texture en mémoire et ceci peut se faire au démarrage du programme. Comme beaucoup d'API graphiques, il est possible qu'à un moment de la vie du programme, il faille recharger cette texture (par exemple, lors d'un changement de résolution). Nous allons donc créer une fonction LoadRessources qui sera appelée lors de la création du programme et lorsque le composant graphique doit être réinitialisé. Ceci se fait en écrivant deux fonctions supplémentaires : OnStarting et GraphicsDevice_DeviceReset.
protected
override
void
OnStarting()
{
base.OnStarting();
graphics.GraphicsDevice.DeviceReset +=
new
EventHandler(GraphicsDevice_DeviceReset);
LoadResources();
}
void
GraphicsDevice_DeviceReset(object sender, EventArgs e)
{
LoadResources();
}
void
LoadResources()
{
myTexture =
Texture2D.FromFile(graphics.GraphicsDevice, "balle.dds"
);
spriteBatch =
new
SpriteBatch(graphics.GraphicsDevice);
}
La fonction OnStarting démarre la base du programme et met en place la gestion d'une réinitialisation du composant graphique en demandant qu'on appelle la fonction GraphicsDevice_DeviceReset, puis la fonction LoadRessources.
La fonction GraphicsDevice_DeviceReset demande simplement le chargement des ressources graphique. Enfin, la fonction LoadRessources charge la texture balle.dds. Ensuite on crée une instance de la classe SpriteBatch qui je le rappelle gérera le rendu de la balle.
La dernière nouvelle fonction est appelée BougeBalle. Elle permet de déplacer la balle et de vérifier si on sort de la fenêtre. Si c'est le cas, on la repositionne et on inverse sa direction. Son code ressemble donc à :
void
BougeBalle()
{
//Bouger la balle par rapport a la vitesse
m_balleX +=
m_vx;
m_balleY +=
m_vy;
int
MaxX =
Window.ClientWidth -
m_textureBalle.Width;
int
MinX =
0
;
int
MaxY =
Window.ClientHeight -
m_textureBalle.Height;
int
MinY =
0
;
//On regarde si on sort de la fenetre
if
(m_balleX >
MaxX)
{
m_vx *=
-
1
;
m_balleX =
MaxX;
}
else
if
(m_balleX <
MinX)
{
m_vx *=
-
1
;
m_balleX =
MinX;
}
if
(m_balleY >
MaxY)
{
m_vy *=
-
1
;
m_balleY =
MaxY;
}
else
if
(m_balleY <
MinY)
{
m_vy *=
-
1
;
m_balleY =
MinY;
}
}
Si on regarde ce code attentivement, on remarque que l'objet Window permet d'avoir la taille de la fenêtre et l'objet m_textureBalle permet d'avoir les dimensions de l'objet. Avec la position et la vitesse de la balle, la fonction est donc capable de mettre à jour la position de l'objet et de vérifier si la balle sort de la fenêtre.
V-B. Modifications des autres fonctions▲
Cette petite partie présente les modifications de code pour gérer et afficher la balle dans la fenêtre. La fonction Update appelle la fonction BougeBalle pour mettre à jour la position de la balle.
protected
override
void
Update()
{
// The time since Update was called last
float
elapsed =
(float
)ElapsedTime.TotalSeconds;
//Bouger la balle
BougeBalle();
// Let the GameComponents update
UpdateComponents();
}
La fonction Draw a un peu plus de modifications. Nous avons déjà dit que c'est l'objet m_spriteBatch qui gère l'affichage des objets. Comme pour le rendu de beaucoup d'API graphiques, nous englobons le code de rendu par une fonction Begin et une fonction End.
La fonction Begin de la classe SpriteBatch prend le style de rendu que nous voulons faire. Dans le cas présent, nous voulons avoir un affichage qui tient en compte le canal Alpha de la texture. Ceci implique donc que nous allons passer SpriteBlendMode.AlphaBlend à la fonction Begin.
Ensuite, pour dessiner la balle, nous utilisons la fonction Draw de l'objet m_spriteBatch en lui passant la texture à dessiner, un rectangle contenant la position de la balle, une taille et une couleur qui sera multiplié sur chaque pixel. En mettant Red, nous allons donc obtenir une image dont tous les pixels sont multipliés par une couleur rouge.
protected
override
void
Draw()
{
if
(!
graphics.EnsureDevice())
{
return
;
}
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
graphics.GraphicsDevice.BeginScene();
//Dessiner la balle
m_spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
m_spriteBatch.Draw(m_textureBalle,
new
Rectangle(m_balleX, m_balleY, m_textureBalle.Width, m_textureBalle.Height),
Color.Red);
m_spriteBatch.End();
// Let the GameComponents draw
DrawComponents();
graphics.GraphicsDevice.EndScene();
graphics.GraphicsDevice.Present();
}
Enfin, voici une image du petit programme que nous venons de créer :
VI. Conclusion▲
Voilà, l'introduction de la programmation XNA est terminée ! Vous avez en principe tous les outils pour créer des jeux qui pourront être portés vers la XBox. Bien sûr, il faudra faire plus qu'une balle qui rebondit sur les bords de l'écran, mais c'est un début.
L'aide MSDN est complète et présente de nombreux exemples pour savoir comment créer divers éléments d'un jeu !
Jc
Liens
VII. Téléchargements▲
Voici le code source pour ce premier tutoriel : (10 Ko).
Enfin, sur la page http://jeux.developpez.tv/tutoriel/xna, vous pourrez trouver une vidéo montrant le déroulement de cet article et qui constitue une présentation visuelle de Visual C#/XNA et de l'aide MSDN.
Si vous avez des suggestions, remarques, critiques, si vous avez remarqué une erreur, ou bien si vous souhaitez des informations complémentaires, n'hésitez pas à me contacter !
VIII. Remerciements▲
Je remercie matrix788 pour sa relecture et ses remarques.