This article has been localized into French by the community.
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!
Mouvement en continu avec un DispatcherTimer
Dans les articles précédents, nous avons créé une zone de jeu pour notre Snake et nous avons créé le code pour créer et mettre en mouvement ce serpent. Toutefois, comme nous l'avons déjà mentionné, le code de mise en mouvement doit être appelé plusieurs fois - encore et encore, afin de garder le serpent en mouvement tant que le jeu tourne. En d'autres termes, nous allons avoir besoin d'un Timer.
Généralement, en programmation, un Timer est un mécanisme permettant à une tâche d'être répétée encore et encore à intervalle régulier. En d'autres termes, à chaque fois que le timer "ticks", un bout de code est exécuté. C'est exactement ce dont nous avons besoin pour garder le serpent en mouvement, donc nous allons ajouter un DispatcherTimer à notre Window:
public partial class SnakeWPFSample : Window
{
private System.Windows.Threading.DispatcherTimer gameTickTimer = new System.Windows.Threading.DispatcherTimer();
....
Avec ceci en place, nous devons maintenant nous inscrire à un seul événement : l'événement Tick. Nous le ferons dans le constructeur de la fenêtre (Window):
public SnakeWPFSample()
{
InitializeComponent();
gameTickTimer.Tick += GameTickTimer_Tick;
}
Et voici l'implémentation de l'événement:
private void GameTickTimer_Tick(object sender, EventArgs e)
{
MoveSnake();
}
De cette manière, chaque fois que le timer tique, l'événement Tick est appelée, lequel fait appel à la méthode MoveSnake() que nous avons implémenté précédemment. Pour finalement voir le résultat de tant de labeurs et avoir un serpent visible en mouvement, nous n'avons plus qu'à créer les parties initiales du serpent et démarrer le timer. Nous allons créer une méthode StartNewGame() que nous utiliserons pour démarer la première partie ainsi que les parties suivantes quand le joueur mourra. Nous démarrerons avec une version basique, puis nous la complèterons avec davantage de fonctionnalités au fur et à mesure que nous avancerons - pour le moment, mettons juste ce serpent en mouvement !
La première étape est l'ajout un autre ensemble de constantes que nous utiliserons pour démarrer une nouvelle partie:
public partial class SnakeWPFSample : Window
{
const int SnakeSquareSize = 20;
const int SnakeStartLength = 3;
const int SnakeStartSpeed = 400;
const int SnakeSpeedThreshold = 100;
......
Seules les trois premières constantes sont utilisée à ce niveau, pour controler la taille, la longueur et la vitesse de démarrage du Snake. Nous utiliserons SnakeSpeedThreshold (seuil de vitesse) plus tard, mais pour l'instant, ajoutons une implémentation simple de la méthode StartNewGame() comme promis:
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
DrawSnake();
// Go!
gameTickTimer.IsEnabled = true;
}
Nous débutons en affectant snakeLength et snakeDirection selon leurs valeurs initiales. Ensuite nous ajoutons une partie unique à la liste des snakeParts (d'autres viendront par après), et lui donnons une position de départ pour un bon démarrage - nous utiliserons une fois de plus la constante SnakeSquareSize pour calculer une position correcte. Une fois ceci fait, nous pouvons dessiner le serpent en appelant la méthode DrawSnake() et activer le timer, ce qui fera démarrer le serpent.
Nous avons presque fini et pourrons bientôt profiter de la toute première version de quelque chose qui commence à ressembler à un jeu - en fait, tout ce que nous avons à faire maintenant est d'appeler la méthode StartNewGame(). Cela devrait évidemment être fait quand le joueur est prêt, mais pour vérifier que tout fonctionne, nous allons simplement le faire dès que tout le reste sera initialisé - nous comptera à nouveau sur l'événement ContentRendered de la Window, que nous avons ajouté dans les articles précédents. Ajoutez simplement un appel à la méthode StartNewGame() et nous pouvons finalement compiler et démarrer:
private void Window_ContentRendered(object sender, EventArgs e)
{
DrawGameArea();
StartNewGame();
}
Si vous avez tout fait comme décrit, vous devriez pouvoir démarrer le jeu et voir le serpent être créé et avancer immédiatement après:
Remarquez comme le serpent apparait de nulle part, comme un seul carré, puis grandit jusqu'à 3 cases de longueur. Cela vient du fait que nous n'avons qu'une seul partie dans notre list snakeParts, mais à chaque fois que la méthode MoveSnake() est appelée par le timer, une nouvelle partie est ajoutée (pour le faire grandir), tandis que la suppression du bloc de queue n'arrive que si la longueur du serpent excède la longueur voulue (définie à 3 au début dans la constante SnakeStartLength).
Résumé
Nous avons maintenant un serpent qui bouge, ce qui est vraiment génial ! Mais comme vous le voyez sur l'image animée ci-dessus, il reste des choses à faire - il n'y a pas de nourriture pour le serpent, et quand ce dernier touche le mur, rien ne se passe. Nous travaillerons sur ces aspects dans les prochains articles.