Créer un jeu UWP dans MonoGame 2DCreate a UWP game in MonoGame 2D

Un jeu UWP simple en 2D pour le Microsoft Store, écrit en C# et MonoGameA simple 2D UWP game for the Microsoft Store, written in C# and MonoGame

Feuille de sprite Dino marcheur

IntroductionIntroduction

MonoGame est une infrastructure légère de développement de jeux.MonoGame is a lightweight game development framework. Ce didacticiel vous explique les notions de base du développement de jeux dans MonoGame, notamment comment charger du contenu, dessiner des sprites, les animer et gérer les entrées utilisateur.This tutorial will teach you the basics of game development in MonoGame, including how to load content, draw sprites, animate them, and handle user input. Vous trouverez également des concepts plus avancés, tels que la détection des collisions et la prise en charge des écrans haute résolution.Some more advanced concepts like collision detection and scaling up for high-DPI screens are also discussed. Ce didacticiel dure 30 à 60 minutes.This tutorial takes 30-60 minutes.

Conditions préalablesPrerequisites

  • Windows 10 et Microsoft Visual Studio 2017.Windows 10 and Microsoft Visual Studio 2017. Cliquez ici pour savoir comment prendre en main Visual Studio.Click here to learn how to get set up with Visual Studio.
  • L’infrastructure de développement de bureau .NET.The .NET desktop development framework. Si vous ne l'avez pas encore installé, vous pouvez l’obtenir en réexécutant le programme d’installation de Visual Studio et en modifiant votre installation de Visual Studio 2017.If you don't already have this installed, you can get it by re-running the Visual Studio installer and modifying your installation of Visual Studio 2017.
  • Connaissances de base de C# ou d’un langage de programmation orienté objet similaire.Basic knowledge of C# or a similar object-oriented programming language. Cliquez ici pour savoir comment commencer en C#.Click here to learn how to get started with C#.
  • La connaissance de concepts informatiques élémentaires tels que les classes, les méthodes ou les variables sera un plus.Familiarity with basic computer science concepts like classes, methods, and variables is a plus.

Pourquoi MonoGame ?Why MonoGame?

Le choix ne manque pas en matière d'environnements de développement de jeux.There’s no shortage of options when it comes to game development environments. Entre les moteurs complets comme Unity et les API multimédias exhaustives et complexes telles que DirectX, savoir par où commencer peut s'avérer difficile.From full-featured engines like Unity to comprehensive and complex multimedia APIs like DirectX, it can be hard to know where to start. MonoGame est un ensemble d’outils dont le niveau de complexité se situe entre un moteur de jeu et une API plus fruste comme DirectX.MonoGame is a set of tools, with a level of complexity falling somewhere between a game engine and a grittier API like DirectX. Il fournit un pipeline de contenu facile à utiliser, ainsi que toutes les fonctionnalités requises pour créer des jeux légers qui s’exécutent sur un large éventail de plateformes.It provides an easy-to-use content pipeline, and all the functionality required to create lightweight games that run on a wide variety of platforms. Meilleures de MonoGame all, elles ont été écrites dans pure C#, et vous pouvez les distribuer rapidement via le Microsoft Store ou d’autres plateformes de distribution similaires.Best of all, MonoGame apps are written in pure C#, and you can distribute them quickly via the Microsoft Store or other similar distribution platforms.

Obtenir le codeGet the code

Si vous ne souhaitez pas suivre le didacticiel pas à pas et préférez juste voir MonoGame en action, cliquez ici pour obtenir l’application terminée.If you don’t feel like working through the tutorial step-by-step and just want to see MonoGame in action, click here to get the finished app.

Ouvrez le projet dans Visual Studio 2017, puis appuyez sur F5 pour exécuter l’exemple.Open the project in Visual Studio 2017, and press F5 to run the sample. Cela peut prendre un certain temps la première fois, puisque Visual Studio doit extraire les packages NuGet qui peuvent manquer dans votre installation.The first time you do this may take a while, as Visual Studio needs to fetch any NuGet packages that are missing from your installation.

Si cela est déjà fait, ignorez la section suivante sur la configuration de MonoGame pour passer directement à une explication pas à pas du code.If you’ve done this, skip the next section about setting up MonoGame to see a step-by-step walkthrough of the code.

Remarque : Le jeu créé dans cet exemple n’est pas censé être complète (ou les amusants du tout).Note: The game created in this sample is not meant to be complete (or any fun at all). Son seul but est de montrer tous les principaux concepts du développement 2D dans MonoGame.Its only purpose is to demonstrate all the core concepts of 2D development in MonoGame. N’hésitez pas à utiliser ce code pour créer quelque chose de plus intéressant ou même repartir de zéro lorsque vous maîtriserez les concepts de base !Feel free to use this code and make something much better—or just start from scratch after you’ve mastered the basics!

Configuration du projet MonoGameSet up MonoGame project

  1. Installer MonoGame 3.6 pour Visual Studio à partir de MonoGame.netInstall MonoGame 3.6 for Visual Studio from MonoGame.net

  2. Démarrez Visual Studio 2017.Start Visual Studio 2017.

  3. Accédez à Fichier -> Nouveau -> ProjetGo to File -> New -> Project

  4. Sous les modèles de projet Visual C#, sélectionnez MonoGame et Projet MonoGame Universal Windows 10Under the Visual C# project templates, select MonoGame and MonoGame Windows 10 Universal Project

  5. Nommez votre projet « MonoGame2D » et sélectionnez OK.Name your project “MonoGame2D" and select OK. Une fois créé, le projet aura probablement l'air truffé d'erreurs. Celles-ci devraient disparaître lorsque vous aurez exécuté le projet pour la première fois et que tous les packages NuGet manquants auront été installés.With the project created, it will probably look like it is full of errors—these should go away after you run the project for the first time, and any missing NuGet packages are installed.

  6. Assurez-vous que x86 et Local Machine sont définis comme plateforme cible, puis appuyez sur F5 pour générer et exécuter le projet vide.Make sure x86 and Local Machine are set as the target platform, and press F5 to build and run the empty project. Si vous avez suivi les étapes ci-dessus, vous devez voir apparaître une fenêtre bleue vide une fois que le projet a achevé la génération.If you followed the steps above, you should see an empty blue window after the project finishes building.

Vue d’ensemble de la méthodeMethod overview

