Archives de
Catégorie : XNA / MonoGame

Des tutoriels sur la technologie XNA et MonoGame pour Windows et Linux.

Compiler ses Shaders et ressources en XNB pour MonoGame avec Pipeline

Compiler ses Shaders et ressources en XNB pour MonoGame avec Pipeline

Le Framework XNA proposait en son temps une génération du contenu à la volée lors de la compilation. C’était relativement pratique, mais aussi un peu ennoyant parfois car il n’était pas possible d’y mettre n’importe quoi. La principale difficulté quand on passe sur MonoGame est de construire ses assets au format XNB pour pouvoir les exploiter ensuite. Jusqu’à maintenant il fallait avoir recourt à plusieurs méthodes plus ou moins contraignantes pour les générer, de la VM Windows à l’installation du vieux SDK de Windows Phone, il y avait de quoi faire..

L’équipe du projet MonoGame travail depuis un moment sur plusieurs outils qui permettent de générer ces fichiers, ça a commencé par des outils en ligne de commande comme 2MGFX (génération de shaders), puis MGCB (Génération de XNB pour les images, fonts, modèles, etc…), puis ça a été au tour du plugin pour MonoDevelop (j’en ai parlé ici). Aujourd’hui un nouvel outil est arrivé, il est graphique et indépendant de tout IDE : Pipeline !

Lire la suite Lire la suite

Utilisation du plugin MonoGame pour MonoDevelop 4.x sous Linux

Utilisation du plugin MonoGame pour MonoDevelop 4.x sous Linux

Un des atouts du Framework XNA est la génération du contenu sous forme de fichier xnb. Concrètement lorsque vous compilez un projet XNA sous Windows avec Visual Studio, vos ressources (images, son, musiques, modèles, etc…) sont transformés dans un autre format que seule une application XNA peut décrypter. Ces fichiers xnb contiennent des informations sur la ressource qu’ils embarquent, pour une image cela va être le format de compression, pour un modèle ça sera le type d’effet à utiliser. Le projet MonoGame a mis en place dans un premier temps une méthode pour exploiter les xnb mais il était jusqu’alors impossible d’en créer. Pour ça il fallait obligatoirement passer par une session Windows avec Visual Studio, créer un projet bidon et compiler son contenu.

Lire la suite Lire la suite

Restez à jour avec Mono, MonoDevelop et MonoGame sous Linux

Restez à jour avec Mono, MonoDevelop et MonoGame sous Linux

Utiliser un environnement de développement .Net/Mono à jour sous Windows ou Mac OSX est relativement facile, sous Windows on a directement le Framework .Net proposé par Microsoft et sous Mac OSX il y a des paquets officiels pour Mono. Cependant sous Linux c’est différent.. Effectivement le projet Mono est très mal vue pour des raisons plus ou moins discutables et un des plus gros reproche que l’on puisse faire à certaines distributions populaires est de ne pas proposer de paquet à jour. Par exemple sur la dernière version beta d’Ubuntu, Mono est encore en version 2.10 et MonoDevelop en 3.x. Il faut aussi voir que certains utilisateurs ne mettent pas à jour leurs système (Le cas des LTS par exemple) et les ancienne distributions là aussi ne se mettent pas à jour. Pour MonoDevelop c’est la même chose, sous Windows et Mac OSX, il y a des paquets officiels, mais pas sous Linux où il faut se contenter des paquets par défaut qui sont encore une fois peut à jour (voir totalement vieux…). Heureusement certaines distributions telles que Mageia, Arch Linux ou Gentoo proposent des versions à jour via les canaux de mise à jour stable ou testing.

Lire la suite Lire la suite

Détecter des collisions par pixel

Détecter des collisions par pixel

La série des tutoriels sur XNA et MonoGame continue et cette fois-ci nous allons voir  une technique redoutablement efficace permettant de détecter des collisions grâce aux pixels d’une image, pour ce faire nous allons réaliser une petite scène 2D avec un circuit et une voiture de course. Le résultat est sous vos yeux (j’arrive à lire la magie dans vos yeux).

Un début de jeu de course
Un début de jeu de course

Lire la suite Lire la suite

Programmer en Visual Basic.Net avec MonoGame

Programmer en Visual Basic.Net avec MonoGame

Suite à mon précédent article sur l’utilisation de MonoGame avec C++/CLI je vous propose le même genre mais cette fois le langage Visual Basic.Net. Il faut savoir que ce langage a de l’histoire chez Microsoft et c’est pour ça qu’on le trouve toujours parmi les langages disponibles dans Visual Studio. Historiquement on notera 2 grandes versions de Visual Basic, la version classique jusqu’à la version 6 et la version .Net qui fonctionne sur machine virtuelle et qui permet de travailler avec les composants de cette dernière. Pourquoi utiliser Visual Basic ? Et bien il y a des gens qui aiment encore ce langage et puis il y a les nostalgiques comme moi qui aiment bien programmer avec des « vieux » trucs remis au gout du jour, alors même si Locomotive Basic et Turbo Basic sont bien loin, aujourd’hui nous jouerons avec MonoGame en Visual Basic.Net.

Lire la suite Lire la suite

Programmer en C++/Cli avec MonoGame

Programmer en C++/Cli avec MonoGame

MonoGame est un Framework écrit en C# pour la plateforme .Net et Mono et permet de créer des jeux vidéo ou des applications multimédia sur plusieurs plateformes. L’avantage avec la machine virtuelle .Net est qu’elle permet d’utiliser plusieurs langages de programmation, ainsi vous pouvez avoir un projet en C# qui appel un projet en Visual Basic .Net qui lui même est appelé par un projet en C++/CLI voir en F#. A l’origine XNA et MonoGame ont été créés pour le langage C# (XNA en Visual Basic a été officiellement supporté à partir de Windows Phone 7.5) car c’est un langage cool et qu’il permet de garder le meilleur des 2 mondes entre C++ et des langages comme Java (oui il y a des choses très bien en Java aussi), cependant ce n’est pas strictement obligatoire, vous pouvez utiliser une dll .Net avec d’autres langages supportés par la CLR (Common Language Runtime) et là tout de suite nous allons voir comment utiliser MonoGame en C++/CLI.

Lire la suite Lire la suite

Sauvegarder des données sous Windows avec XNA

Sauvegarder des données sous Windows avec XNA

La sauvegarde des données est aujourd’hui quelque chose d’assez banale et ce, même sur les petites productions. C’est effectivement pratique pour le joueur de pouvoir régler une fois les paramètres et option du jeu et d’avoir sa progression de sauvegardée. Comme toujours le Framework XNA met à notre disposition une fonctionnalité intéressante pour sauvegarder et charger des données assez facilement. Le stockage est un sujet assez vaste car il est très dépendant du système sur lequel vous développez, ici nous ne traiterons que du cas sur PC sous Windows avec XNA, nous aurons l’occasion de revenir sur les autres cas dans des articles dédiés.

