Exceptions et gestion des fichiers : sauvegarder et charger un niveau
Le stockage des données
Dans cette première partie, vous allez découvrir la théorie liée aux différents emplacements de stockage mis à disposition par XNA, ainsi qu’aux différentes méthodes de sauvegarde de données. Les espaces de stockage Le framework XNA met à votre disposition deux espaces de stockage bien distincts : • Le dossier du jeu dans lequel se situe l’exécutable, ainsi que tout le contenu que vous aurez créé (textures, sons, etc.). =Labat FM.book Page 145 Vendredi, 19. juin 2009 4:01 16 Exceptions et gestion des fichiers : sauvegarder et charger un niveau Développement XNA pour la XBox et le PC 146 • Le dossier de l’utilisateur où se situent les sauvegardes ou la configuration préférée d’un joueur. Sous Windows, il s’agit du répertoire SavedGames situé dans le répertoire personnel de l’utilisateur connecté sur le PC. À l’intérieur de ce répertoire se trouve un dossier correspondant au nom du jeu exécuté. Enfin, la dernière ramification correspond au numéro du joueur (PlayerIndex). Si aucun n’est spécifié, les fichiers se trouvent dans le répertoire AllPlayers, sinon dans un répertoire correspondant à ce numéro (Player1, Player2, Player3 ou Player4). Sur Xbox, il s’agit du disque dur ou d’une carte mémoire : c’est le joueur qui choisira le périphérique de stockage qu’il souhaite utiliser. Le format XML, un format intelligible qui simplifie le stockage de données XML (eXtensible Markup Language, en français langage extensible de balisage) est utilisé pour contenir des données qui seront encadrées par des balises. Si vous vous êtes déjà aventuré dans la création d’un site web, vous avez probablement rencontré le HTML qui repose également sur des balises utilisées pour formater l’affichage de données. L’autre spécificité de XML est qu’il n’y a pas une liste de balises définies : c’est à vous de créer celles qui vous seront utiles. Ainsi, XML est utilisé dans des domaines très variés : • Les fichiers de configuration de logiciels ou de jeux sont de plus en plus basés sur ce format. Certains utilisent même ces fichiers pour la configuration de l’interface utilisateur, permettant ainsi aux utilisateurs novices de la paramétrer très facilement. Zune Sur le Zune, cet espace de stockage se limite à 16 Mo. Cela correspond à la mémoire vive qu’un jeu peut utiliser. Figure 8-1 Fichier personnel de configuration du jeu Racing Game Lecteur réseau Si votre dossier personnel (Documents and Settings\) ne se situe pas sur l’ordinateur où vous exécuterez un jeu qui doit sauvegarder des données personnelles, mais sur un lecteur réseau, une exception sera levée rendant la sauvegarde impossible. À l’heure actuelle, l’exécution d’un jeu à travers le réseau n’est pas supportée par XNA. =Labat FM.book Page 146 Vendredi, 19. juin 2009 4:01 16 Exceptions et gestion des fichiers : sauvegarder et charger un niveau CHAPITRE 8 147 • Dans les jeux vidéos, les fichiers de sauvegarde ou ceux qui décrivent les niveaux peuvent aussi utiliser le format XML. Ci-dessous, vous retrouvez un fichier de configuration fictif, utilisant le XML, qui pourrait correspondre à la résolution de l’écran dans un de vos jeux.
Les exceptions
Essayez de vous connecter avec un compte qui n’est pas membre du XNA Creators Club. Que se passe-t-il ? La fenêtre du jeu se ferme et le focus est donné à Visual Studio où une bien étrange boîte de dialogue est apparue. Cela signifie qu’une exception a été levée, en l’occurrence GamerServicesNotAvailableException. Quand une erreur survient, une exception est levée. À partir de ce moment, l’exécution normale est interrompue et un gestionnaire d’exceptions est recherché dans le bloc d’instructions courant. S’il n’est pas trouvé, la recherche se poursuit dans le bloc engloFigure 8-3 Une exception a été levée =Labat FM.book Page 148 Vendredi, 19. juin 2009 4:01 16 Exceptions et gestion des fichiers : sauvegarder et charger un niveau CHAPITRE 8 149 bant celui-ci ou, à défaut, dans le bloc de la fonction appelante, et ainsi de suite. Si la recherche n’aboutit pas, une boîte de dialogue signalant l’exception s’affiche. Si votre jeu avait été exécuté en mode Release, par exemple par un de vos amis dont vous auriez aimé avoir l’avis, une boîte de dialogue peu commode se serait affichée (figure 8-4). Vous allez donc devoir protéger votre jeu de ces arrêts brutaux en ajoutant autant de gestionnaires d’exceptions que nécessaire. En pratique, il faut en ajouter chaque fois qu’une portion de code est susceptible de rencontrer un problème : tentative de connexion au réseau impossible, accès à des données qui n’existent pas, division par zéro, dépassement de l’indice maximum lorsque vous manipulez des tableaux, etc. La liste peut être très longue… L’extrait de code ci-dessous vous présente la structure basique d’un gestionnaire d’exceptions. Le code susceptible de générer une exception, et qui doit dont être testé, est celui présent dans le bloc try. Vous pouvez ensuite récupérer l’exception pour la traiter dans le bloc catch. try { // Portion de code pouvant lancer une exception } catch(Exception e) { // Traitement de l’exception } L’exemple suivant divise une variable a par une variable b. Ici vous connaissez la valeur de b, or cela n’est pas toujours le cas. Dans le doute, il est préférable d’ajouter un gestionnaire d’exceptions pour se prémunir contre une division par zéro. Si une exception est levée, sa description est affichée dans le titre de la fenêtre du jeu. Figure 8-4 Voici la fenêtre qui apparaîtra si vous gérez mal vos exceptions =Labat FM.book Page 149 Vendredi, 19. juin 2009 4:01 16 Développement XNA pour la XBox et le PC 150 int a = 10; int b = 0; try { a /= b; } catch (Exception e) { Window.Title = e.Message; } Dans l’intitulé de la fenêtre, vous pouvez lire : En C#, les exceptions particulières dérivent toutes de la classe Exception. L’exemple précédent a levé une exception de type DivideByZeroException, mais aucun bloc catch qui lui correspond n’est présent. Il en existe tout de même un traitant une exception de type Exception, c’est ce bloc qui sera exécuté. Vous pouvez donc cumuler les blocs catch de manière à effectuer un traitement spécial pour certaines erreurs. L’extrait de code ci-dessous reprend l’exemple précédent en affichant un message spécial si l’exception levée est une division par zéro et un message plus générique s’il s’agit d’une autre exception (sait-on jamais). int a = 10; int b = 0; try { a /= b; } catch (DivideByZeroException e) { Window.Title = « Je le savais »; } catch (Exception e) { Window.Title = e.Message; } Cette fois-ci, dans l’intitulé de la fenêtre, vous pouvez lire le message personnalisé. Vous pouvez également ajouter un bloc finally qui sera exécuté, qu’une exception ait été levée ou non. int a = 10; int b = 0; Tentative de division par zéro. Je le savais =Labat FM.book Page 150 Vendredi, 19. juin 2009 4:01 16 Exceptions et gestion des fichiers : sauvegarder et charger un niveau CHAPITRE 8 151 try { a /= b; } catch (DivideByZeroException e) { Window.Title = « Je le savais »; } catch (Exception e) { Window.Title = e.Message; } finally { Window.Title = « Il est passé ici »; } La levée d’une exception se fait en utilisant le mot-clé throw suivi d’un objet du type de l’exception voulue. Dans l’exemple suivant, la fonction TestException lèvera une exception si le paramètre i vaut 0. protected override void Initialize() { base.Initialize(); try { TestException(0); } catch (Exception e) { Window.Title = e.Message; } } private void TestException(int i) { if (i == 0) throw new Exception(« i vaut 0 ! »); } Personnaliser les exceptions Vous pouvez créer vos propres exceptions selon vos besoins. Il suffit de les faire dériver de la classe Exception.