Tutoriel XNA 1 : Afficher une image

tuto1gdv

Dans ce premier tutoriel sur XNA, nous allons voir comment est construit et exécuté un programme XNA dans les grandes lignes. Ensuite nous allons voir comment charger une image, modifier ses propriétés et l’afficher.

Ce tutoriel s’adresse avant tout aux débutants, c’est pour cela que vous trouverez des explications de base sur le fonctionnement de Visual Studio et de XNA.

Logiciels nécessaires pour suivre ce tutoriel :

  • Visual Studio 2010 ou Visual C# Express 2010
  • Les Frameworks .NET 4.0 et XNA 4.0

S’il vous manque un ou plusieurs de ces pré-requis, vous pouvez vous les procurer gratuitement sur le site de Microsoft dédié à XNA.

Première étape : Création du projet

Lancer Visual Studio 2010 !

Ensuite, si vous avez bien installé le Framework XNA 4.0, vous devriez voir dans le menu de création de projet (CTRL + SHIFT + N) une template « Windows Game (4.0) » comme sur l’image ci dessous :

Création d'un template Windows Game sous XNA 4.0

Sélectionnez ce template et créez votre projet.

Un template est un projet pré-configuré (contenant donc l’architecture de base de l’application pour que celle ci s’initialise correctement).

Deuxième Étape : Fonctionnement de base

1. Organisation des fichiers

Tout d’abord, nous allons voir comment sont organisés les fichiers de notre template lorsqu’il vient d’être crée. (Pour ceux qui découvrent Visual Studio, pour les autres, vous pouvez passer directement à l’étape numéro 2)

Sur la partie droite de Visual Studio, vous pouvez voir un encart qui ressemble à ceci:

Organisation des fichiers d'une solution sous Visual Studio 2010

Le terme « Solution » désigne l’ensemble des projets crées pour réaliser votre application. En effet, sous Visual Studio, vos réalisations sont « découpées » en projets distincts.

Pour notre exemple, la Solution "WindowsGame1" contient deux projets :

  • WindowsGame1, tout le code de notre application
  • WindowsGame1Content, toutes les ressources qui seront utilisées par notre application (images, vidéos, sons…)

Il y a deux fichiers .cs dans notre projet WindowsGame1, le fichier Program.cs est le fichier de base de notre projet qui contient le fonction main (celle qui va être exécutée en premier lorsque nous allons lancer le .exe en quelque sorte). Nous n’avons pas besoin d’y toucher pour réaliser notre projet XNA.

Le seul fichier qui va nous intéresser est le fichier Game1.cs, il contiendra toute la logique de notre application.

2. Le fichier Game.cs

Le fichier Game1.cs contient donc toute la logique de notre code. C’est à dire que toutes les étapes nécessaires au fonctionnement de notre application vont se trouver dans ce fichier.

Nous allons maintenant l’ouvrir dans Visual Studio. (Double clic sur le fichier dans l’explorateur de solution)

Il contient diverses méthodes et objets qui vont chacun avoir un rôle précis : charger les ressources, mettre à jour les données du jeu, dessiner à l’écran. Nous allons maintenant décrire le fonctionnement de chaque méthode et objet.

Au début de votre classe, deux objets sont définis:

GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;

L’objet graphics est du type GraphicsDeviceManager. Cet objet va servir à configurer et à utiliser notre carte graphique. (Résolution, mode plein écran, etc…)

L’objet spriteBatch est du type SpriteBatch. Il va nous servir à afficher plusieurs sprites à l’écran. (Un sprite est une image 2D)

 

La première méthode à analyser est le constructeur de la classe :

public Game1()
{
    graphics = new GraphicsDeviceManager(this);
    Content.RootDirectory = "Content";
}

L’objet graphics est instancié au moment où notre programme va se lancer, ce qui parait logique puisqu’il s’agit je le rappelle de l’objet qui va nous servir à communiquer avec la carte graphique.