Mise en situation

L’objectif de ce tutoriel va être de sauvegarder des paramètres système dans l’espace de stockage de l’utilisateur et de les charger au lancement du jeu. Lorsque le jeu démarre on va vérifier qu’ils existent et si ce n’est pas le cas on utilisera des valeurs par défaut. La configuration du jeu sera stockée dans une classe très simple que voici :

[Serializable]
public class GameConfiguration
{
	public int Width;
	public int Height;
	public bool IsFullScreen;
	public float SoundVolume;
	public float MusicVolume;

	public GameConfiguration()
	{
		Width = 1280;
		Height = 720;
		IsFullScreen = false;
		SoundVolume = 0.7f;
		MusicVolume = 0.9f;
	}

	public GameConfiguration(int width, int height, 
		bool fullscreen, float soundVolume, float musicVolume)
	{
		Width = width;
		Height = height;
		IsFullScreen = fullscreen;
		SoundVolume = soundVolume;
		MusicVolume = musicVolume;
	}
}

Vous noterez que la classe est sérialisable ce qui est logique car son contenu va être sérialisé au format XML. Voyons maintenant comme travailler avec cette classe et surtout comment sauvegarder son contenu. Avant de commencer à rentrer dans le vif du sujet sachez que les sauvegardes seront stockées dans le dossier c:\Users\{Nom d’utilisateur}\Documents\SavedGames\{Nom de votre projet}\, vous noterez que c’est l’endroit où sont stocké les fichiers de sauvegarde (paramètres, statistiques, parcours du joueur, etc…) de  tous les jeux qui utilisent XNA et son système de stockage.

Je vous propose de créer une classe qui sera chargé de charger et sauvegarder des données dans l’espace de stockage de l’utilisateur. Je vous donne le début de la classe et nous la compléterons petit à petit avec les 2 méthodes manquantes.

using System;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Storage;

namespace StorageGameProject
{
    public class StorageManager
    {
        private const string ConfigurationFileName = "game.config";
        private StorageDevice _storageDevice;

        public StorageManager()
        {
            IAsyncResult result =  
		StorageDevice.BeginShowSelector(PlayerIndex.One, null, null);
            _storageDevice = StorageDevice.EndShowSelector(result);
        }

        public GameConfiguration LoadGameConfiguration()
        {

        }

        public void SaveGameConfiguration(GameConfiguration gameConfig)
        {

        }

        private StorageContainer GetContainer(string name)
        {
            IAsyncResult result = _storageDevice.BeginOpenContainer(name, null, null);
            result.AsyncWaitHandle.WaitOne();

            StorageContainer container = _storageDevice.EndOpenContainer(result);
            result.AsyncWaitHandle.Close();

            return container;
        }
    }
}

Dans un premier temps il faut ajouter les espaces de nom permettant de travailler avec les fichiers, les fichiers XML et le gestionnaire de stockage de XNA. Intéressons nous au constructeur de cette classe qui appel deux méthodes statiques issues de l’objet StorageDevice de XNA. Il faut savoir que sur PC, les actions de ces méthodes sont invisibles pour l’utilisateur car BeginShowSelector() sert à afficher à l’écran la liste des périphériques de stockage disponible et à inviter l’utilisateur a en sélectionner un, la méthode EndShowSelector() étant quant à elle appelée quand l’utilisateur a fait son choix. On retrouve ce fonctionnement sur Xbox 360 mais sur PC c’est totalement transparent pour l’utilisateur car il n’a qu’un seul stockage de disponible, son disque dur 😉

Choix du périphérique de stockage sur Xbox 360
Choix du périphérique de stockage sur Xbox 360

La méthode BeginShowSelector() va dans notre cas sélectionner le disque dur de l’utilisateur comme espace de stockage et EndShowSelector() va renvoyez une instance d’un objet de type StorageDevice pointant sur ce périphérique. Maintenant que le périphérique de stockage est défini, on peut l’utiliser pour sauvegarder ou charger des données. Vous noterez qu’on passe un paramètre PlayerIndex pour indiquer qu’on veux récupérer l’espace de stockage pour le joueur 1, on peut donc travailler avec les espaces de stockages des 4 joueurs au besoin.

Les conteneurs

Un conteneur est un endroit dans l’espace de stockage qui contient un ou plusieurs fichiers, par exemple nous pourrons avoir un conteneur « Sauvegardes » où on stockera tous les fichiers de sauvegarde, un conteneur « Paramètres » où on stockera tous les paramètres relatif à l’application ou encore un conteneur « Score » qui contiendrait tous les scores et succès remportés pour le joueur. Au final un conteneur n’est rien de plus qu’un dossier.

L’ouverture d’un conteneur est une opération asynchrone c’est à dire que l’exécution du jeu n’est pas bloquée durant la phase d’ouverture. Comme pour la récupération du stockage, on va utiliser les méthodes BeginOpenContainer() et EndOpenContainer() pour ouvrir un conteneur nommé.

Le chargement

Maintenant que nous savons comment récupérer l’espace de stockage utilisateur et ouvrir un conteneur, nous allons pouvoir stocker des données. En début de tutoriel j’ai donné une classe qui gère la configuration du jeu (GameConfiguration) et nous allons la créer au lancement du jeu pour récupérer les paramètres d’affichage.

public class Game1 : Microsoft.Xna.Framework.Game
{
	GraphicsDeviceManager graphics;
	SpriteBatch spriteBatch;
	StorageManager storageManager;
	GameConfiguration gameConfiguration;

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

		storageManager = new StorageManager();
		gameConfiguration = storageManager.LoadGameConfiguration();

		graphics.PreferredBackBufferWidth = gameConfiguration.Width;
		graphics.PreferredBackBufferHeight = gameConfiguration.Height;

		if (gameConfiguration.IsFullScreen)
			graphics.ToggleFullScreen();
	}
}

C’est donc le fichier Game1.cs qui se contente d’initialiser notre gestionnaire de stockage ainsi qu’une instance de GameConfiguration. La méthode LoadGameConfiguration() du gestionnaire de stockage sera chargée de récupérer les informations enregistrées si elles existent, sinon, elle renverra une instance par défaut qui contient des paramètres… par défaut. Son résultat permettra de configurer l’affichage du jeu.