Maintenant que vous avez créé le projet, ouvrez le fichier Game1.cs depuis Explorateur de solutions.Now you’ve created the project, open the Game1.cs file from the Solution Explorer. C'est là qu'ira la majeure partie de la logique du jeu.This is where the bulk of the game logic is going to go. De nombreuses méthodes cruciales sont générées automatiquement ici lorsque vous créez un nouveau projet MonoGame.Many crucial methods are automatically generated here when you create a new MonoGame project. Passons-les rapidement en revue :Let’s quickly review them:

public Game1() Le constructeur.public Game1() The constructor. Nous ne modifierons pas du tout cette méthode dans ce didacticiel.We aren’t going to change this method at all for this tutorial.

protected override void Initialize() Ici, nous initialisons toutes les variables de classe utilisées.protected override void Initialize() Here we initialize any class variables that are used. Cette méthode est appelée une fois au début du jeu.This method is called once at the start of the game.

protected override void LoadContent() Cette méthode charge le contenu (par ex.protected override void LoadContent() This method loads content (eg. textures, sons, polices) dans la mémoire avant le démarrage du jeu.textures, audio, fonts) into memory before the game starts. Comme Initialize, elle est appelée une fois lorsque l’application démarre.Like Initialize, it’s called once when the app starts.

protected override void UnloadContent() Cette méthode est utilisée pour décharger le contenu autre que celui du Gestionnaire de contenu.protected override void UnloadContent() This method is used to unload non content-manager content. Nous ne l’utilisons pas du tout.We don’t use this one at all.

protected override void mise à jour (GameTime gameTime) cette méthode est appelée une fois pour chaque cycle de la boucle du jeu.protected override void Update(GameTime gameTime) This method is called once for every cycle of the game loop. Ici, nous mettons à jour les états de n’importe quel objet ou de n’importe quelle variable utilisée dans le jeu.Here we update the states of any object or variable used in the game. Cela inclut des éléments tels que la position d’un objet, sa vitesse ou sa couleur.This includes things like an object’s position, speed, or color. Il s’agit également où l’entrée d’utilisateur est gérée.This is also where user input is handled. Bref, cette méthode traite chaque partie de la logique du jeu à l'exception du dessin des objets à l’écran.In short, this method handles every part of the game logic except drawing objects on screen.

protected override void Draw(GameTime gameTime) C'est là que les objets sont dessinés sur l’écran à l’aide des positions données par la méthode Update.protected override void Draw(GameTime gameTime) This is where objects are drawn on the screen, using the positions given by the Update method.

Dessin d'un spriteDraw a sprite

Vous avez donc exécuté votre projet MonoGame tout neuf et trouvé un joli ciel bleu. Ajoutons-y un sol.So you’ve run your fresh MonoGame project and found a nice blue sky—let’s add some ground. Dans MonoGame, les graphismes 2D sont ajoutés à l’application sous forme de « sprites ».In MonoGame, 2D art is added to the app in the form of “sprites.” Un sprite est tout simplement un élément d'infographie que l'on manipule comme s'il s'agissait d'une seule entité.A sprite is just a computer graphic that is manipulated as a single entity. Les sprites peuvent être déplacés, mis à l’échelle, déformés, animés et combinés pour créer tout ce que vous pouvez imaginer dans l’espace 2D.Sprites can be moved, scaled, shaped, animated, and combined to create anything you can imagine in the 2D space.

1. Télécharger une texture1. Download a texture

Dans notre cas, ce premier sprite va être parfaitement ennuyeux.For our purposes, this first sprite is going to be extremely boring. Cliquez ici pour télécharger ce rectangle vert indifférencié.Click here to download this featureless green rectangle.

2. Ajoutez la texture dans le dossier de contenu2. Add the texture to the Content folder

  • Ouvrez l'Explorateur de solutionsOpen the Solution Explorer
  • Cliquez avec le bouton droit sur Content.mgcb dans le dossier Contenu et sélectionnez Ouvrir avec.Right click Content.mgcb in the Content folder and select Open With. Dans le menu contextuel, sélectionnez Pipeline Monogame, puis OK.From the popup menu select Monogame Pipeline, and select OK.
  • Dans la nouvelle fenêtre, cliquez avec le bouton droit sur l’élément Contenu et sélectionnez Ajouter -> Élément existant.In the new window, Right-Click the Content item and select Add -> Existing Item.
  • Recherchez et sélectionnez le rectangle vert dans l’Explorateur de fichiers.Locate and select the green rectangle in the file browser.
  • Nommez l’élément « grass.png » et sélectionnez Ajouter.Name the item “grass.png” and select Add.

3. Ajouter des variables de classe3. Add class variables

Pour charger cette image en tant que texture de sprite, ouvrez Game1.cs et ajoutez les variables de classe suivantes.To load this image as a sprite texture, open Game1.cs and add the following class variables.

const float SKYRATIO = 2f/3f;
float screenWidth;
float screenHeight;
Texture2D grass;

La variable SKYRATIO nous indique quelle part de la scène nous voulons accorder au ciel par rapport à l’herbe : ici, les deux tiers.The SKYRATIO variable tells us how much of the scene we want to be sky versus grass—in this case, two-thirds. screenWidth et screenHeight assureront le suivi de la taille de la fenêtre de l’application, et grass est l'endroit où nous stockerons notre rectangle vert.screenWidth and screenHeight will keep track of the app window size, while grass is where we’ll store our green rectangle.

4. Initialiser des variables de classe et définissez la taille de la fenêtre4. Initialize class variables and set window size

Les variables screenWidth et screenHeight doivent encore être initialisées. Ajoutez ce code à la méthode Initialize :The screenWidth and screenHeight variables still need to be initialized, so add this code to the Initialize method:

ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.FullScreen;

screenHeight = (float)ApplicationView.GetForCurrentView().VisibleBounds.Height;
screenWidth = (float)ApplicationView.GetForCurrentView().VisibleBounds.Width;

this.IsMouseVisible = false;

Outre la hauteur et la largeur de l’écran, nous réglons également le mode de fenêtrage de l’application sur Fullscreenet nous rendons la souris invisible.Along with getting the screen’s height and width, we also set the app’s windowing mode to Fullscreen, and make the mouse invisible.

5. Chargez la texture5. Load the texture

Pour charger la texture dans la variable d’herbe, ajoutez le code suivant à la méthode LoadContent :To load the texture into the grass variable, add the following to the LoadContent method:

grass = Content.Load<Texture2D>("grass");

6. Dessiner le sprite6. Draw the sprite

Pour dessiner le rectangle, ajoutez les lignes suivantes à la méthode Draw :To draw the rectangle, add the following lines to the Draw method:

GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.Draw(grass, new Rectangle(0, (int)(screenHeight * SKYRATIO),
  (int)screenWidth, (int)screenHeight), Color.White);
spriteBatch.End();

Ici, nous utilisons la méthode spriteBatch.Draw pour placer la texture donnée dans les limites d’un objet Rectangle.Here we use the spriteBatch.Draw method to place the given texture within the borders of a Rectangle object. Un Rectangle est défini par les coordonnées x et y de ses angles supérieur gauche et inférieur droit.A Rectangle is defined by the x and y coordinates of its top left and bottom right corner. À l’aide des variables screenWidth, screenHeight et SKYRATIO que nous avons définies précédemment, nous dessinons la texture du rectangle sur le tiers inférieur de l’écran.Using the screenWidth, screenHeight, and SKYRATIO variables we defined earlier, we draw the green rectangle texture across the bottom one-third of the screen. Si vous exécutez le programme maintenant, vous devriez voir l’arrière-plan bleu précédent partiellement recouvert par le rectangle vert.If you run the program now you should see the blue background from before, partially covered by the green rectangle.

Rectangle vert

Adaptation à des écrans haute résolutionScale to high DPI screens

Si vous utilisez Visual Studio sur un moniteur à haute densité de pixels, comme celui des Surface Pro ou Surface Studio, vous pouvez constater que le rectangle vert des étapes ci-dessus ne recouvre pas tout à fait le tiers inférieur de l’écran.If you’re running Visual Studio on a high pixel-density monitor, like those found on a Surface Pro or Surface Studio, you may find that the green rectangle from the steps above doesn’t quite cover the bottom third of the screen. Il flotte probablement au-dessus de l’angle inférieur gauche de l’écran.It’s probably floating above the bottom-left corner of the screen. Pour résoudre ce problème et unifier l’apparence de notre jeu sur tous les appareils, nous allons devoir créer une méthode qui fait évoluer certaines valeurs en fonction de la densité de pixels de l’écran :To fix this and unify the experience of our game across all devices, we will need to create a method that scales certain values relative to the screen’s pixel density:

public float ScaleToHighDPI(float f)
{
  DisplayInformation d = DisplayInformation.GetForCurrentView();
  f *= (float)d.RawPixelsPerViewPixel;
  return f;
}

Remplacez ensuite les initialisations de screenHeight et screenWidth dans la méthode Initialize par ce qui suit :Next replace the initializations of screenHeight and screenWidth in the Initialize method with this:

screenHeight = ScaleToHighDPI((float)ApplicationView.GetForCurrentView().VisibleBounds.Height);
screenWidth = ScaleToHighDPI((float)ApplicationView.GetForCurrentView().VisibleBounds.Width);

Si vous utilisez un écran à fort taux de PPP et que vous essayez d’exécuter l’application maintenant, vous devriez voir le rectangle vert recouvrir le tiers inférieur de l’écran, comme prévu.If you’re using a high DPI screen and try to run the app now, you should see the green rectangle covering the bottom third of the screen as intended.

Générer la SpriteClassBuild the SpriteClass

Avant de commencer à animer les sprites, nous allons créer une nouvelle classe appelée « SpriteClass » qui nous permettra de simplifier la manipulation des sprites au niveau de la surface.Before we start animating sprites, we’re going to make a new class called “SpriteClass,” which will let us reduce the surface-level complexity of sprite manipulation.

1. Créer une nouvelle classe1. Create a new class

Dans l'Explorateur de solutions, cliquez avec le bouton droit sur MonoGame2D (Windows universel) et sélectionnez Ajouter -> Classe.In the Solution Explorer, right-click MonoGame2D (Universal Windows) and select Add -> Class. Nommez la classe « SpriteClass.cs », puis sélectionnez Ajouter.Name the class “SpriteClass.cs” then select Add.

2. Ajouter des variables de classe2. Add class variables

Ajoutez ce code à la classe que vous venez de créer :Add this code to the class you just created:

public Texture2D texture
{
  get;
}

public float x
{
  get;
  set;
}

public float y
{
  get;
  set;
}

public float angle
{
  get;
  set;
}

public float dX
{
  get;
  set;
}

public float dY
{
  get;
  set;
}

public float dA
{
  get;
  set;
}

public float scale
{
  get;
  set;
}

Ici, nous allons configurer les variables de classe dont nous avons besoin pour dessiner et animer un sprite.Here we set up the class variables we need to draw and animate a sprite. Les variables x et y représentent la position actuelle du sprite sur le plan, tandis que la variable angle est l'angle actuel du sprite en degrés (0 étant vertical et 90 représentant une inclinaison de 90 degrés vers la droite).The x and y variables represent the sprite’s current position on the plane, while the angle variable is the sprite’s current angle in degrees (0 being upright, 90 being tilted 90 degrees clockwise). Il est important de noter que, pour cette classe, x et y représentent les coordonnées du centre du sprite (l’origine par défaut est le coin supérieur gauche).It’s important to note that, for this class, x and y represent the coordinates of the center of the sprite, (the default origin is the top-left corner). Cela facilite la rotation des sprites, lesquels pivoteront autour de l’origine indiquée et sachant qu'une rotation autour du centre nous donne un mouvement de rotation uniforme.This is makes rotating sprites easier, as they will rotate around whatever origin they are given, and rotating around the center gives us a uniform spinning motion.

Après cela, nous avons dX, dY et dA, qui sont les taux respectifs de changements par seconde des variables x, y et angle.After this, we have dX, dY, and dA, which are the per-second rates of change for the x, y, and angle variables respectively.

3. Créez un constructeur3. Create a constructor

Lors de la création d’une instance de SpriteClass, nous fournissons le constructeur avec le périphérique graphique de Game1.cs, le chemin d’accès à la texture par rapport au dossier du projet et l’échelle désirée de la texture par rapport à sa taille d’origine.When creating an instance of SpriteClass, we provide the constructor with the graphics device from Game1.cs, the path to the texture relative to the project folder, and the desired scale of the texture relative to its original size. Nous définirons le reste des variables de classe une fois que nous aurons démarré le jeu, dans la méthode de mise à jour.We’ll set the rest of the class variables after we start the game, in the update method.

public SpriteClass (GraphicsDevice graphicsDevice, string textureName, float scale)
{
  this.scale = scale;
  if (texture == null)
  {
    using (var stream = TitleContainer.OpenStream(textureName))
    {
      texture = Texture2D.FromStream(graphicsDevice, stream);
    }
  }
}

