TOC

This article has been localized into French by the community.

Création d'un jeu : SnakeWPF:
Chapter introduction:

In this article series, we're building a complete Snake game from scratch. It makes sense to start with the Introduction and then work your way through the articles one by one, to get the full understanding.

If you want to get the complete source code for the game at once, to get started modifying and learning from it right now, consider downloading all our samples!

Ajouter de la nourriture pour le serpent

À ce stade de la série d'articles SnakeWPF, nous avons maintenant un arrière-plan en damier comme zone de jeu, ainsi qu'un joli serpent vert qui se déplace autour. Cependant, comme mentionné dans l'introduction, le but du jeu est que le serpent mange de la nourriture - dans notre version, ce seront des pommes rouges!

Il est maintenant temps de commencer à ajouter de la nourriture à la zone de jeu. Nous allons faire cela en ajoutant aléatoirement un cercle rouge quelque part à l'intérieur des limites du GameArea Canvas, mais il est nécessaire de nous assurer que nous ne le plaçons pas dans l'un des carrés déjà occupé par le serpent qui grandit constamment. Autrement dit, l'une des choses importantes quand on place une pomme sur la zone de jeu est le code qui décide de sa prochaine position. Voici le code que nous utiliserons pour faire précisément cela :

private Point GetNextFoodPosition()
{
    int maxX = (int)(GameArea.ActualWidth / SnakeSquareSize);
    int maxY = (int)(GameArea.ActualHeight / SnakeSquareSize);
    int foodX = rnd.Next(0, maxX) * SnakeSquareSize;
    int foodY = rnd.Next(0, maxY) * SnakeSquareSize;

    foreach(SnakePart snakePart in snakeParts)
    {
if((snakePart.Position.X == foodX) && (snakePart.Position.Y == foodY))
    return GetNextFoodPosition();
    }

    return new Point(foodX, foodY);
}

Assurez-vous de bien ajouter la ligne suivante en haut de la fenêtre de déclaration de classe, ainsi que le reste des variables/constantes :

public partial class SnakeWPFSample : Window
{
    private Random rnd = new Random();
    ......

Pour récapituler rapidement : On utilise la constante SnakeSquareSize pour calculer la prochaine position de notre nourriture, ainsi que la classe Random qui nous permet de générer des positions X et Y aléatoires. Une fois ces coordonnées obtenues, on parcourt toutes les parties du serpent et on vérifie si elles sont au même endroit que la nourriture. Si c'est le cas, on génére un nouveau set de coordonnées en appelant à nouveau la fonction (notons le caractère récursif de cette méthode).

Cette méthode peut donc s'appeller elle même un nombre illimité de fois. En effet, si le serpent occupe toutes les cases du jeu, cela résulte en une boucle infinie. Pour résoudre ce problème théorique, on pourrait implémenter certaines vérifications mais on suppose ici que le jeu sera fini avant d'en arriver là.

Avec ces éléments implémentés, on est prêt à ajouter le code qui génère la nourriture à la position calculée. On fera ceci à l'aide d'une méthode DrawSnakeFood(). Heureusement, le gros du travail a déjà été fait par la méthode GetNextFoodPosition() ! Attention cependant de ne pas oublier de déclarer les champs qui nous permettront de sauvegarder une référence à la nourriture, ainsi qu'un élément SolidColorBrush pour dessiner la pomme. (et les autres éléments et déclarations)

public partial class SnakeWPFSample : Window  
{  
    private UIElement snakeFood = null;  
    private SolidColorBrush foodBrush = Brushes.Red;
    ......

Vous trouverez ci dessous une implémentation de la méthode :

private void DrawSnakeFood()
{
    Point foodPosition = GetNextFoodPosition();
    snakeFood = new Ellipse()
    {
Width = SnakeSquareSize,
Height = SnakeSquareSize,
Fill = foodBrush
    };
    GameArea.Children.Add(snakeFood);
    Canvas.SetTop(snakeFood, foodPosition.Y);
    Canvas.SetLeft(snakeFood, foodPosition.X);
}

Comme promis, c'est très simple : Tant que nous avons la position, nous créons simplement une nouvelle instance d'Ellipse et nous utilisons à nouveau la constante SnakeSquareSize afin de nous assurer qu'il fait la même taille tout comme les tuiles de fond et chaque partie du serpent. On sauvegarde une référence de l'instance Ellipse dans le champ snakeFood car nous en aurons besoin plus tard.

Une fois que c'est fait, il ne nous reste plus qu'à appeler la méthode DrawSnakeFood() pour voir le résultat de notre travail. Cela peut se faire dans deux cas : quand le jeu commence et quand le serpent "mange" la nourriture (nous verrons d'autres ca plus tard). Pour l'instant, ajoutons un appel dans notre méthode StartNewGame() :

private void StartNewGame()
{
    snakeLength = SnakeStartLength;
    snakeDirection = SnakeDirection.Right;
    snakeParts.Add(new SnakePart() { Position = new Point(SnakeSquareSize * 5, SnakeSquareSize * 5) });
    gameTickTimer.Interval = TimeSpan.FromMilliseconds(SnakeStartSpeed);

    // Draw the snake and the snake food
    DrawSnake();
    DrawSnakeFood();

    // Go!    
    gameTickTimer.IsEnabled = true;
}

C'est fait! Si vous lancez le jeu maintenant, vous devriez voir que le serpent a maintenant de la nourriture à "chasser".

Ca fait un peu de travail pour placer un point rouge à l'écran, non?

Résumé

Dans cet article, nous avons maintenant ajouté de la nourriture sur la table pour que le serpent puisse l'attraper, mais il y a encore du travail à faire : nous devons être capable de contrôler le serpent, et nous devons savoir quand il rencontre un obstacle (un mur, son propre corps ou de la nourriture). A suivre dans le prochain article.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!