public GameConfiguration LoadGameConfiguration()
{
	StorageContainer container = GetContainer("config");

	// Pas de sauvegarde
	if (!container.FileExists(ConfigurationFileName))
		return new GameConfiguration();

	// La sauvegarde existe
	Stream stream = container.OpenFile(ConfigurationFileName, FileMode.Open);

	XmlSerializer serializer = new XmlSerializer(typeof(GameConfiguration));

	GameConfiguration config = (GameConfiguration)serializer.Deserialize(stream);

	stream.Close();

	// Ne pas oublier de fermer le flux ET le container
	container.Dispose();

	return config;
}

La première étape consiste à récupérer le conteneur dans lequel les paramètres doivent être enregistrés, j’ai choisis de le nommer « config », il y aura donc un dossier « config » dans l’espace de stockage. Si le conteneur n’existe pas alors on retourne une instance de GameConfiguration qui possède des paramètres par défaut, sinon on ouvre un flux et on ouvre le fichier ou mode ouverture. L’objet XmlSerializer va nous permettre de désérialiser le contenu du fichier et en récupérer une instance, vous comprenez maintenant pourquoi il fallait que notre classe de configuration ai l’attribut « Serializable« . Il ne faut surtout pas oublier de fermer le flux et le conteneur. Nous sommes assurés que le jeu récupère bien des données.

La sauvegarde

Intéressons nous maintenant à la sauvegarde de données. Voyez plutôt le minuscule bout de code suivant :

// Sauvegarde des paramètres
if (state.IsKeyDown(Keys.S))
{
	gameConfiguration = new GameConfiguration(640, 480, true, 0.5f, 0.4f);
	storageManager.SaveGameConfiguration(gameConfiguration);
}

Si l’utilisateur presse la touche S alors les paramètres de configuration sont modifiés et ils sont sauvegardés dans le stockage utilisateur grâce à notre fantastique StorageManager (Lisez le avec un accent à l’américaine bien prononcé, ça le fera encore plus :P). On va maintenant terminer la classe de gestion du stockage avec l’implémentation de sa dernière méthode.

public void SaveGameConfiguration(GameConfiguration gameConfig)
{
	StorageContainer container = GetContainer("Config");

	if (container.FileExists(ConfigurationFileName))
		container.DeleteFile(ConfigurationFileName);

	Stream stream = container.CreateFile(ConfigurationFileName);

	XmlSerializer serializer = new XmlSerializer(typeof(GameConfiguration));
	serializer.Serialize(stream, gameConfig);
	stream.Close();

	container.Dispose();
}

Après récupération du conteneur on supprime le fichier de configuration et on le réécrit à la fin avec les nouvelles données qui sont passées en paramètre à la méthode.

Conclusion

Il n’y a pas à dire, la sauvegarde de données sur PC est vraiment très simple et grâce à cette nouvelle fonctionnalité vous allez pouvoir stocker facilement la configuration du jeu et les sauvegardes. Comme je l’ai annoncé en introduction le stockage est un gros morceau car il est très dépendant du système utilisé. Par exemple sur Xbox il faut bien faire attention que tous les conteneurs soient fermés avant d’essayer d’en ouvrir un autre. Sachez qu’il existe des composants pour XNA qui proposent une abstraction de haut niveau sur le stockage en proposant une API qui passe partout (mobile, console, pc), cependant il faut à mon sens, connaitre un peu le fonctionnement du stockage en natif avant de passer sur quelque chose de plus haut niveau.

Vous pouvez retrouver les sources de ce tutoriel sur mon espace Github à cette adresse.

Les fichiers XML avec XNA

Les fichiers XML avec XNA

Lorsque l’on développe un jeu, il y a un moment où l’utilisation d’une base de données, même minimaliste devient indispensable pour y stocker par exemple, certaines informations comme les caractéristiques d’une entité, les dialogues, etc.. Effectivement on ne peut pas tout écrire en dur dans le code car c’est sale et c’est surtout difficilement éditable, surtout pour des non programmeurs. Le Framework XNA met à notre disposition une solution très simple à mettre en oeuvre pour utiliser les fichiers XML avec le gestionnaire de contenu. On pourra ainsi créer le fichier, le modifier à la main et le charger dans le jeu depuis le gestionnaire de contenu (ce fichier sera transformé lui aussi en xnb). Dans un premier temps je vais vous présenter rapidement ce que l’on peut faire avec ce système puis nous verrons en deuxième partie comment mettre oeuvre cette technique.

Mise en situation

J’avais une classe EnnemyManager qui était chargée de créer des vagues d’ennemies dans mon jeu. La méthode qui ajoute une vague d’ennemie génère un identifiant qui correspond à un type d’ennemie. Ainsi dans ma classe ennemie j’avais quelque chose comme ça :

public Ennemy(EnnemyType type)
{
  _type = type;

  switch (type)
  {
    case EnnemyType.AnciensA:
	  _textureName = "Ennemies/AnciensA_48";
	  _framerate = 200;
	  _animationSize = new Vector2(48, 48);
	  _animationIndex = new int[] { 1, 2, 3, 4 };
	  _speed = 0.3f;
	  _live = 100;
	  // Etc...
	  break;
	case EnnemyType.AnciensB:
	 // Et encore d'autres cas...
  }
}

Je vous epargne le reste du switch (qui à force contenait 6 types). J’ai finalement réécris mon constructeur pour qu’il ressemble à ça  :

public Ennemy(EnnemyDescription description)
{
	_type = (AlienType)description.Id;
	_textureName = description.AssetName;
	_framerate = description.Framerate;
	_animationSize = new Vector2(description.AnimationSize[0], description.AnimationSize[1]);
	_animationIndex = description.AnimationIndex;
	_speed = description.Speed;
	_live = description.Health;

	// D'autres trucs
}

La première chose qui saute au yeux est la taille du constructeur qui a vraiment diminué ! C’est normal car on passe d’un switch avec des valeurs de variable en dur à une simple initialisation avec un objet de description. Voyons de plus prés le contenu de la classe EnnemyDescription.cs :

namespace SpaceGame.Data.Description
{
    public enum EnnemyType
    {
        OrganicsA = 0, OrganicsB, RobotA, RobotB, AncienA, AncienB
    }

    public class EnnemyDescription
    {
        public int     Id              { get; set; }
        public string  AssetName       { get; set; }
        public int     Health          { get; set; }
        public int     Framerate       { get; set; }
        public float   Speed           { get; set; }
        public int[]   AnimationSize   { get; set; }
        public int[]   AnimationIndex  { get; set; }
    }
}

Cette classe est très simple, on y retrouve les informations de base caractérisant un ennemie dans le jeu. La propriété Id est un entier qui représente la valeur de l’énumération EnnemyType, ainsi (int)EnnemyType.OrganicsA vaudra 0.