4. Update et Draw4. Update and Draw

Nous devons encore ajouter une ou deux méthodes à la déclaration SpriteClass :There are still a couple of methods we need to add to the SpriteClass declaration:

public void Update (float elapsedTime)
{
  this.x += this.dX * elapsedTime;
  this.y += this.dY * elapsedTime;
  this.angle += this.dA * elapsedTime;
}

public void Draw (SpriteBatch spriteBatch)
{
  Vector2 spritePosition = new Vector2(this.x, this.y);
  spriteBatch.Draw(texture, spritePosition, null, Color.White, this.angle, new Vector2(texture.Width/2, texture.Height/2), new Vector2(scale, scale), SpriteEffects.None, 0f);
}

La méthode SpriteClass Update est appelée dans la méthode Update de Game1.cs et sert à mettre à jour les valeurs de sprites x, y et angle en fonction de leurs taux de modification respectifs.The Update SpriteClass method is called in the Update method of Game1.cs, and is used to update the sprites x, y, and angle values based on their respective rates of change.

La méthode Draw est appelée dans la méthode Draw de Game1.cs et sert à dessiner le sprite dans la fenêtre de jeu.The Draw method is called in the Draw method of Game1.cs, and is used to draw the sprite in the game window.

Entrées de l’utilisateur et animationUser input and animation

Maintenant que la SpriteClass est créée, nous allons l’utiliser pour créer deux nouveaux objets du jeu. Le premier est un avatar que le joueur peut contrôler avec les touches de direction et la barre d’espace.Now we have the SpriteClass built, we’ll use it to create two new game objects, The first is an avatar that the player can control with the arrow keys and the space bar. Le second est un objet qui le joueur doit éviter.The second is an object that the player must avoid.

1. Obtenir les textures1. Get the textures

Pour l’avatar du joueur, nous allons utiliser le Chat ninja de Microsoft lui-même, chevauchant son fidèle T-Rex.For the player’s avatar we’re going to use Microsoft’s very own ninja cat, riding on his trusty t-rex. Cliquez ici pour télécharger l’image.Click here to download the image.

Occupons-nous maintenant de l’obstacle que le joueur doit éviter.Now for the obstacle that the player needs to avoid. Qu'est-ce que les chats ninjas et les dinosaures carnivores détestent plus que tout ?What do ninja-cats and carnivorous dinosaurs both hate more than anything? Manger des légumes !Eating their veggies! Cliquez ici pour télécharger l’image.Click here to download the image.

Exactement comme pour le rectangle vert, ajoutez ces images à Content.mgcb via le Pipeline MonoGame et appelez-les respectivement « ninja-cat-dino.png » et « broccoli.png ».Just as before with the green rectangle, add these images to Content.mgcb via the MonoGame Pipeline, naming them “ninja-cat-dino.png” and “broccoli.png” respectively.

2. Ajouter des variables de classe2. Add class variables

Ajoutez le code suivant à la liste des variables de classe dans Game1.cs :Add the following code to the list of class variables in Game1.cs:

SpriteClass dino;
SpriteClass broccoli;

bool spaceDown;
bool gameStarted;

float broccoliSpeedMultiplier;
float gravitySpeed;
float dinoSpeedX;
float dinoJumpY;
float score;

Random random;

dino et broccoli sont les variables de notre SpriteClass.dino and broccoli are our SpriteClass variables. dino contiendra l’avatar du joueur, tandis que broccoli contiendra l’obstacle brocoli.dino will hold the player avatar, while broccoli holds the broccoli obstacle.

spaceDown suit la position de la barre d’espace pour déterminer si elle maintenue enfoncée ou enfoncée, puis relâchée.spaceDown keeps track of whether the spacebar is being held down as opposed to pressed and released.

gameStarted nous prévient si c'est la première fois que l’utilisateur a démarré le jeu.gameStarted tells us whether the user has started the game for the first time.

broccoliSpeedMultiplier détermine la vitesse de déplacement de l’obstacle brocoli sur l’écran.broccoliSpeedMultiplier determines how fast the broccoli obstacle moves across the screen.

gravitySpeed détermine la vitesse à laquelle l’avatar du joueur accélère vers le bas après un saut.gravitySpeed determines how fast the player avatar accelerates downward after a jump.

dinoSpeedX et dinoJumpY déterminent la vitesse avec laquelle l’avatar du joueur se déplace et saute.dinoSpeedX and dinoJumpY determine how fast the player avatar moves and jumps. score compte les obstacles que le joueur a correctement évités.score tracks how many obstacles the player has successfully dodged.

Enfin, random servira à ajouter une dose de hasard au comportement de l’obstacle brocoli.Finally, random will be used to add some randomness to the behavior of the broccoli obstacle.

3. Initialiser des variables3. Initialize variables

Nous devons ensuite initialiser ces variables.Next we need to initialize these variables. Ajoutez le code suivant à la méthode :Add the following code to the Initialize method:

broccoliSpeedMultiplier = 0.5f;
spaceDown = false;
gameStarted = false;
score = 0;
random = new Random();
dinoSpeedX = ScaleToHighDPI(1000f);
dinoJumpY = ScaleToHighDPI(-1200f);
gravitySpeed = ScaleToHighDPI(30f);

Notez que les trois dernières variables doivent être mises à l’échelle pour les périphériques haute résolution, car ils spécifient un taux de changement en pixels.Note that the last three variables need to be scaled for high DPI devices, because they specify a rate of change in pixels.

4. Construction SpriteClasses4. Construct SpriteClasses

Nous allons construire des objets SpriteClass dans la méthode LoadContent.We will construct SpriteClass objects in the LoadContent method. Ajoutez ce code à ce que vous avez déjà ici :Add this code to what you already have there:

dino = new SpriteClass(GraphicsDevice, "Content/ninja-cat-dino.png", ScaleToHighDPI(1f));
broccoli = new SpriteClass(GraphicsDevice, "Content/broccoli.png", ScaleToHighDPI(0.2f));

La taille de l’image du brocoli est nettement plus grande que celle que nous voulons lui donner dans le jeu. Nous allons donc la ramener à 0,2 fois sa taille d’origine.The broccoli image is quite a lot larger than we want it to appear in the game, so we’ll scale it down to 0.2 times its original size.

5. Comportement d’obstacle de programme5. Program obstacle behaviour

