Conception du jeu XSimon : PARTIE III

Publié le par Jérémy JANISZEWSKI

Cette troisième partie va s'occuper de créer le jeu sous PC. Grâce à ce qui a été fait précédemment, le jeu sera plus simple à programmer.

Le jeu sera multilingues. Cependant comme ce n'est pas le but de cet article, je n'expliquerais pas comment nous allons le faire, téléchargez juste ces fichiers. Créez un répertoire Languages dans le projet XSimon. Ajoutez-y ensuite les 2 fichiers que vous venez de télécharger.

Maintenant de quoi allons avoir besoin comme variables ?

- Une variable de type GameState permettant de connaitre l'état de jeu.
- Une variable de type AudioManager pour manipuler l'audio.
- Une variable de type ButtonManager pour manipuler les boutons.
- Une variable de type Player pour gérer le joueur.
- 2 variables de type SpriteFont pour afficher les instructions et le score du joueur.
- Une variable de type Color pour changer la couleur de l'arrière-plan.
- Une variable de type StringBuilder pour le rendu de texte.
- Une variable de type float pour contenir le temps écoulé.
- Une variable de type Button pour connaitre le bouton à appuyer.

Cela nous donne :

 private GameState state; private AudioManager audioManager;
private ButtonManager buttonManager; private Player player; private SpriteFont instructionFont; private SpriteFont scoreFont; private readonly Color backgroundColor; private StringBuilder text; private float elapsedTime; private Button buttonToPress;


Vous remarquez que la variable backgroundColor est marquée readonly. Cela signifie qu'une fois la variable définie, elle ne peut plus être changée. Dans le constructeur, nous allons définir les variables backgroundColor et text.

 public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; backgroundColor = new Color(51, 51, 51); text = new StringBuilder(); } 

Maintenant dans notre méthode Initialize, nous allons définir la taille de l'écran de jeu. Sous PC et XBOX360, nous allons fixer cette taille à 720p (1280 x 720), pour le WINDOWS PHONE la taille sera fixé à 480p (800 x 480).

Puis nous ajouterons notre gestionnaire de périphériques à la liste des composants (pour que le gestionnaire de périphériques se mette à jour automatiquement), nous instancierons notre gestionnaire audio, nous positionnerons notre état de jeu à GameInstruction et enfin nous crérons notre joueur et ajouterons le premier bouton à jouer.

 sealed override protected void Initialize() { #if WINDOWS
graphics.PreferredBackBufferWidth = 1280; graphics.PreferredBackBufferHeight = 720; IsMouseVisible = true;
#endif graphics.ApplyChanges(); state = GameState.GameInstruction; Components.Add(new InputManager(this)); audioManager = new AudioManager(this); player = new Player(); player.GenerateNextButton(); base.Initialize(); }

Dans la méthode LoadContent va créer le gestionnaire de boutons, enregistrer son évènement SelectedButton, charger son contenu et enfin charger les 2 spritefonts pour le rendu de texte.

 sealed override protected void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice); buttonManager = new ButtonManager(this, spriteBatch); buttonManager.SelectedButton += new EventHandler<ButtonEventArgs>(buttonManager_SelectedButton); buttonManager.LoadContent(); scoreFont = Content.Load<SpriteFont>("Fonts/scoreFont"); instructionFont = Content.Load<SpriteFont>("Fonts/title"); } 

La méthode UnloadContent va détruire :
- le gestionnaire de boutons.
- le gestionnaire audio.
- les 2 spritefonts.

 sealed override protected void UnloadContent() {  instructionFont = null; scoreFont = null; buttonManager.UnloadContent(); audioManager.UnloadContent(); } 

La méthode buttonManager_SelectedButton va détecter si le bouton à appuyer vaut le bouton qui vient d'être appuyé.

Si ce n'est pas le cas, nous devons passer l'état de jeu à PostGame et jouer le son "Défaite".
Si c'est le cas, on remet à zéro le temps écoulé puis il y'a deux possibilités :
- soit le joueur a terminé sa séquence
- soit le joueur n'a pas terminé sa séquence.

Si le joueur a terminé sa séquence, nous allons :
- augmenter son score de 1.
- ajouter un nouveau bouton dans la séquence.
- passer l'état de jeu à ShowingButton (c'est ça, le système va montrer au joueur la séquence à jouer)
- jouer le son "Succès"

Si le joueur n'a pas terminé sa séquence, nous sélectionnons le prochain bouton à appuyer.

 void buttonManager_SelectedButton(object sender, ButtonEventArgs e) { if (buttonToPress == e.Button) { elapsedTime = 0f; if (player.Count > 0) buttonToPress = buttonManager.GetButtonToPress(player.GetButtonToPress()); else { player.Score++; state = GameState.ShowingButton; player.GenerateNextButton(); AudioManager.PlaySuccess(); } } else { AudioManager.PlayDefeat(); state = GameState.PostGame; } } 

C'est dans la méthode Update que le plus gros du travail se fait. Dans cette méthode, nous allons détecter dans quel état est le jeu :
- S'il est dans l'état GameInstruction alors nous génèrerons le texte à afficher tant qu'un appuie sur Entrée ou sur le bouton A ou sur le bouton Start n'est pas détecté. Lorsqu'il y'a détection de l'une de ces 3 interactions, on passe l'état de jeu à ShowingButton.