Maintenant voyons comment charger ces données pour initialiser un ennemie. Dans un premier je charge les données depuis le gestionnaire de contenu :

// Chargement depuis le gestionnaire de contenu
// Dans mon cas c'est une collection de description
SpaceCollection<EnnemyDescription> ennemiesDescription  = Content.Load<SpaceCollection<AlienDescription>>("Datas/ennemies");

// Récupération de la 1ère description qui correspond à
// EnnemyType.AnciensA (qui vaut 0 rappellez vous)
EnnemyDescription desc = ennemiesDescription[(int)EnnemyType.AnciensA];

// Création de l'ennemie
Ennemy ennemy = new Ennemy(desc);

C’est redoutablement efficace ! Dans mon cas je fais plus que charger une simple description d’ennemie car je charge en réalité toutes les descriptions dans une collection, que je stock dans la partie statique du jeu, ainsi je peux y accéder à n’importe quel moment. Voyons un extrait du fichier XML présent dans le dossier Content :

<?xml version="1.0" encoding="utf-8"?>
<XnaContent xmlns:Collection="SpaceGame.Data.Collection" xmlns:Description="SpaceGame.Data.Description">
  <Asset Type="Collection:SpaceCollection[Description:EnnemyDescription]">
    <collection>
      <Item>
        <Key>0</Key>
        <Value>
          <Id>0</Id>
          <AssetName>Ennemys/OrganicsA_48</AssetName>
          <Health>100</Health>
          <Framerate>150</Framerate>
          <Speed>1</Speed>
          <AnimationSize>48 48</AnimationSize>
          <AnimationIndex>1 2 3 4</AnimationIndex>
        </Value>
      </Item>
      <Item>
        <Key>1</Key>
        <Value>
          <Id>1</Id>
          <AssetName>Ennemys/OrganicsB_48</AssetName>
          <Health>100</Health>
          <Framerate>150</Framerate>
          <Speed>1</Speed>
          <AnimationSize>48 48</AnimationSize>
          <AnimationIndex>1 2 3 4</AnimationIndex>
        </Value>
      </Item>
    </collection>
  </Asset>
</XnaContent>

C’est très pratique car on peut facilement l’éditer à la main ou même construire un logiciel qui va le générer, le travail d’équipe sera largement facilité durant la phase d’affinage de Gameplay 🙂

Bon passons maintenant à la 2éme partie où nous allons mettre en place ce système avec un exemple très simple.

Paramétrage du projet

Il va nous falloir 3 projets différents pour mettre en place cette fonctionnalité, en réalité un projet est suffisant si vous ne faites qu’exploiter le fichier XML, mais comme nous voulons aussi le créer il nous faut 2 autres projets supplémentaires, que je détail ci-dessous.

  1. Le projet de jeu XNA pour Windows (ou Xbox ou WP7)
  2. Un projet de bibliothéque XNA pour Windows (ou Xbox ou WP7)
  3. Un projet C# sans interface graphique (mode console)

Projet de jeu XNA

La première étape va être de créer un nouveau projet de jeu (Windows Game 4.0). Pour ce tutoriel je l’ai appelé DemonixisGame (original vous ne trouvez pas ?). Ce projet contiendra le jeu, sa logique, etc…

Projet de bibliothéque XNA

Vous allez maintenant ajouter un nouveau projet en faisant un clic droit sur le nom de la solution, puis Ajouter > Nouveau projet > XNA Game Studio 4.0 > Windows Game Library 4.0, dans le cadre de ce tutoriel je l’ai nommé DemonixisGame.Data car c’est un projet qui ne contiendra que des données et des schémas de description, rien d’autre. Je vous invite à référencer tout de suite ce projet sur le projet de jeu et sur le projet de contenu (Clic droit sur le dossier référence des 2 projets > Ajouter une référence > Projet > Demonxis.Data).

Projet d’application Windows (console)

Enfin, il faut maintenant créer un dernier projet qui lui ne sera pas un projet XNA, mais une simple application Windows en console. Clic droit sur la solution > Ajouter > Nouveau projet > Visual C# > Application console. Vous pouvez la nommer DemonixisGame.ConsoleSerializer pour rester original. Ce dernier projet va nous permettre de générer le fichier XML à partir de données qu’on entrera en dur la première fois afin de créer la bonne structure du fichier (oui il faut une première fois pour tout ^^). Encore une fois il faut ajouter une référence vers le projet de donnée (Demonixis.Data). Vous pouvez constatez que le projet de bibliothèque est un pont entre tous tous les projets et c’est d’ailleurs son but (pour information, quand vous compilerez votre projet complet vous aurez un fichier DLL DemonixisGame.Data.dll à côté de votre exécutable de jeu).

Le projet console va utiliser l’IntermediateSerializer pour créer le fichier XML, il faut donc référencer les fichiers DLL suivants qui sont présents dans le dossier c:\Program Files (x86)\Microsoft XNA\Reference\Windows\ .

  1. Microsoft.Xna.Framework.dll
  2. Microsoft.Xna.Framework.Content.Pipeline.dll

Mise en place

Notre objectif va être d’exploiter la classe HeroDescription ci-dessous, elle est à ajouter dans le projet de bibliothèque (les données)

namespace DemonixisGame.Data
{
    public class HeroDescription
    {
        public string Name { get; set; }
        public int Health { get; set; }
        public int Mana { get; set; }
        public int WeaponId { get; set; }
    }
}

Maintenant dans le projet de jeu, pour exploiter ces données, on va créer un objet de type HeroDescription grâce au gestionnaire de contenu. Pour que cette opération fonctionne il faut bien évidemment que le dossier Content contienne un fichier xml avec le bon nom.

using DemonixisGame.Data;

private HeroDescription heroDescription;

protected override void LoadContent()
{
    spriteBatch = new SpriteBatch(GraphicsDevice);
    heroDescription = Content.Load<HeroDescription>("MageDescription");
}

C’est le fichier MageDescription.xml qui sera chargé. On va maintenant passer au projet Windows Console pour créer le fichier XML qui sera utilisé par le gestionnaire de contenu.

La sérialisation

La première chose à faire est de changer la version cible du Framework .Net de votre projet afin d’utiliser la version 4.0 et pas la version 4.0 Client Profile (Projet > propriétés > Application > Framework Cible).

Il faut ensuite ajouter quelques espaces de noms afin de pouvoir utiliser les fonctionnalités XML du Framework .Net, l’IntermediateSerializer du Content Pipeline de XNA et enfin les données issues de votre jeu (via le projet de bibliothèque).