Nous voulons que le brocoli soit généré quelque part hors de l'écran et se dirige dans la direction de l’avatar du joueur, qui doit alors les éviter.We want the broccoli to spawn somewhere offscreen, and head in the direction of the player’s avatar, so they need to dodge it. Pour ce faire, ajoutez cette méthode à la Game1.cs classe :To accomplish this, add this method to the Game1.cs class:

public void SpawnBroccoli()
{
  int direction = random.Next(1, 5);
  switch (direction)
  {
    case 1:
      broccoli.x = -100;
      broccoli.y = random.Next(0, (int)screenHeight);
      break;
    case 2:
      broccoli.y = -100;
      broccoli.x = random.Next(0, (int)screenWidth);
      break;
    case 3:
      broccoli.x = screenWidth + 100;
      broccoli.y = random.Next(0, (int)screenHeight);
      break;
    case 4:
      broccoli.y = screenHeight + 100;
      broccoli.x = random.Next(0, (int)screenWidth);
      break;
  }

  if (score % 5 == 0) broccoliSpeedMultiplier += 0.2f;

  broccoli.dX = (dino.x - broccoli.x) * broccoliSpeedMultiplier;
  broccoli.dY = (dino.y - broccoli.y) * broccoliSpeedMultiplier;
  broccoli.dA = 7f;
}

La première partie de la méthode détermine le point de l'écran où sera généré l’objet brocoli, en utilisant pour cela deux nombres aléatoires.The first part of the of the method determines what off screen point the broccoli object will spawn from, using two random numbers.

La deuxième partie détermine la vitesse à laquelle le brocoli se déplace, ce qui est déterminé par le score du moment.The second part determines how fast the broccoli will travel, which is determined by the current score. Il accélérera chaque fois que le joueur aura réussi à en éviter cinq.It will get faster for every five broccoli the player successfully dodges.

La troisième partie définit la direction du mouvement du sprite brocoli.The third part sets the direction of the broccoli sprite’s motion. Il pointe dans la direction de l’avatar du joueur (dino) lorsque le brocoli est généré.It heads in the direction of the player avatar (dino) when the broccoli is spawned. Nous lui attribuons également une valeur dA de 7f qui fait tournoyer le brocoli dans les airs en poursuivant le joueur.We also give it a dA value of 7f, which will cause the broccoli to spin through the air as it chases the player.

6. État de départ du programme game6. Program game starting state

Avant de pouvoir passer à la gestion des entrées clavier, nous avons besoin d’une méthode qui définit l’état de jeu initial des deux objets que nous avons créés.Before we can move on to handling keyboard input, we need a method that sets the initial game state of the two objects we’ve created. Plutôt que le jeu démarre dès que l’application s’exécute, nous voulons que l’utilisateur le démarre manuellement en appuyant sur la barre d’espace.Rather than the game starting as soon as the app runs, we want the user to start it manually, by pressing the spacebar. Ajoutez le code suivant, qui définit l’état initial des objets animés et réinitialise le score :Add the following code, which sets the initial state of the animated objects, and resets the score:

public void StartGame()
{
  dino.x = screenWidth / 2;
  dino.y = screenHeight * SKYRATIO;
  broccoliSpeedMultiplier = 0.5f;
  SpawnBroccoli();  
  score = 0;
}

7. Gérer l’entrée clavier7. Handle keyboard input

Ensuite, nous avons besoin d'une nouvelle méthode pour traiter les entrées de l'utilisateur via le clavier.Next we need a new method to handle user input via the keyboard. Ajoutez cette méthode à Game1.cs:Add this method to Game1.cs:

void KeyboardHandler()
{
  KeyboardState state = Keyboard.GetState();

  // Quit the game if Escape is pressed.
  if (state.IsKeyDown(Keys.Escape))
  {
    Exit();
  }

  // Start the game if Space is pressed.
  if (!gameStarted)
  {
    if (state.IsKeyDown(Keys.Space))
    {
      StartGame();
      gameStarted = true;
      spaceDown = true;
      gameOver = false;
    }
    return;
  }            
  // Jump if Space is pressed
  if (state.IsKeyDown(Keys.Space) || state.IsKeyDown(Keys.Up))
  {
    // Jump if the Space is pressed but not held and the dino is on the floor
    if (!spaceDown && dino.y >= screenHeight * SKYRATIO - 1) dino.dY = dinoJumpY;

    spaceDown = true;
  }
  else spaceDown = false;

  // Handle left and right
  if (state.IsKeyDown(Keys.Left)) dino.dX = dinoSpeedX * -1;

  else if (state.IsKeyDown(Keys.Right)) dino.dX = dinoSpeedX;
  else dino.dX = 0;
}

Au-dessus, nous avons une série de quatre instructions si :Above we have a series of four if-statements:

La première fait quitter le jeu si la touche Échappement est enfoncée.The first quits the game if the Escape key is pressed.

La seconde démarre le jeu si la touche Espace est enfoncée et si le jeu n’a pas déjà démarré.The second starts the game if the Space key is pressed, and the game is not already started.

La troisième fait sauter l’avatar dino si Espace est enfoncé, en modifiant sa propriété dY.The third makes the dino avatar jump if Space is pressed, by changing its dY property. Notez que le lecteur ne peut pas sauter, sauf si elles se trouvent sur « zéro » (dino.y = caractéristiques * SKYRATIO) et également pas accédera si la touche espace est enfoncée au lieu d’une fois appuyée.Note that the player cannot jump unless they are on the “ground” (dino.y = screenHeight * SKYRATIO), and will also not jump if the space key is being held down rather than pressed once. Cela empêche le dino de sauter dès que le jeu démarre, puisqu'il utilise la même touche que celle qui démarre le jeu.This stops the dino from jumping as soon as the game is started, piggybacking on the same keypress that starts the game.

Enfin, la dernière clause si/alors vérifie si les flèches directionnelles gauche ou droite sont enfoncées. Si tel est le cas, elle modifie la propriété dX du dino en conséquence.Finally, the last if/else clause checks if the left or right directional arrows are being pressed, and if so changes the dino’s dX property accordingly.

Défi : pouvez-vous faire fonctionner la méthode ci-dessus de gestion par le clavier avec le schéma d’entrée WASD, ainsi qu'avec les touches fléchées ?Challenge: can you make the keyboard handling method above work with the WASD input scheme as well as the arrow keys?

8. Ajouter une logique à la méthode de mise à jour8. Add logic to the Update method

Nous devons ensuite ajouter une logique pour toutes ces parties à la méthode Update dans Game1.cs :Next we need to add logic for all of these parts to the Update method in Game1.cs:

float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
KeyboardHandler(); // Handle keyboard input
// Update animated SpriteClass objects based on their current rates of change
dino.Update(elapsedTime);
broccoli.Update(elapsedTime);

// Accelerate the dino downward each frame to simulate gravity.
dino.dY += gravitySpeed;

// Set game floor so the player does not fall through it
if (dino.y > screenHeight * SKYRATIO)
{
  dino.dY = 0;
  dino.y = screenHeight * SKYRATIO;
}

// Set game edges to prevent the player from moving offscreen
if (dino.x > screenWidth - dino.texture.Width/2)
{
  dino.x = screenWidth - dino.texture.Width/2;
  dino.dX = 0;
}
if (dino.x < 0 + dino.texture.Width/2)
{
  dino.x = 0 + dino.texture.Width/2;
  dino.dX = 0;
}

// If the broccoli goes offscreen, spawn a new one and iterate the score
if (broccoli.y > screenHeight+100 || broccoli.y < -100 || broccoli.x > screenWidth+100 || broccoli.x < -100)
{
  SpawnBroccoli();
  score++;
}

9. Dessiner des objets de SpriteClass9. Draw SpriteClass objects

Enfin, ajoutez le code suivant à la méthode Draw de Game1.cs, juste après le dernier appel de spriteBatch.Draw :Finally, add the following code to the Draw method of Game1.cs, just after the last call of spriteBatch.Draw:

broccoli.Draw(spriteBatch);
dino.Draw(spriteBatch);

Dans MonoGame, les nouveaux appels à spriteBatch.Draw dessineront par-dessus tous les appels antérieurs.In MonoGame, new calls of spriteBatch.Draw will draw over any prior calls. Cela signifie que le Brocolis et le sprite de dino seront dessinés sur le sprite grass existant, afin qu’ils ne peuvent jamais masqués derrière lui, quel que soit leur position.This means that both the broccoli and the dino sprite will be drawn over the existing grass sprite, so they can never be hidden behind it regardless of their position.

Essayez maintenant d’exécuter le jeu et de déplacer le dino avec les touches de direction et la barre d’espace.Try running the game now, and moving around the dino with the arrow keys and the spacebar. Si vous avez suivi les étapes ci-dessus, vous devez être en mesure d’apporter votre avatar se déplacent au sein de la fenêtre du jeu et le Brocolis doit générer dynamiquement à une vitesse sans cesse croissante.If you followed the steps above, you should be able to make your avatar move within the game window, and the broccoli should spawn at an ever-increasing speed.

Obstacle et avatar du joueur

Rendu de texte avec SpriteFontRender text with SpriteFont

En utilisant le code ci-dessus, nous suivons le score du joueur en arrière-plan, mais nous ne l'indiquons en réalité pas au joueur.Using the code above, we keep track of the player’s score behind the scenes, but we don’t actually tell the player what it is. Nous avons également une introduction relativement peu intuitive au démarrage de l’application : le joueur voit une fenêtre bleue et verte, mais n’a aucun moyen de savoir qu'il doit appuyer sur espace pour démarrer le jeu.We also have a fairly unintuitive introduction when the app starts up—the player sees a blue and green window, but has no way of knowing they need to press Space to get things rolling.

Pour résoudre ces deux problèmes, nous allons utiliser un nouveau type d’objet MonoGame appelé SpriteFonts.To fix both these problems, we’re going to use a new kind of MonoGame object called SpriteFonts.

1. Créer des fichiers de description SpriteFont1. Create SpriteFont description files

Dans l'Explorateur de solutions, trouvez le dossier Contenu.In the Solution Explorer find the Content folder. Dans ce dossier, cliquez avec le bouton droit sur le fichier Content.mgcb et sélectionnez Ouvrir avec.In this folder, Right-Click the Content.mgcb file and select Open With. Dans le menu contextuel, sélectionnez Pipeline MonoGame, puis appuyez sur OK.From the popup menu select MonoGame Pipeline, then press OK. Dans la nouvelle fenêtre, cliquez avec le bouton droit sur l’élément Contenu et sélectionnez Ajouter -> Nouvel élément.In the new window, Right-Click the Content item and select Add -> New Item. Sélectionnez Description SpriteFont, nommez-le « Score » et appuyez sur OK.Select SpriteFont Description, name it “Score” and press OK. Ajoutez ensuite une autre description SpriteFont nommée « GameState » à l’aide de la même procédure.Then, add another SpriteFont description named “GameState” using the same procedure.

2. Modifier les descriptions2. Edit descriptions

Cliquez avec le bouton droit sur le dossier Contenu dans le Pipeline MonoGame et sélectionnez Ouvrir l’emplacement du fichier.Right click the Content folder in the MonoGame Pipeline and select Open File Location. Vous devriez voir un dossier contenant les fichiers de description SpriteFont que vous venez de créer, ainsi que toutes les images que vous avez ajoutées jusqu'ici au dossier Contenu.You should see a folder with the SpriteFont description files that you just created, as well as any images you’ve added to the Content folder so far. Vous pouvez maintenant fermer et enregistrer la fenêtre Pipeline MonoGame.You can now close and save the MonoGame Pipeline window. Depuis l'Explorateur de fichiers, ouvrez les deux fichiers de description dans un éditeur de texte (Visual Studio, NotePad ++, Atom, etc.).From the File Explorer open both description files in a text editor (Visual Studio, NotePad++, Atom, etc).

Chaque description contient un certain nombre de valeurs qui décrivent le SpriteFont.Each description contains a number of values that describe the SpriteFont. Nous allons apporter quelques modifications :We're going to make a few changes:

Dans Score.spritefont, modifiez la valeur de 12 à 36.In Score.spritefont, change the value from 12 to 36.

Dans GameState.spritefont, modifiez la valeur de 12 à 72 et la valeur d'Arial à Agency.In GameState.spritefont, change the value from 12 to 72, and the value from Arial to Agency. Agency est une autre police livrée en standard avec les ordinateurs Windows 10. Elle ajoute une certaine élégance à notre écran de présentation.Agency is another font that comes standard with Windows 10 machines, and will add some flair to our intro screen.

3. SpriteFonts de charge3. Load SpriteFonts

De retour dans Visual Studio, nous allons tout d’abord ajouter une nouvelle texture pour l’écran de présentation de Microsoft au démarrage.Back in Visual Studio, we’re first going to add a new texture for the intro splash screen. Cliquez ici pour télécharger l’image.Click here to download the image.