A la 4ème ligne du code ci dessus, on définit le répertoire racine des ressources qui vont être utilisées pour notre projet. Ainsi si nous mettons comme répertoire par défaut le dossier Content, toutes les ressources que vous allez charger dans votre projet auront ce préfixe : si je charge le fichier « images/bonhomme1.png », XNA comprendra alors : « Content/images/bonhomme1.png ». Par défaut, Visual Studio a configuré le projet pour placer les ressources dans le dossier « Content ». Nul besoin de changer donc ces deux lignes.

Content est le gestionnaire de contenu de l’application. Il va servir à charger toutes les ressources utiles au programme.

La seconde méthode est la méthode Initialize() :

protected override void Initialize()
{
    // TODO: Add your initialization logic here
    base.Initialize();
}

La méthode Initialize() va servir à initialiser votre programme. Vous pouvez placer les instanciations des objets que vous allez peut être utiliser dans cette méthode.

La troisième méthode est LoadContent()

protected override void LoadContent()
{
    // Create a new SpriteBatch, which can be used to draw textures.
    spriteBatch = new SpriteBatch(GraphicsDevice);
    // TODO: use this.Content to load your game content here
}

Cette méthode sert à charger toutes les ressources qui vont être utilisées dans notre projet (images, vidéos, sons, etc.). C’est ici que nous allons charger notre image, dans la troisième étape.

L’objet spriteBatch est instancié ici.

La méthode suivante est UnloadContent()

protected override void UnloadContent()
{
    // TODO: Unload any non ContentManager content here
}

Cette méthode n’est pas très utilisée, car elle sert uniquement à décharger de la mémoire les ressources que vous n’avez pas chargé via le gestionnaire de contenu. Comme nous allons charger notre image via le gestionnaire de contenu, cette fonction restera dans cet état.

Les deux méthodes les plus importantes sont les suivantes : la méthode Update() et la méthode Draw()

protected override void Update(GameTime gameTime)
{
    // Allows the game to exit
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
        this.Exit();
    // TODO: Add your update logic here
    base.Update(gameTime);
}

Update est exécutée en boucle, dès qu’elle est terminée elle recommence. Elle est comme un espèce de « while(1==1) ». Le if présent dans cette méthode va tester si le bouton back (select) de la manette est appuyé, et dans ce cas précis l’application se terminera. Comme nous n’utilisons pas de manette, ce if est inutile. Pour fermer le programme, nous allons cliquer sur la petite croix en haut à droite ^^. Cela aura le même effet qu’un this.Exit().

La méthode Update() reçoit en paramètre un objet de type GameTime. Cet objet va nous permettre d’obtenir une représentation du temps au moment de l’exécution de la méthode Update().

La dernière instruction de la méthode, base.Update(gameTime), va relancer la méthode Update en passant par la classe mère.

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);
    // TODO: Add your drawing code here
    base.Draw(gameTime);
}

Cette méthode va nous servir à dessiner à l’écran. Comme Update(), elle reçoit en paramètre une représentation du temps.

GraphicsDevice.Clear(Color.CornflowerBlue); va dessiner un fond à notre application (Si vous lancez l’application en appuyant sur la touche F5 par exemple, vous pourrez voir une fenêtre bleue : c’est le Color.CornflowerBlue) mais va également « nettoyer » notre écran en supprimant tout ce qui a été dessiné auparavant. Si vous dessinez une image avant l’appel de cette méthode, vous ne verrez rien.

base.Draw(gameTime), tout comme Update(), va relancer la méthode Draw() en passant par la classe mère.

3. Tester l’application

Pour lancer l’application et vérifier que tout fonctionne bien, appuyez sur la touche F5 (Executer le programme).

Vous devez obtenir une fenêtre comme celle ci-dessous:

Application de base XNA

Troisième Étape : Afficher notre image

1. Inclure le fichier au projet