using System.Xml;
using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate;
using DemonixisGame.Data;

Ensuite dans la fonction Main, nous allons créer un objet de type HeroDescription et renseigner ses propriétés.

static void Main(string[] args)
{
  HeroDescription heroDescription = new HeroDescription()
  {
    Health = 100, Mana = 200, 
	Name = "Vivi", WeaponId = 12
  };

  XmlWriterSettings settings = new XmlWriterSettings();
  settings.Indent = true;

  using (XmlWriter writer = XmlWriter.Create("MageDescription.xml", settings))
  {
    IntermediateSerializer.Serialize<HeroDescription>(writer, heroDescription, null);
  }
}

Ce simple code permet de créer le fichier XML représentant notre classe HeroDescription.cs. Une fois le projet compilé vous pouvez vous rendre dans le dossier « Visual Studio 2010\Projects\DemonixisGame\DemonixisGame.ConsoleSerializer\bin\Debug ». LanceZ le programme et vous verrez apparaitre à côté de l’exécutable un fichier XML MageDescription.xml avec ce contenu :

<?xml version="1.0" encoding="utf-8"?>
<XnaContent xmlns:Data="DemonixisGame.Data">
  <Asset Type="Data:HeroDescription">
    <Name>Vivi</Name>
    <Health>100</Health>
    <Mana>200</Mana>
    <WeaponId>12</WeaponId>
  </Asset>
</XnaContent>

Il ne reste plus qu’à déposer ce fichier dans le dossier Content du projet de contenu et compiler le jeu pour vérifier que tout fonctionne bien. Si vous avez une erreur de compilation il est très probable que ce soit à cause d’une référence manquante sur le projet de contenu (Il faut qu’il ai une référence vers le projet de données pour connaitre le type sérialisé). Vous pouvez maintenant utiliser le contenu de ce fichier directement dans votre jeu et faire des affinages des données au besoin.

Ne vous limitez pas à de simple objet de description, vous pouvez sérialiser des collections (génériques ou standards), des tableaux, etc…

Conclusion

Nous avons vue comment utiliser et exploiter le système de sérialisation proposé par XNA, celui-ci s’avère relativement pratique pour stocker des données et les réutiliser plus tard dans son jeu. La prochaine étape pour exploiter au mieux cette fonctionnalité, pourrait être de créer une interface graphique permettant de créer et éditer les données.

J’attire votre attention sur le fait que le fichier xnb généré durant la sérialisation est parfaitement compatible avec le Framework MonoGame 😉 Vous pouvez donc utiliser cette technique sur vos projet Windows, Linux, Mac, Android et j’en passe.

Intégration de MonoGame avec du XAML sous Windows 8 Metro

Intégration de MonoGame avec du XAML sous Windows 8 Metro

Nous avons vue dans un précédent tutoriel comment mettre en place un projet MonoGame pour Windows 8 Metro, aujourd’hui je vais vous expliquer comment utiliser du XAML avec MonoGame. Avant de commencer je tiens à vous dire que mélanger MonoGame et XAML n’offre pas de bonnes performances sur les appareils de faible puissance, comme les tablettes ou certains netbook. L’objectif de cet article va être de créer deux pages, un menu qui sera tout en XAML et une page de jeu où on utilisera MonoGame. J’ai pu écrire cet article grâce à un poste sur le forum de MonoGame ainsi qu’à un article du blog Game Development Resources que j’ai adapté et corrigé.

1 – Prérequis

Pour suivre ce tutoriel vous devez avoir une version de Windows 8 RC ou finale ainsi que Visual Studio Express 2012 final (ou une version supérieur). Vous devrez aussi compiler la dernière version de MonoGame pour Windows 8 (consultez ce tutoriel si vous ne savez pas comment faire). Si vous ne pouvez pas compiler MonoGame pas d’inquiétude, le projet complet est téléchargeable à la fin de cet article.

Enfin vous devrez connaitre les bases du XAML et les bases du fonctionnement d’une application Metro (je sais il ne faut plus les appeler comme ça).

2 – La création du projet

La première chose à faire est de créer un projet avec Visual Studio, en choisissant Application vide (xaml), ensuite vous devrez éditer le fichier du projet comme indiqué dans le précédent tutoriel afin de pouvoir charger du contenu à partir du dossier Content. J’attire encore une fois votre attention sur le fait que MonoGame n’a pas de compilateur de contenu (pour le moment) et que vous ne pouvez charger que des fichiers xnb déjà compilés.

Une fois que le projet est créé vous avez 2 fichiers xaml, App.xaml qui représente votre application, c’est cette classe qui est instanciée en premier quand l’utilisateur lance l’application et MainPage.xaml qui représente le contenu de la première page visible par l’utilisateur. Nous allons ajouter une nouvelle page au projet qui sera la page dite de « Jeu » et qui contiendra le rendu et la logique de MonoGame. Faites donc un clique droit sur votre projet (pas la solution, le projet) et choisissez dans le menu contextuel l’option Ajouter / Nouvel élément.. et enfin page vierge. Vous vous retrouvez maintenant avec une nouvelle page XAML que nous allons modifier dans un moment. Enfin nous ajoutons une référence vers MonoGame.Windows8.dll au projet.

3 – La classe App.xaml.cs

La première chose à faire est d’ajouter les directives using necessaires pour travailler avec MonoGame

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

On déclare ensuite quelques références pour naviguer entre les pages, on initialise le gestionnaire de contenu et le gestionnaire de service.

public ContentManager Content { get; set; }
public GameServiceContainer Services { get; set; }
public GamePage GamePage { get; set; }
public Frame RootFrame { get; set; }

Il ne reste plus qu’à initialiser MonoGame avec une méthode InitializeXNA() par exemple, que nous appellerons dans le constructeur de App.

// Constructeur
public App()
{
	this.InitializeComponent();
	this.InitializeXNA();
	this.Suspending += OnSuspending;
}

private void InitializeXNA()
{
	Services = new GameServiceContainer();
	Services.AddService(typeof(IGraphicsDeviceService), new SharedGraphicsDeviceManager());

	Content = new ContentManager(Services);
	Content.RootDirectory = "Content";
}

Enfin nous allons changer le contenu de la méthode OnLaunched afin d’y initialiser la page de jeu « GamePage » et définir comme première vue MainPage.xaml.

protected override void OnLaunched(LaunchActivatedEventArgs args)
{
	if (args.PreviousExecutionState == ApplicationExecutionState.Running)
	{
		Window.Current.Activate();
		return;
	}

	if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
	{
		// On termine l'application
	}

	RootFrame = new Frame();
	if (!RootFrame.Navigate(typeof(MainPage)))
	{
		throw new Exception("Impossible de créer la page initiale");
	}

	// Initialisation de la page de jeu qui contient le code XNA
	GamePage = new GamePage();

	Window.Current.Content = RootFrame;
	Window.Current.Activate();
}