Comme précédemment, ajoutez la texture au projet en cliquant avec le bouton droit sur le Contenu et en sélectionnant Ajouter -> Élément existant.As before, add the texture to the project by right-clicking the Content and selecting Add -> Existing Item. Nommez le nouvel élément « start-splash.png ».Name the new item “start-splash.png”.

Ensuite, ajoutez les variables de classe suivantes à Game1.cs :Next, add the following class variables to Game1.cs:

Texture2D startGameSplash;
SpriteFont scoreFont;
SpriteFont stateFont;

Ajoutez ensuite ces lignes à la méthode LoadContent :Then add these lines to the LoadContent method:

startGameSplash = Content.Load<Texture2D>("start-splash");
scoreFont = Content.Load<SpriteFont>("Score");
stateFont = Content.Load<SpriteFont>("GameState");

4. Dessiner le score4. Draw the score

Accédez à la méthode Draw de Game1.cs et ajoutez le code suivant juste avant spriteBatch.End() ;Go to the Draw method of Game1.cs and add the following code just before spriteBatch.End();

spriteBatch.DrawString(scoreFont, score.ToString(),
new Vector2(screenWidth - 100, 50), Color.Black);

Le code ci-dessus utilise la description de sprite que nous avons créée (Arial taille 36) pour tirer le score actuel du joueur vers le coin supérieur droit de l’écran.The code above uses the sprite description we created (Arial Size 36) to draw the player’s current score near the top right corner of the screen.

5. Dessiner le texte centré horizontalement5. Draw horizontally centered text

Lorsque vous créez un jeu, vous souhaitez souvent dessiner un texte centré, soit horizontalement, soit verticalement.When making a game, you will often want to draw text that is centered, either horizontally or vertically. Pour centrer horizontalement le texte d’introduction, ajoutez ce code à la méthode Draw juste avant spriteBatch.End();To horizontally center the introductory text, add this code to the Draw method just before spriteBatch.End();

if (!gameStarted)
{
  // Fill the screen with black before the game starts
  spriteBatch.Draw(startGameSplash, new Rectangle(0, 0,
  (int)screenWidth, (int)screenHeight), Color.White);

  String title = "VEGGIE JUMP";
  String pressSpace = "Press Space to start";

  // Measure the size of text in the given font
  Vector2 titleSize = stateFont.MeasureString(title);
  Vector2 pressSpaceSize = stateFont.MeasureString(pressSpace);

  // Draw the text horizontally centered
  spriteBatch.DrawString(stateFont, title,
  new Vector2(screenWidth / 2 - titleSize.X / 2, screenHeight / 3),
  Color.ForestGreen);
  spriteBatch.DrawString(stateFont, pressSpace,
  new Vector2(screenWidth / 2 - pressSpaceSize.X / 2,
  screenHeight / 2), Color.White);
  }

Tout d’abord, nous créons deux chaînes, une pour chaque ligne de texte à dessiner.First we create two Strings, one for each line of text we want to draw. Ensuite, nous mesurons la largeur et la hauteur de chaque ligne une fois imprimée, à l’aide de la méthode SpriteFont.MeasureString(String).Next, we measure the width and height of each line when printed, using the SpriteFont.MeasureString(String) method. Cela nous donne la taille en tant qu'objet Vector2, avec la propriété X contenant sa largeur, et Y sa hauteur.This gives us the size as a Vector2 object, with the X property containing its width, and Y its height.

Enfin, nous traçons chaque ligne.Finally, we draw each line. Pour centrer le texte horizontalement, nous nous assurons la X valeur de sa position vecteur égal à largeur / 2 - textSize.X / 2.To center the text horizontally, we make the X value of it’s position vector equal to screenWidth / 2 - textSize.X / 2.

Défi : comment modifier la procédure ci-dessus afin de centrer le texte verticalement et horizontalement ?Challenge: how would you change the procedure above to center the text vertically as well as horizontally?

Essayez d’exécuter le jeu !Try running the game. Voyez-vous l’écran de présentation au démarrage ?Do you see the intro splash screen? Le score augmente-t-il chaque fois que le brocoli se régénère ?Does the score count up each time the broccoli respawns?

Écran de présentation

Détection des collisionsCollision detection

Nous avons un brocoli qui vous suit partout, ainsi qu'un score qui augmente chaque fois qu’un nouveau brocoli est créé, mais pour l'instant, il n’existe aucun moyen de perdre réellement à ce jeu.So we have a broccoli that follows you around, and we have a score that ticks up each time a new one spawns—but as it is there is no way to actually lose this game. Il nous faut un moyen de savoir si les sprites dino et brocolis entrent en collision et, quand c'est le cas, de déclarer que le jeu est fini.We need a way to know if the dino and broccoli sprites collide, and if when they do, to declare the game over.

1. Obtenir les textures1. Get the textures

La dernière image que nous avons besoin, est une pour « game over ».The last image we need, is one for “game over”. Cliquez ici pour télécharger l’image.Click here to download the image.

Comme auparavant avec le rectangle vert, images ninja-cat et brocolis, ajouter cette image à Content.mgcb via la MonoGame Pipeline, en le nommant « jeu-over.png ».Just as before with the green rectangle, ninja-cat and broccoli images, add this image to Content.mgcb via the MonoGame Pipeline, naming it “game-over.png”.

2. Collision rectangulaire2. Rectangular collision

Lorsque des collisions sont détectées dans un jeu, les objets sont souvent simplifiés pour réduire la complexité des calculs nécessaires.When detecting collisions in a game, objects are often simplified to reduce the complexity of the math involved. Nous allons traiter à la fois l'avatar du joueur et l'obstacle brocoli comme des rectangles afin de détecter leurs collisions.We are going to treat both the player avatar and broccoli obstacle as rectangles for the purpose of detecting collision between them.

Ouvrez SpriteClass.cs et ajoutez une nouvelle variable de classe :Open SpriteClass.cs and add a new class variable:

const float HITBOXSCALE = .5f;

Cette valeur représente le degré de « tolérance » de la détection des collisions pour le joueur.This value will represent how “forgiving” the collision detection is for the player. Avec la valeur .5f, les bords du rectangle dans lequel le dino peut entrer en collision avec les brocolis (souvent appelée la « hitbox) auront la moitié de la taille totale de la texture.With a value of .5f, the edges of the rectangle in which the dino can collide with the broccoli—often call the “hitbox”—will be half of the full size of the texture. Il n'y aura donc que peu de cas dans lesquels les coins des deux textures entreront en collision, sans qu'aucune partie des images aient l'air de se toucher réellement.This will result in few instances where the corners of the two textures collide, without any parts of the images actually appearing to touch. N’hésitez pas à modifier cette valeur à votre convenance.Feel free to tweak this value to your personal taste.