Nous allons tout d’abord afficher un ciel. Un joli ciel se trouve à cette adresse : http://media.ryzom.com/?query=sky&start=0&asset=4ff21cef9faf79b7ce8a023624b0f96d (image tirée du jeu libre Ryzom).

Téléchargez le ciel sur votre disque dur. Ensuite rendez vous dans le dossier où vous avez téléchargé le fichier image et renommez le fichier en ciel.png.

Pour importer votre fichier, il faut que vous le glissiez dans le répertoire content de votre projet comme sur l’image ci dessous : (Cliquez pour agrandir)

Ajout d'une ressource à un projet XNA

Une fois ceci fait, vous devriez avoir un explorateur de solution qui ressemble à cela :

Le fichier ciel.png est bien ajouté

Notre projet contient maintenant notre fichier ciel.png.

 

 

2. Charger le fichier

Maintenant que notre image est disponible pour notre application, nous allons devoir la charger en mémoire avant de la dessiner.

XNA contient une classe spéciale pour charger et utiliser les images dans l’application : l’objet Texture2D.

Déclarons donc notre objet afin qu’il soit accessible dans toutes les méthodes de notre classe Game1. (Fichier Game1.cs)

GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D maTexture;

Ensuite, dans la méthode Load(), nous allons charger le fichier ciel.png et le mettre dans notre Texture2D.

protected override void LoadContent()
{
    // Create a new SpriteBatch, which can be used to draw textures.
    spriteBatch = new SpriteBatch(GraphicsDevice);
    // TODO: use this.Content to load your game content here
    this.maTexture = Content.Load<Texture2D>("ciel");
}

Nous avons chargé le fichier image dans maTexture avec la ligne suivante:

this.maTexture = Content.Load<Texture2D>("ciel");

Ici, nous utilisons la méthode Load() du gestionnaire de contenu Content pour charger notre ressource de type Texture2D (Nous le précisons entre les <>). En paramètre pour la méthode Load, nous donnons le nom du fichier sans l’extension. C’est très important, le gestionnaire de contenu charge toujours les fichiers sans l’extension. (Il se débrouille tout seul pour la trouver)

Ainsi pas besoin de réaliser un traitement particulier pour charger chaque type d’image (jpeg, mpg, bmp, png, etc…), Content de débrouille tout seul.

 

3. Dessiner notre image

Maintenant que nous avons chargé notre image en mémoire il ne reste plus qu’à la dessiner : direction la méthode Draw()

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);
    // TODO: Add your drawing code here
    spriteBatch.Begin();
    spriteBatch.Draw(this.maTexture, GraphicsDevice.Viewport.TitleSafeArea, Color.White);
    spriteBatch.End();
    base.Draw(gameTime);
}

Ici, nous avons ajouté 3 lignes :

spriteBatch.Begin();
spriteBatch.Draw(this.maTexture, GraphicsDevice.Viewport.TitleSafeArea, Color.White);
spriteBatch.End();

La première demande à notre SpriteBatch de se préparer à dessiner. Cette méthode est nécessaire, sans elle vous ne pourrez pas écrire les deux autres lignes.

SpriteBatch.Draw va appliquer la texture (image) passée en paramètre et effectuer des opérations dessus pour préparer un rendu. SpriteBatch.Draw() prend 3 paramètres : la texture, le rectangle, et la couleur. La texture doit être de type Texture2D, le rectangle de type Rectangle et la couleur de type… Color.

Pour ce qui est de la texture, nous l’avons déjà chargée dans une variable de type Texture2D, donc pas de problème pour la fournir à spriteBatch.Draw().

Pour la couleur, cela va définir les couleurs à afficher. (Color.White représente une couleur en RBG, ici rouge 255, bleu 255 et vert 255. Ainsi toutes les couleurs seront affichées. Si vous mettez Color.Black par exemple, cela donnera rouge 0, bleu 0, vert 0 : aucune couleur ne sera affichée.)