Il faut que je vous parle de la méthode OnSuspending(), elle est appelée lorsque l’utilisateur switch vers une autre application ou ferme votre application. Il faudra donc dans cette méthode mettre le code nécessaire pour sauvegarder les données du jeu (score, avancement, etc…)

4 – MainPage.xaml

Je vous propose de réaliser un petit menu en XAML, rien de bien compliqué, un titre avec un sous titre et des boutons pour choisir l’action désirée. Alors voilà ce que je veux que vous fassiez

Menu XAML
Et voilà le menu !

C’est un chouette non ? Bon c’est très vide d’accord ! Mais ça ira très bien pour notre tutoriel 😉 Vous trouverez le code à la fin de l’article et comme cette partie est très simple je vais juste vous donner le code de l’événement du bouton « New Game »

private void btnLaunchGame_Click_1(object sender, RoutedEventArgs e)
{
	var gamePage = ((App)App.Current).GamePage;

	Window.Current.Content = gamePage;
	Window.Current.Activate();
}

lorsque l’on cliquera sur « New Game » on passera sur le rendu XNA, par contre attention les choses vont se compliquer un peu (mais vraiment un peu) à partir de maintenant.

5 – La vue Game.xaml

Si vous ouvrez cette vue vous pourrez constater qu’elle dérive de la classe Page mais nous, nous voulons un rendu XNA et pas une page. On va donc remplacer tout le code généré par celui ci

<SwapChainBackgroundPanel 
    x:Class="MonoGameXAML.GamePage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MonoGameXAML"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Button x:Name="btnBack" Content="Back" HorizontalAlignment="Center" Width="120" Height="35" Margin="10, 20, 10, 0" VerticalAlignment="Top" Click="btnBack_Click" />
</SwapChainBackgroundPanel>

Alors attention au copier/coller s’il vous plait ! La deuxième ligne x:Class= »MonoGameXAML.GamePage » doit être adaptée à votre projet et votre espace de nom. J’utilise comme espace de nom pour mon application MonoGameXAML (c’est le nom de mon application aussi du coup), donc là il faut bien mettre le nom de votre espace de nom sinon ça ne marchera pas hein 😉

La première chose marquante sur ce code est le remplacement de la classe Page par SwapChainBackgroundPanel ! Cette classe permet d’utiliser un rendu DirectX dans du Xaml or MonoGame utilise justement DirectX pour le rendu graphique (mais comme ça nous arrange tout ça !). Bon sinon j’ai ajouté un petit bouton pour revenir en arrière (donc au menu dans notre cas mais ça peut être n’importe quelle page xaml).

6 – GamePage.xaml.cs

Bon les amis là on ne rigole vraiment plus ! C’est ici qu’on va retrouver toutes les méthodes bien connues, à savoir Initialize(), LoadContent(), UnloadContent(), Update() et enfin.. Draw(). Pour commencer en douceur on va ajouter les directives using qui vont bien, comme on l’a déjà fait dans App.xaml.cs. Ensuite il faut déclarer les objets nécessaires au fonctionnement de MonoGame

private GameTimer gameTimer;
private SharedGraphicsDeviceManager manager;
private ContentManager content;
private bool pageLoaded;
private SpriteBatch spriteBatch;

L’objet GameTimer va permettre de créer la boucle de jeu infinie, le SharedGraphicsDeviceManager va nous permettre d’accéder aux différents objets de GraphicsDeviceManager et les 3 autres et bien vous les connaissez bien je pense 😉 Dans le constructeur nous allons nous abonner à 2 évènements de la classe SwapChainBackgroundPanel et indiquer que la page n’est pas chargée.

public GamePage()
{
	this.pageLoaded = false;
	this.Loaded += GamePage_Loaded;
	this.Unloaded += GamePage_Unloaded;
	this.InitializeComponent();
}

Nous nous occupons tout de suite des évènements de chargement et déchargement de la page comme suis

#region Evénements de la page

private void GamePage_Unloaded(object sender, RoutedEventArgs e)
{
	UnloadContent();
}

private void GamePage_Loaded(object sender, RoutedEventArgs e)
{
	if (!pageLoaded)
	{
		manager = SharedGraphicsDeviceManager.Current;
		manager.PreferredBackBufferWidth = (int)this.ActualWidth;
		manager.PreferredBackBufferHeight = (int)this.ActualHeight;
		manager.SwapChainPanel = this;
		manager.ApplyChanges();

		gameTimer = new GameTimer();
		gameTimer.UpdateInterval = TimeSpan.FromTicks(166666);
		gameTimer.Update += Update;
		gameTimer.Draw += Draw;

		this.SizeChanged += GamePage_SizeChanged;

		// Le contenu est chargé une fois
		LoadContent();

		pageLoaded = true;
	}

	// L'initialisation doit se faire à chaque rechargement
	Initialize();
}

private void GamePage_SizeChanged(object sender, SizeChangedEventArgs e)
{
	ResizePage((int)e.NewSize.Width, (int)e.NewSize.Height);
}

private void ResizePage(int width, int height)
{
	manager.PreferredBackBufferWidth = width;
	manager.PreferredBackBufferHeight = height;
	manager.ApplyChanges();

        // A la suite vous pouvez modifier d'autres tailles et positions
        // de vos objets graphiques
}

#endregion

On a 2 méthodes issus des évènements déclarés dans le constructeur, GamePage_Unload() sera appelée au déchargement de la page et videra la mémoire des ressources chargées et GamePage_Loaded() sera appelée quand la page sera chargé et devra initialiser le gestionnaire graphique, le timer et s’abonner à l’évènement SizeChanged (je vais y revenir). Dans tous les cas on lance la méthode Initialize().

Cycle de vie d’une application

Je vais vous parler rapidement du cycle de vie de l’application. Quand vous lancer pour la première fois GamePage.xaml le constructeur fait son travail et l’initialisation est faite. Si vous revenez au menu et que vous relancez GamePage.xaml, la page ne sera pas recréée car elle a déjà été instanciée une fois,  par contre la méthode GamePad_Loaded() sera rappelée une seconde fois, c’est pour cette raison que l’on a une variable qui va nous permettre de savoir si la page a déjà été chargée, auquel cas on ne réinitialise ni le gestionnaire graphique, ni les ressources, par contre on réinitialise le reste avec Initialize() afin que les différentes positions et autres réglages d’initialisation soit remis à zéro.