Ajoutez ensuite une nouvelle méthode pour SpriteClass.cs :Next, add a new method to SpriteClass.cs:

public bool RectangleCollision(SpriteClass otherSprite)
{
  if (this.x + this.texture.Width * this.scale * HITBOXSCALE / 2 < otherSprite.x - otherSprite.texture.Width * otherSprite.scale / 2) return false;
  if (this.y + this.texture.Height * this.scale * HITBOXSCALE / 2 < otherSprite.y - otherSprite.texture.Height * otherSprite.scale / 2) return false;
  if (this.x - this.texture.Width * this.scale * HITBOXSCALE / 2 > otherSprite.x + otherSprite.texture.Width * otherSprite.scale / 2) return false;
  if (this.y - this.texture.Height * this.scale * HITBOXSCALE / 2 > otherSprite.y + otherSprite.texture.Height * otherSprite.scale / 2) return false;
  return true;
}

Cette méthode détecte si les deux objets rectangulaires se sont heurtés.This method detects if two rectangular objects have collided. L’algorithme fonctionne par test pour voir s’il existe un écart entre un des côtés des rectangles.The algorithm works by testing to see if there is a gap between any of the sides of the rectangles. Si c'est le cas, c'est qu'il n'y a aucune collision. Inversement, s'il n'y a aucun espace, c'est qu'une collision s'est produite.If there is any gap, there is no collision—if no gap exists, there must be a collision.

3. Charger de nouvelles textures3. Load new textures

Ouvrez ensuite Game1.cs et ajoutez deux nouvelles variables de classe, l'une pour stocker la texture du sprite signifiant la fin du jeu et une valeur booléenne pour suivre l’état du jeu :Then, open Game1.cs and add two new class variables, one to store the game over sprite texture, and a Boolean to track the game’s state:

Texture2D gameOverTexture;
bool gameOver;

Initialisez ensuite gameOver dans la méthode initialiser :Then, initialize gameOver in the Initialize method:

gameOver = false;

Enfin, chargez la texture dans gameOverTexture dans la méthode LoadContent :Finally, load the texture into gameOverTexture in the LoadContent method:

gameOverTexture = Content.Load<Texture2D>("game-over");

4. Implémenter la logique « partie terminée »4. Implement “game over” logic

Ajoutez ce code à la méthode Update, juste après l'appel de la méthode KeyboardHandler :Add this code to the Update method, just after the KeyboardHandler method is called:

if (gameOver)
{
  dino.dX = 0;
  dino.dY = 0;
  broccoli.dX = 0;
  broccoli.dY = 0;
  broccoli.dA = 0;
}

Cela stoppera toutes les animations lorsque le jeu sera terminé, figeant les sprites dino et brocoli sur place.This will cause all motion to stop when the game has ended, freezing the dino and broccoli sprites in their current positions.

Ensuite, à la fin de la méthode Update, juste avant base. Update(gameTime), ajoutez la ligne suivante :Next, at the end of the Update method, just before base.Update(gameTime), add this line:

if (dino.RectangleCollision(broccoli)) gameOver = true;

Cela appelle la méthode RectangleCollision que nous avons créée dans SpriteClasset marque le jeu comme étant terminé si elle retourne true.This calls the RectangleCollision method we created in SpriteClass, and flags the game as over if it returns true.

5. Ajouter une entrée d’utilisateur permettant de réinitialiser le jeu5. Add user input for resetting the game

Ajoutez ce code à la KeyboardHandler méthode, pour autoriser l’utilisateur de réinitialiser le jeu si elles appuyez sur ENTRÉE :Add this code to the KeyboardHandler method, to allow the user to reset the game if they press Enter:

if (gameOver && state.IsKeyDown(Keys.Enter))
{
  StartGame();
  gameOver = false;
}

6. Jeu de dessin sur l’écran de démarrage et le texte6. Draw game over splash and text

Pour finir, ajoutez ce code à la méthode Draw, juste après le premier appel de spriteBatch.Draw (il doit s’agir de l’appel qui dessine la texture herbe).Finally, add this code to the Draw method, just after the first call of spriteBatch.Draw (this should be the call that draws the grass texture).

if (gameOver)
{
  // Draw game over texture
  spriteBatch.Draw(gameOverTexture, new Vector2(screenWidth / 2 - gameOverTexture.Width / 2, screenHeight / 4 - gameOverTexture.Width / 2), Color.White);

  String pressEnter = "Press Enter to restart!";

  // Measure the size of text in the given font
  Vector2 pressEnterSize = stateFont.MeasureString(pressEnter);

  // Draw the text horizontally centered
  spriteBatch.DrawString(stateFont, pressEnter, new Vector2(screenWidth / 2 - pressEnterSize.X / 2, screenHeight - 200), Color.White);
}

Nous utilisons ici la même méthode que celle nous avons employée pour tracer le texte centré à l’horizontale (en réutilisant la police que nous avons utilisée pour la présentation de démarrage) et pour centrer gameOverTexture dans la partie supérieure de la fenêtre.Here we use the same method as before to draw text horizontally centered (reusing the font we used for the intro splash), as well as centering gameOverTexture in the top half of the window.

Et c'est fini !And we’re done! Essayez de réexécuter le jeu.Try running the game again. Si vous avez suivi les étapes ci-dessus, le jeu doit maintenant se terminer lorsque le dino entre en collision avec le brocoli et le lecteur doit être invité à redémarrer le jeu en appuyant sur la touche ENTRÉE.If you followed the steps above, the game should now end when the dino collides with the broccoli, and the player should be prompted to restart the game by pressing the Enter key.

Fin du jeu

Publier sur le Microsoft StorePublish to the Microsoft Store

Étant donné que nous avons créé ce jeu comme une application UWP, il est possible de publier ce projet dans le Microsoft Store.Because we built this game as a UWP app, it is possible to publish this project to the Microsoft Store. La procédure comprend quelques étapes.There are a few steps to the process.

Vous devez être enregistré en tant que développeur Windows.You must be registered as a Windows Developer.

Vous devez utiliser la liste de vérification de soumission d’applications.You must use the app submission checklist.

L’application doit être soumise pour certification.The app must be submitted for certification.

Pour plus d’informations, consultez publication de votre application UWP.For more details, see Publishing your UWP app.