Pour le rectangle, c’est très simple : un rectangle est définit par sa position en x, en y, sa largeur et sa longueur.

Voici un schéma représentant l’axe X et Y dans une application XNA :

Axe X et Y dans une application XNA

Ainsi, plus Y est grand plus on se rapproche du bas de la fenêtre, plus X est grand plus on se rapproche de la droite de la fenêtre.

L’angle en haut à gauche se trouve à l’indice X:0 Y:0.

Nous voulons dessiner le ciel sur la totalité de l’application. Si la résolution de mon application est de 800* 480, vais dessiner ma texture dans un rectangle de largeur 800 et de hauteur 480, à l’indice X: 0 et Y: 0.

Un rectangle représentant toute la surface de l’application est disponible avec l’objet qui nous permet de communiquer avec la carte graphique.

GraphicsDevice.Viewport.TitleSafeArea

Ceci équivaut à créer un nouveau rectangle (pour une résolution d’application de 800 par 480):

 

Rectangle monRectangle = new Rectangle(0, 0, 800, 480);

Maintenant, en appuyant sur F5 nous devons obtenir ceci :

Notre image s'affiche correctement sur la surface de notre application

 

 

Dernière Étape : Faire bouger notre image

Maintenant que nous affichons correctement notre image, nous allons revenir sur les rectangles pour la faire bouger.

Nous devons donc définir notre propre rectangle qui va servir à placer notre image sur notre surface (au lieu d’utiliser comme précédemment le rectangle représentant la surface).

Nous déclarons le rectangle dans notre classe :

GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D maTexture;
Rectangle monRectangle;

Ensuite, nous allons lui donner sa valeur par défaut dans la méthode Initialize()

protected override void Initialize()
{
    // TODO: Add your initialization logic here
    base.Initialize();
    this.monRectangle = new Rectangle(0, 0, graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height);
}

graphics.GraphicsDevice.Viewport.Width permet d’obtenir la largeur de la fenêtre.

graphics.GraphicsDevice.Viewport.Height permet d’obtenir la hauteur de la fenêtre.

A présent, notre objet rectangle couvre la totalité de la surface de la fenêtre. Nous pouvons donc à présent mettre à jour notre méthode Draw() pour utiliser notre rectangle personnalisé plutôt que celui donné par l’objet GraphicsDevice (et qui n’est pas modifiable).

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);
    // TODO: Add your drawing code here
    spriteBatch.Begin();
    spriteBatch.Draw(this.maTexture, this.monRectangle, Color.White);
    spriteBatch.End();
    base.Draw(gameTime);
}

A présent, pour modifier la position de notre image sur la surface, il nous suffit de modifier la position X et Y de la variable « monRectangle » directement dans la méthode Update().

protected override void Update(GameTime gameTime)
{
    // Allows the game to exit
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
        this.Exit();
    // TODO: Add your update logic here
    this.monRectangle.X++;
    base.Update(gameTime);
}

Nous avons rajouté l’instruction suivante :

this.monRectangle.X++;

Ceci a pour effet d’incrémenter (augmenter de 1) la valeur de la propriété X de l’objet monRectangle de type Rectangle (En gros, le déplacer sur la droite), et ce à chaque fois que la méthode Update() sera appelée.

Si vous lancez votre application, vous devriez maintenant voir votre image se déplacer sur la droite.

Vous savez maintenant :

  • Créer un projet
  • Inclure des ressources à votre projet
  • Charger des ressources en mémoire
  • Afficher des images
  • Déplacer des images

Dans le prochain tutoriel, nous verrons comment réaliser des contrôles au clavier (Pour pouvoir bouger les images nous même !).

One thought on “Tutoriel XNA 1 : Afficher une image

Laisser un commentaire

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

*

Vous pouvez utiliser ces balises et attributs HTML : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>