Un autre aspect important à prendre en compte lors du cycle de vie de l’application est le redimensionnement de celle ci. Les applications Windows 8 Metro peuvent en effet être redimensionnées, pour par exemple s’accrocher sur le bord de l’écran (voir le screen plus haut) et il faut donc à chaque changement de taille, faire les changements qui vont bien (changer la taille de la scène ou la mettre en pause si la surface est trop petite par exemple).

Il y a deux autres évènements issus de la classe SwapChainBackgroundPanel assez pratiques à exploiter que je vous encourage à implémenter. LostFocus et GotFocus sont très importants lorsque l’utilisateur accroche l’application au bureau par exemple, car il peut arriver que votre application perde le focus et dans ce cas il faut agir en conséquence (la mettre en pause, sauvegarder les données, afficher un truc rigolo ou qui fait peur ?). Lorsqu’elle retrouve le focus (l’utilisateur agit dessus) vous pourrez alors tout remettre en place (virer la pause ou le trucs rigolo ou qui fait peur!). Je vous invite à lire l’article du blog Dot.Blog de qui explique très bien le cycle de vis d’une application.

Fin d’implémentation

Enfin nous allons écrire les méthodes Update() et Draw() qui permettent respectivement de mettre à jour la logique du jeu et dessiner le tout à l’écran

#region XNA GameState pattern

private void LoadContent()
{
	spriteBatch = new SpriteBatch(manager.GraphicsDevice);
	// On récupère l'instance du gestionnaire de contenu
	// créé dans App.xaml.cs
	content = ((App)App.Current).Content;
}

private void Initialize()
{
	// 1 - Il faut démarrer le timer
	gameTimer.Start();

	// Vos initialisations
}

private void UnloadContent()
{
	// On stop la boucle de jeu
	gameTimer.Stop();
}

private void Update(object sender, GameTimerEventArgs e)
{
	// Vos mises à jour de logique de jeu
	// on accéde au temps écoulé avec 
	// e.ElaspsedGameTime
}

private void Draw(object sender, GameTimerEventArgs e)
{
	manager.GraphicsDevice.Clear(Color.DarkCyan);
	spriteBatch.Begin();
	spriteBatch.Draw(...);
	spriteBatch.End();
}

#endregion

On termine avec le bouton « Back » qui permet de revenir au menu. On récupère l’instance de la classe App et on redirige vers MainPage.xaml.

private void btnBack_Click(object sender, RoutedEventArgs e)
{
	var mainPage = ((App)App.Current).RootFrame;

	Window.Current.Content = mainPage;
	Window.Current.Activate();
}

Voilà c’est terminé ! Vous avez une application Metro en XAML et MonoGame (bon sang j’ai faillis écrire XNA un paquet de fois !)

 

Vous retrouverez le projet entier sur mon espace Github dédié à ce blog avec un exemple d’utilisation basique de MonoGame. Vous pouvez aussi le télécharger depuis ce lien. Le projet est complet avec les références de MonoGame et la modification du projet pour profiter du gestionnaire de contenu grâce au dossier Content

J’espère que cet article vous aura permis d’y voir un peu plus clair sur l’utilisation de MonoGame et de XAML, n’oubliez pas comme je l’ai dis en introduction que les performances XAML + MonoGame ne sont pas exceptionnelles sur des machines de faible puissance. Sur un PC classique ça fonctionne en tout cas très bien. Si vous rencontrez des problèmes de compilation, de code ou autre, n’hésitez pas à laisser un commentaire ou à me contacter sur ma page Google+. Codez bien ! On se revoit dans un prochain article.

Créer un projet MonoGame pour Windows 8 ModernUI

Créer un projet MonoGame pour Windows 8 ModernUI

Le prochain système d’exploitation de Microsoft, Windows 8, apporte une nouvelle approche d’utilisation proche des appareils mobiles, la fameuse interface Metro. Toutes les applications Metro (les Metro Style Apps) sont des applications autonomes qui ont leurs propre espace de stockage comme c’est le cas déjà le cas pour les applications mobiles sur Windows Phone 7 et sur Xbox 360 mais aussi sur AIR par exemple. La nouvelle API WinRT apporte des changements important sur la conception des applications au sein de Metro. Comme XNA n’a pas été mis à jour pour Windows 8 et Windows Phone 8, l’équipe du Framework MonoGame a commencé un portage qui commence d’arriver à maturation. Les changements au niveau de MonoGame sont nombreux, on notera par exemple la suppression de la dépendance à OpenTK qui permettait de gérer l’affichage via OpenGL et le son via OpenAL pour une utilisation de SharpDX (la meilleur bibliothèque DirectX managée actuelle). Nous partons donc avec un rendu via Direct3D 11 ! Il y a aussi des changements important au niveau du gestionnaire de contenu, mais nous y reviendrons. Actuellement le support de Windows 8 n’est pas « officiel » et il faudra compiler la branche de développement « develop3d » et mettre en place un projet Metro manuellement. Nous allons voir comment mettre en place tout ça, voilà ce qui vous attend :

  1. Téléchargement des sources de la branche « develop3d »
  2. Compilation des sources en mode « Release »
  3. Création du projet Metro
  4. Code de test

Courage ! il faut souffrir pour être beau non ? Et bien pour faire des jeux cools sous Windows 8 RC avant tout le monde c’est pareil 😉

Télécharger les sources

On va commencer par mettre en place les outils dont nous aurons besoin, dans un premier temps installez Visual Studio 2012 (j’utilise la version Pro) et Git pour Windows. Nous allons récupérer les sources, ouvrez git bash et placez vous dans le dossier où vous voulez télécharger les sources (je me place pour ma part dans c:\User\Yann\Sources). Ensuite on récupère les sources

git clone https://github.com/mono/MonoGame.git

Une fois que le téléchargement est terminé on passe sur la branche « develop3d »

git checkout develop3d --force

J’ai ajouté l’option –force car les fichiers du dépôt ne seront peut être pas encodés avec le même saut de ligne que vous et git vous aurait demandé de commiter les changements avant de faire un changement de branche, donc là on dit à git « fou moi la paix et passe sur develop3d ». Il faut maintenant ajouter les dépendances externes comme suis :

git submodule init

pour finir on les télécharges

git submodule update .\ThridParty

Si vous voulez récupérer les exemples et les starter kits vous pouvez aussi faire un update tout court mais attention ça sera beaucoup plus long car il y a beaucoup d’exemples 😉 (J’attire votre attention sur le fait qu’un ne possède de projet Windows 8 donc ça ne sert pas à grand chose).

