|
|
|||||||||||||||
|
Ce très bon article est aussi disponible sur l'excellent site c2i.fr de notre ami Richard Clark, l'un des grands spécialistes français de .NET
Ceci est mon premier programme pour le Compact .NET Framework, et j'avoue que l'aventure fut passionnante mais surtout, un peu plus ardue que je ne pensais. Enfin, c'est comme tout, c'est la première fois le plus dur, après, c'est de la routine...
Pour développer cette application, j'ai utilisé Visual Studio .NET 2003 en Final Beta ainsi que le Compact .NET Framewor(CF par la suite) qui est maintenant en version Gold (donc redistribuable). Si vous ne désirez que tester l'application sur votre machine, il vous faudra dans un premier temps télécharger et installer ce CF à l'adresse suivante : http://www.gotdotnet.com/team/netcf/askdotnet/downloadRuntime.aspx Vous le trouverez en version arm, mips et sh3.
Elles sont très simples : quand vous cliquez sur une bulle, un score apparait. Celui-ci est calculé en fonction du nombre de bulles adjacentes de même couleur (verticalement et horizontalement) et est le produit de ce nombre par son nombre moins 1 (n*(n-1)). Ainsi si trois bulles rouges sont adjacentes, vous aurez un score de 3*(3-1) soit 6. Un deuxième clic sur l'une de ces bulles, elles sont détruites et vous êtes crédité alors de ce score et les bulles placées au dessus des bulles détruites descendent sous l'effet de la gravité. Si une colonne entière est vide, les colonnes placées à gauche sont décalées vers la droite (j'ai horreur du vide). Le jeu se termine s'il n'y a plus de bulle de même couleur adjacente. NB : mon record actuel réalisé dans le train me ramenant des DevDays de Lyon à 2h du mat est de 1550 points, avis aux amateurs.
Bien entendu, je souhaite développer cette application pour mon iPAQ mais aussi pour mes postes de travail sous Windows XP ainsi que pour Windows CE en version 4 ! Comme je n'ai pas envie de réécrire 15 fois le code, j'ai du organisé quelque peu ma façon de développer. J'ai donc créé trois projets, un pour le CF (répertoire c2iBubbles), l'autre pour une application Windows traditionnelle (répertoire c2iWinBubbles) et le dernier pour Windows CE 4 (répertoire WPBubbles). Certains fichiers seront communs à ces trois projets, je les ai donc placés dans un autre dossier, Common :
Dans chaque projet, j'ai juste une Form principale, Form1, une Form secondaire pour l'affichage des scores, FormHS, des images gif et les fichiers placés dans le répertoire Common. Vous remarquerez que dans l'explorateur de projet de VS .NET, ils sont représentés avec une petite flèche de raccourci en bas à gauche :
Astuce : pour pouvoir ajouter un fichier dans votre projet sans en faire la copie, il faut faire juste une petite manipulation au moment de l'importation dans votre projet. Je dois avouer que jusqu'il y a 2 jours, j'effectuais cette manoeuvre "à la main", c'est-à-dire en éditant le fichier .vbproj avec le bloc-notes. Heureusement, une personne dont j'ai oublié le nom m'a donné cette astuce sur le newsgroup de Miscrosoft sur .NET : Clic droit sur votre projet et choississez "Ajoutez un Item existant". Sélectionnez votre fichier mais au lieu de cliquer sur "Ajouter", cliquez sur la petite flèche placée à droite du bouton et sélectionnez "Lier le fichier". Et voilà, simple et effeicace pour des fichiers partagés comme c'est le cas ici. A noter que malheureusement, vous ne pouvez avoir dans VS .NET des projets Pocket PC et WinXP dans une même solution. Dommage cela m'aurait éviter d'avoir trois instances de VS .NET en même temps. Important : A noter qu'il existe une autre solution plus élégante comme nous le verrons dans un prochain article pour développer sur plusieurs plateformes à la fois un même projet mais je voulais ici pouvoir tester mon application directement sur les trois plateformes.
Form1.vb et FormHS.vb sont les deux forms qui sont spécifiques à chaque plateforme. Les images 0 à 4.gif sont les différentes bulles de couleur. Ce sont des bitmaps de 16*16 pixels avec une couleur de fond blanche qui nous servira de couleur de transparence. Comme ces fichiers sont livrés en tant que tel avec l'application, l'utilisateur peut très bien créer ses propres bulles du moment qu'elles respectent la taille et la couleur de transparence. fond.gif est l'image de fond, ici la lune. De même, en la changeant, vous pouvez placer Cindy Crawford en arrière plan. logo.gif est mon petit logo en haut à droite (on ne le change pas SVP, ca me fait de la pub !). bubbles.gif et ico.ico ne servent à rien pour l'instant (j'ai oublié de les supprimer de la solution). score est un petit bitmap de 16*16 qui est affiché quand on souhaite connaitre le score quand on détruit des bulles (dans la capture plus haut de l'émulateur Pocket PC, c'est la bulle marron ou apparait le score 30). Les autres fichiers, donc ceux avec la flèche de raccourci, contiennent les types de l'application que nous allons décrire de ce pas.
Cell (dans le fichier Tableau.vb) Tout d'abord, chaque cellule est de type Cell (normal quoi) avec les membres suivants :
Col et Row indiquant les numéros de colonne et ligne
de la cellule, Tableau (dans le fichier Tableau.vb) Le Tableau de jeu de type Tableau possédant une propriété principale Cells : c'est un tableau à deux dimensions contenant des Cells :
Nous verrons plus en détail l'ensemble de ses membres plus tard mais regardons tout d'abord son constructeur : Public Sub New(ByVal inColor As Int32, ByVal iTaille As
Int32) _inColor permet de déterminer le nombre de couleur utilisées.
Dans tous mes projets je l'initialise à 5 mais cela laisse la porte ouverte
pour créer des tableaux avec 245 000 couleurs différentes !!!
Bon, le plus simple est de regarder le code en détail ;-) Voici quelques uns des autres membres de ce type :
GameUIManager (dans le fichier GameUIManager.vb) Maintenant, concentrons nous sur le type GameUIManager.
C'est lui qui est au coeur du développement inter-plateforme. Le constructeur de ce type attend comme argument une référence vers un System.Windows.Forms.Form. Dans ce dernier, j'abonne un certain nombre de méthodes aux évènements de la Form : Public Sub New(ByVal frmParent As System.Windows.Forms.Form) Ainsi, quand la form (sur Pocket PC, Win32 ou Win CE) devra être repainte, la méthode frmPaint de mon GameUIManager sera appelée. De même pour le MouseUp et le Closed. Ce qui signifie que dans mes Forms (spécifiques à la plateforme), je n'ai que deux lignes de code et une déclaration : Public Sub New() Ce sont les méthodes du GameUIManager qui gèreront les évènements de ma form. Pourquoi je fais cela ? Tout simplement parce que je laisse la possibilité au designer des applications d'ajouter des contrôles qui peuvent être spécifiques à la plateforme ciblée. L'exemple le plus visible est le menu. Vous verrez que le constructeur utilisé automatiquement par Visual Studio .NET pour un menu Windows est différent de celui pour un Pocket PC. Ensuite, car ce n'est pas fini avec le constructeur du GameUIManager, je crée une instance d'un tableau (il était temps) et je charge dans des objets Bitmaps les différentes images qui seront utilisées pour le fond, les bulles, le logo, etc. Juste une remarque pour le chargement des images : j'utilise pour cela le constructeur du type Bitmap qui attend le nom du fichier. Si vous êtes sous Windows XP & Co, vous obtenez le chemin de l'exécution de l'application simplement avec le code suivant : System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly.Location) Malheureusement sous PocketPC, la propriété Location n'existe pas. Damned, comment faire ? Et bien, c'est possible avec la ligne suivante : System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly.GetName.CodeBase) Mais attendez, là ou cela se corse comme dirait Tino Rossi, c'est que cette dernière ligne ne fonctionne pas sous Windows XP ! Du coup, on est obligé, pour ce type qui, je le rappelle, sera utilisé dans des projets WinXP, PocketPC et WinCE4, d'utiliser la compilation conditionnelle. Il suffit pour cela dans les propriétés du projet d'ajouter une constante personnalisée que j'ai appelée PPC :
Dans mes projets PocketPC et WinCE4, PPC vaudra True mais dans mon projet WinXP, il sera à False. Enfin, pour déterminer mon chemin de l'application, j'aurais le code suivant :
De la bonne compilation conditionnelle comme au bon vieux temps de VB4 avec les Win16 et Win32 !
Une fois que j'ai donc mes bitmaps, il va falloir les afficher ou plus exactement afficher les Cells du Tableau. Le principe est donc de parcourrir l'ensemble des éléments de type Cell de la propriété Cells de mon type Tableau. Pour pouvoir exécuter cela le plus rapidement possible, il n'est pas question de dessiner les bitmaps directement dans la form mais d'utiliser un Bitmap placé en mémoire. C'est le rôle de la fonction PaintOffBitmap. Comme avec DirectX, on fait tout le travail du dessin sur une image en mémoire puis, une fois le travail effectué, on fait une copie de cette image sur notre form. L'évènement Paint de notre form (ou plutôt la procédure frmPaint du GameUIManager appelée par le délégué Paint de la form) ne tient donc qu'en une seule ligne :
Ou _oBitmapOff est le bitmap en mémoire. La procédure PaintOffBitmap, qui dessine sur le _oBitmapOff, est un peu plus compliquée (regardez donc le code à télécharger) mais elle fait juste dans un premier temps une itération sur les Cells du Tableau pour les dessiner puis dessine les cadres des Cells sélectionnées (collection CellsChecked) puis la prévisualisation du score et enfin le score.
On gère donc le clic sur l'écran via la procédure frmMouseUp du GameUIManager, procédure s'étant abonnée à l'évènement de la form. Rien de bien compliqué dans cette procédure puisque l'on transforme dans un premier temps les coordonnées du clic en numéro de ligne et de colonne pour savoir sur quelle Cell on a cliqué. Mais il faut savoir si c'est un clic qui affiche un score ou qui confirme la suppression des bulles. Souvenez-vous, quand j'appele la méthode getScore, je remplie un ArrayList, CellsChecked. Donc, dans le MouseUp, je fais une itération sur l'ensemble des bulles de cette collection :
En revanche, il faut gérer le fait que le tableau est terminé, le fameux GAME OVER. A ce moment, une nouvelle feuille devrait s'afficher avec les scores ou l'enregistrement du HALL OF FAME. Seul problème, cette analyse est effectuée dans notre GameUIManager donc indépendant de l'interface utilisateur, ie la plateforme cible. Moralité, on va délégué le travail à notre form appelante. Ceci explique pourquoi dans la form principale, notre GameUIManager est déclaré avec le mot clé WithEvents : Private WithEvents oGameUIManager As GameUIManager Nous allons donc ajouter un évènement au GameUIManager. Pour des raisons qui ne sont pas obscures mais que je ne dévoilerais pas ici (achetez donc mon livre "Au coeur de VB .NET" chez MS Press), j'ajoute le code suivant :
Du coup, dans la form principale, je peux gérer cet évènement :
La seule chose qu'il faut retenir, c'est que c'est à la form de créer une nouvelle form. Dans le projet WinCE 4 par exemple, j'ai juste décidé d'afficher le score obtenu. Dans les projets Pocket PC et WinXP en revanche, j'ai décidé d'afficher et de stocker un HALL OF FAME. C'est le sujet de cette dernière partie et le rôle du type HighScore : HighScore (fichier HighScore.vb) C'est ce type qui est en charge de gérer le HALL OF FAME. Il possède les propriétés Min et Max qui sont suffisamment explicites pour que je ne vous dise pas ce qu'elles retournent.
IsHighScore indique si l'Int32 passé en argument est un HighScore, c'est-à-dire supérieur à l'un des scores déjà enregistré. Add enfin ajoute un nouveau HighScore avec le nom de la personne qui l'a réalisé. Il enregistre également la date et l'heure de cette performance historique ;-) . Mais justement, je parle d'enregistrement et c'est là ou intervient la sérialisation sous Pocket PC.
Il va falloir donc stocker les meilleurs scores. Ma première idée a donc été de chercher un sérialisateur de type binaire, XML ou, au pire SOAP (dans le genre verbeux...) comme ceux qui existent pour le .NET Framework. Ne cherchez pas comme je l'ai fais : y'en a pas ! C'est d'autant plus bizarre que l'on peut consommer sans problème des services web avec le Compact Framework ! Tant pis, pas de sérialisateur. Deuxième idée, utilisez System.IO et enregistrer mes données dans un fichier au format propriétaire (ici, type texte). Sympa mais je n'avais toujours pas touché à l'espace de noms System.Data et c'était l'occasion de m'y mettre. J'ai donc décidé d'utiliser un DataSet et plus particulièrement ses méthodes ReadXML et WriteXML. Les données sont donc stockées dans un fichier XML de données lu par le DataSet et modifié par ce dernier. C'est pourquoi le constructeur de ce type HighScore attend le nom du fichier.
Du coup, dans la méthode Add, je vérifie dans un premier temps si le score que l'on souhaite ajouté est bel et bien un high score puis et si c'est le cas, je modifie le score le plus bas (c'est-à-dire la DataRow correspondante obtenue avec la méthode privée getMinRow). Je sauvegarde alors le tout avec la méthode WriteXML du DataSet.
Maintenant que notre programme est terminé, il va falloir le distribuer. La première solution consiste simplement à copier les fichiers nécessaires (ie les gif et l'exe) dans un répertoire du Pocket PC pour que cela fonctionne, mais il n'apparaitra pas alors dans la liste des programmes installés. Pour cela, là encore, VS .NET 2003 nous facilité grandement la tâche : un seul clic suffit ! Dans la barre d'outils Device, vous verrez un bouton "Build Cab File". Cliquez dessus et il nous compile alors automatiquement les CAB pour tous les POcket PC possibles (arm, mips et sh3). Simple non ?
Ces codes sont en libre service. Vous pouvez en faire ce que vous voulez, les modifier, les triturer dans tous les sens SAUF : si vous créez une nouvelle version, celle ci doit aussi est libre de droit et devra mentionner le programme d'origine (et un lien vers cet article). Avertissez moi aussi, ça me fera plaisirs ;-) Téléchargement obligatoire du Compact .NET Framework pour Pocket PC ARM, MIPS, SH3 (environ 2 Mo) Installation et exécutable pour ARM (104 Ko) Installation et exécutable pour MIPS (107 Ko) Installation et exécutable pour SH3 (103 Ko) Codes sources pour VS .NET 2003 pour Pocket PC, WinCE 4 et Windows (215Ko)
En quelques heures, ce petit programme a donc pu être développé sans problèmes pour les différentes plateformes. Mais ne vous inquiètez pas, il reste pas mal de choses à voir sur les Pocket PC, ce qui sera l'objet, of course, d'autres articles.
|
|||||||||||||||
|
Copyright 2001-2004 - Tous droits réservés Toutes les autres marques et produits présents dans ces pages sont la propriété exclusive de leurs sociétés respectives. |
|||||||||||||||