Cela donne :

 #if WINDOWS || XBOX360 if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); #endif switch(state) { case GameState.GameInstruction: #if WINDOWS text.Clear(); #endif text.AppendLine(Languages.Lng.FirstInstructionLine); text.AppendLine(Languages.Lng.SecondInstructionLine); #if WINDOWS text.AppendLine(Languages.Lng.ThirdInstructionLinePC); if (InputManager.IsEnterKeyPressed()) state = GameState.ShowingButton; #endif #if WINDOWS text.AppendLine(Languages.Lng.ThirdInstructionLineXBOX360); if (InputManager.IsStartButtonPressed() || InputManager.IsAButtonPressed()) state = GameState.ShowingButton; #endif  break; 

Ensuite dans l'état ShowingButton, nous devons :

- calculer le temps écoulé.
- Si le temps écoulé est de plus de 3/4 de secondes, le gestionnaire de boutons "éteint" tous les boutons "allumés"
- Si le temps écoulé est de plus de 1 seconde, nous devons regarder si la séquence est terminée.
      + Si elle ne l'est pas, le système montre le prochain bouton à appuyer.
      + Si elle l'est, nous devons :
           - remettre à jour le compteur.
           - mettre en place le premier bouton à appuyer.
           - mettre l'état de jeu à Playing.
- Remettre le temps écoulé à 0.

 case GameState.ShowingButton: elapsedTime += (float)gameTime.ElapsedGameTime.TotalMilliseconds; if (elapsedTime >= 750f) buttonManager.UnselectAll(); if (elapsedTime >= 1000f) { if (player.Count > 0) buttonManager.SelectButton(player.GetButtonToPress()); else { player.UpdateCount(); buttonToPress = buttonManager.GetButtonToPress(player.GetButtonToPress()); state = GameState.Playing; } elapsedTime = 0f; } break; 

A l'état playing, nous devons utiliser la même technique pour l'extinction des boutons à ceci près qu'au lieu d'attendre 3 / 4 de secondes, nous n'attendons que 1/2 seconde. Ensuite nous n'avons qu'à appeler la méthode Update du gestionnaire de boutons qui s'occupera à seul de gérer les périphériques.

  case GameState.Playing: elapsedTime += (float)gameTime.ElapsedGameTime.TotalMilliseconds; if (elapsedTime >= 500f) { buttonManager.UnselectAll(); elapsedTime = 0f; } buttonManager.Update(); break; 

Et enfin à l'état PostGame, nous faisons la même chose qu'avec GameInstruction à ceci près que le texte à afficher change et qu'un appuie de touche ramène l'état de jeu à GameInstruction.

  case GameState.PostGame: player.Reset(); #if WINDOWS text.Clear(); #endif text.AppendLine(Languages.Lng.SimonsWins); text.AppendLine(); #if WINDOWS text.AppendLine(Languages.Lng.ThirdInstructionLinePC); if (InputManager.IsEnterKeyPressed()) state = GameState.GameInstruction; #endif #if WINDOWS
text.AppendLine(Languages.Lng.ThirdInstructionLineXBOX360); if (InputManager.IsStartButtonPressed() || InputManager.IsAButtonPressed()) state = GameState.GameInstruction; #endif break; } base.Update(gameTime); }

Et voilà, nous sommes presque à la fin de notre projet (pour PC), nous devons écrire notre méthode Draw. Il nous suffit d'afficher notre texte, notre gestionnaire de boutons et notre score.

Cela nous donne :

  sealed override protected void Draw(GameTime gameTime) { GraphicsDevice.Clear(backgroundColor); spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend); buttonManager.Draw(); switch (state) { case GameState.GameInstruction: spriteBatch.DrawString(instructionFont, text, new Vector2((GraphicsDevice.Viewport.Width - instructionFont.MeasureString(text).X) / 2f, (GraphicsDevice.Viewport.Height - instructionFont.MeasureString(text).Y) / 2f), Color.White); break; case GameState.ShowingButton: case GameState.Playing: spriteBatch.DrawString(scoreFont, "Score ", new Vector2(20, 20), Color.White); string txt = string.Format("{0:000}", player.Score); spriteBatch.DrawString(scoreFont, string.Format("{0:000}", txt), new Vector2(20 + instructionFont.MeasureString("Score ").X + 10, 20), Color.White); break; case GameState.PostGame: spriteBatch.DrawString(instructionFont, text, new Vector2((GraphicsDevice.Viewport.Width - instructionFont.MeasureString(text).X) / 2f, (GraphicsDevice.Viewport.Height - instructionFont.MeasureString(text).Y) / 2f), Color.White); break; } spriteBatch.End(); base.Draw(gameTime); } } } 

Vous remarquerez que les instructions sont centrées au milieu de l'écran de jeu.
Il faut savoir que la méthode GraphicsDevice contient une variable nommée Viewport qui contient la position et la taille de l'écran de jeu. Cette variable est peu utile dans notre cas (nous aurions pu utilisée la variable PreferredBackBufferXXXX) mais lorsque nous verrons comment créer des jeux en écran séparé, la dite variable se révèlera extrêmement interessante.

Et voilà, cet article est maintenant terminé. La prochaine partie vous montrera comment faire pour exporter ce jeu sous XBOX360.

Stay tuned,

@ bientôt sur ce blog

Publié dans XNA

Pour être informé des derniers articles, inscrivez vous :
Commenter cet article