Voilà nous sommes prêt à compiler les sources, rendez vous dans le dossier de MonoGame (dans l’explorateur cette fois ci, la console c’est fini) et ouvrez la solution Windows 8 : MonoGame.Framework.Windows8

Compilation des sources

Les dépendances sont manquantes

La première étape consiste à vérifier si les références sont bien là, si les références sont manquantes il faudra les ajouter, pour ça pas de panique on sen rend sur le site de SharpDX pour télécharger les binaires et on ajoutes les fichiers dll de l’archive précédemment téléchargé en référence au projet. Je ne pense pas que vous soyez intéressé pour debuger le Framwork MonoGame ? Donc dans ce cas on sélectionne le mode de compilation « Release » qui nous fournira une série de fichiers dll optimisés pour la production.

On compile la solution entière, clic droit/Compiler la solution. Une fois la compilation terminée allez dans le dossier MonoGame\MonoGame.Framework\bin\Release et récupérez y son contenu, nous l’utiliserons prochainement dans notre projet MonoGame Metro.

 Création du projet Metro

Si vous avez déjà essayé de faire des applications Metro vous avez remarqué que le fonctionnement est similaire à celui de Windows Phone, à savoir un fichier d’interface XAML et du code behind en C#. Pour créer un jeu avec MonoGame nous n’avons pas besoin de tout ça alors l’équipe à créé une série de Templates pour Visual Studio afin de démarrer un projet rapidement et sans trop de prise de tête.

Les templates pour Visual Studio 2012

Dans un premier temps allez dans Mes documents puis dans le dossier Visual Studio 2012, allez ensuite dans Templates, ProjectTemplates\Visual C# et créez un dossier MonoGame.

Il faut maintenant y copier les 3 dossiers présents dans le dossier ProjectTemplates\VisualStudio11.MonoGame.2.5.

Maintenant quand vous démarrerez Visual Studio et que vous créerez un nouveau projet C# vous aurez une nouvelle possibilité : MonoGame ! Les amis, nous attaquons la partie la pénible de cet article, il va falloir éditer le fichier de projet pour pouvoir utiliser le gestionnaire de contenu.

Comme je l’ai dit au début de cet article, l’API WinRT introduit un tas de changements  comme par exemple le stockage mais surtout la programmation asynchrone (une nouveauté de .Net 4.5). On ne peut donc pas charger des ressources qui pourraient bloquer le programme trop longtemps (voir les spécifications des applications Metro). J’attire aussi votre attention sur le fait que pour le moment vous ne pouvez charger que du contenu compilé en .xnb, donc pas de format non compressé comme une image JPG ou PNG, mais nous y reviendrons en fin d’article (j’ai un super outils à vous présenter).

Dans un premier temps on créé un nouveau projet de jeu MonoGame pour Metro et on ajoute les références qui vont bien, prenez donc les fichiers dll que nous avons compilé tout à l’heure et ajoutez les en tant que référence au projet, à partir de là vous pouvez compiler et lancer le projet, vous aurez le droit à un petit Splash Screen puis à un écran bleu (normal on fait un clear de l’écran avec Color.AliceBlue et rien d’autre :P). Le projet contient un dossier Assets où sont stockés les différentes images pour les icones et le Splash Screen, créez maintenant un dossier Content où on pourra mettre toutes nos assets de jeu (au format XNB je vous le rappel), pendant que vous y êtes créez aussi un dossier MonoGame.

Maintenant fermez Visual Studio 2012 et rendez vous dans le dossier « projet » de votre projet (typiquement dans Mes Documents/Visual Studio 2012/Projects/Votre Projet/Votre Projet puis éditez le fichier du projet avec un éditeur de texte comme Notepad++ par exemple.

 

Vous avez devant vous un fichier XML qui décrit le fonctionnement de votre projet, on y retrouve les références, les dossiers du projet, etc…

Vous allez remplacer la troisième ligne

<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />

Par celle-ci

<Import Project="MonoGame\MonoGame.ContentPipeline.targets" />

Enfin ajoutez ceci avant la fermeture de la première balise <PropertyGroup>

<MonoGamePlatform>Windows8</MonoGamePlatform>

Ensuite vers la ligne 118 cherchez la propriété <ItemGroup> vous y trouverez des balises <Content>, il faut maintenant ajouter la ligne suivante qui va dire à Visual Studio qu’il faut copier le dossier Content dans l’espace de stockage de l’application

<Content Include="Content\**\*.*">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

Si vous n’êtes pas sur de votre coup ne vous en faites pas j’ai laissé le projet fonctionnel en fin d’article, alors vous pourrez vérifier ce que vous avez fait.

Il nous reste encore une chose à faire (oui je sais ça commence à être long mais c’est promis après ça c’est fini) et c’est là une des chose les plus importantes à faire ! Vous allez copier le contenu du dossier MonoGame\MonoGame.ContentPipeline (des sources de MonoGame) vers le dossier MonoGame de votre projet, si vous regardez plus haut on fait référence à ce dossier et son contenu dans le fichier XML du projet en ligne 3. A partir de maintenant vous pouvez ouvrir votre projet avec Visual Studio et commencer à programmer votre jeu ! Oui on a fini, c’est vrai  je vous assure 🙂

Le projet fonctionnel sur l’émulateur Windows 8

Une dernière chose avant de vous laisser partir, comme nous l’avons vue pour le moment on ne peut utiliser que des fichiers xnb alors comment faire pour ne pas devoir installer XNA Game Studio et créer un projet afin de compiler ses fichiers en xnb ? La réponse est simple il existe un petit programme « XNA 4 Content Compiler » qui permet de compiler des images, musiques, fonts en fichier xnb ! La solution vraiment pratique pour éviter une installation de Visual Studio 2010 Express.

Une autre alternative existe et est tout aussi efficace, XNB Builder vous permettra de construire des fichiers XNB à partir de tous les formats connus par XNA. Je vous recommande vivement cet outils qui est plus complet que le précédent.

Conclusion

Vous pouvez télécharger le projet sur le dépôt github dédié à ce blog. Bon et bien nous avons finalement réussi à mettre en place un projet fonctionnel pour Windows 8 Metro. Sachez que grâce à l’utilisation de SharpDX, les jeux que vous créerez seront compatible avec le tout nouveau Windows Store et vous pourrez ainsi en faire profiter tout les utilisateurs. Pour plus d’information n’hésitez pas à suivre le compte twitter de MonoGame et consulter le forum sur le codeplex.

SpaceShip porté sur Windows 8 Metro
SpaceShip porté sur Windows 8 Metro

Edit : Je viens de réaliser un port très rapide du jeu de shoot spatial du TP XNA que je vous propose sur ce blog. Vous pouvez le télécharger sur Github à cette adresse.