Exporter (0) Imprimer
Développer tout
5 sur 5 ont trouvé cela utile - Évaluez ce sujet

Programmation de jeux simples avec Canvas ou SVG

.NET Framework 3.0

Cette rubrique compare l’utilisation de Canvas et de SVG pour créer un jeu d’arcade simple, exécutable sur une page Web.

Elle contient deux exemples de code autonomes annotés qui présentent un jeu de raquettes générique. L’objectif de ce jeu est de frapper une balle avec une raquette pour qu’elle rebondisse au plafond et sur les murs latéraux du court. Ces exemples sont rédigés en langage HTML5 et JavaScript. Ils expliquent les principes élémentaires du dessin du court, de la balle et de la raquette, ainsi que de la création de l’action, de la détection des collisions et de la fin de la partie. Le premier exemple de code présente le jeu dans Canvas et montre de quelle manière cette technologie utilise des pixels en mode immédiat (immediate mode) pour dessiner la raquette et le terrain avec des rectangles et la balle avec la méthode arc. Ensuite, le code décrit comment colorier le terrain, la raquette et la balle. Le deuxième exemple est une version SVG qui illustre la manière dont SVG utilise des formes en mode retenu ( retained mode) pour afficher un cercle (circle) pour la balle, et des rectangles pour le terrain et la raquette, tout en ajoutant les couleurs adéquates. Les commentaires techniques qui suivent chaque exemple expliquent le fonctionnement du code. La comparaison finale résume les principales différences notées lors de la création d’un jeu de raquettes insérable dans une page Web.

Exemple de code Canvas



<!DOCTYPE html>
<html>
  
  <head>
    <script type="text/javascript">
      // Global variables.
      var ballX = 150; // Ball x position.
      var ballY = 150; // Ball y position.
      var ballDX = 2; // Change in ball x position.
      var ballDY = 4; // Change in ball y position.
      var boardX = 300; // Board width.
      var boardY = 300; // Board height.
      var paddleX = 150; // Initial paddle location.
      var paddleH = 10; // Paddle height.
      var paddleD = boardY - paddleH; // Paddle depth.
      var paddleW = 150; // Paddle width.
      var canvas; // Canvas element.
      var ctx; // Canvas context.
      var gameLoop; // Game loop time interval.
      // This function is called on page load.


      function drawGameCanvas() {

        // Get the canvas element.
        canvas = document.getElementById("gameBoard");

        // Make sure you got it.
        if (canvas.getContext) {
          // Specify 2d canvas type.
          ctx = canvas.getContext("2d");

          // Play the game until the ball stops.
          gameLoop = setInterval(drawBall, 16);

          // Add keyboard listener.
          window.addEventListener('keydown', whatKey, true);

        }
      }

      function drawBall() {

        // Clear the board.
        ctx.clearRect(0, 0, boardX, boardY);

        // Fill the board.
        ctx.fillStyle = "thistle";
        ctx.beginPath();
        ctx.rect(0, 0, boardX, boardY);
        ctx.closePath();
        ctx.fill();

        // Draw a ball.
        ctx.fillStyle = "tomato";
        ctx.beginPath();
        ctx.arc(ballX, ballY, 15, 0, Math.PI * 2, true);
        ctx.closePath();
        ctx.fill();

        // Draw the paddle.
        ctx.fillStyle = "navy";
        ctx.beginPath();
        ctx.rect(paddleX, paddleD, paddleW, paddleH);
        ctx.closePath();
        ctx.fill();

        // Change the ball location.
        ballX += ballDX;
        ballY += ballDY;

        // Bounce on a left or right edge.
        if (ballX + ballDX > boardX - 15 || ballX + ballDX < 15) ballDX = -ballDX;

        // If ball hits the top, bounce it. 
        if (ballY + ballDY < 15) ballDY = -ballDY;
        // If the ball hits the bottom, check see if it hits a paddle.
        else if (ballY + ballDY > boardY - 15) {
          // If the ball hits the paddle, bounce it.
          if (ballX > paddleX && ballX < paddleX + paddleW) ballDY = -ballDY;
          // Otherwise the game is over.
          else {
            clearInterval(gameLoop);
            alert("Game over!");
          }
        }
      }

      // Get key press.


      function whatKey(evt) {

        switch (evt.keyCode) {
          // Left arrow.
        case 37:
          paddleX = paddleX - 20;
          if (paddleX < 0) paddleX = 0;
          break;

          // Right arrow.
        case 39:
          paddleX = paddleX + 20;
          if (paddleX > boardX - paddleW) paddleX = boardX - paddleW;
          break;
        }
      }
    </script>
  </head>
  
  <body onload="drawGameCanvas()">
    <h1>
      Canvas Racquetball
    </h1>
    <div>
      <canvas id="gameBoard" width="300" height="300">
      </canvas>
    </div>
  </body>

</html>

Discussion sur l’exemple de code Canvas

Cet exemple utilise un en-tête HTML5 standard, <!doctype html>, pour que les navigateurs puissent l’identifier comme faisant partie de la spécification HTML5.

Ce code se divise en deux parties principales :

  • Code de corps
  • Code de script

Code de corps

La fonction drawGameCanvas est appelée lors du chargement de la page. La balise canvas fait partie du code de corps et la largeur et la hauteur initiales sont précisées, tout comme l’attribut ID. L’ID est indispensable pour que l’élément canvas puisse être ajouté au modèle d’objet de la page.

Code de script

Le code script est composé d’un ensemble de variables globales et de trois fonctions : drawGameCanvas, drawBall et whatKey. Les variables globales sont initialisées au chargement de la page, de même que drawGameCanvas. drawBall est appelée à l’approche de la fin de drawGameCanvas et reliée à un événement de minuterie appelé gameLoop. La fonction drawBall est appelée toutes les 16 millisecondes. La troisième fonction, whatKey, est reliée à un écouteur d’événements et « écoute » l’événement « keydown », déclenché dès que l’utilisateur appuie sur une touche.

Variables globales

Cette section indique comment initialiser plusieurs variables utilisées tout au long du jeu.

  • ballX et ballY définissent la position initiale de la balle au centre du terrain (150,150).
  • ballDX et ballDy initialisent la vitesse initiale du changement de position de la balle.
  • boardX et boardY initialisent la hauteur et la largeur du terrain (300 x 300).
  • paddleX définit la position x initiale (x supérieur gauche) de la raquette (150).
  • paddleH définit la hauteur absolue de la raquette (10).
  • paddleD représente la position y initiale (y supérieur gauche) de la raquette (290).
  • paddleW représente la largeur de la raquette (150).
  • Les variables canvas, ctx et gameLoop sont créées en tant que variables globales pour être accessibles de partout dans le code script.

Fonction drawGameCanvas

Cette fonction est appelée lors du chargement de la page. Elle permet d’obtenir l’élément canvas en recourant à l’ID de l’élément canvas dans le code de corps. Elle obtient ensuite le contexte du canevas, ce dernier étant alors prêt à accepter le dessin.

La boucle du jeu est alors définie avec un appel setInterval de la fonction drawBall. Cette fonction sera appelée toutes les 16 millisecondes. La plupart des jeux disposent d’une boucle de jeu appelée à des intervalles définis pour effectuer des animations.

Enfin, l’écouteur d’événements de clavier whatKey est défini pour traiter tous les événements de touche.

Fonction drawBall

Cette fonction est appelée par un compteur d’événement toutes les 16 millisecondes. Chaque appel de cette fonction génère l’exécution des tâches suivantes :

  • Le terrain de jeu se vide et se remplit. La méthode clearRect est appelée pour effacer le canevas, puis une couleur (chardon) est indiquée. Un tracé rectangulaire est défini et rempli.
  • La balle est dessinée dans sa position actuelle en spécifiant fillStyle, beginPath, arc, closePath et fill. La position de la balle est définie par les variables ballX et ballY qui changent en fonction des collisions avec les murs et la raquette.
  • La raquette est ensuite dessinée de la même manière, mais avec les spécifications de paddleX, paddleD, paddleW et paddleH.
  • L’emplacement de la balle est modifié pour son dessin suivant en fonction des variables ballDX et ballDY. Cela suppose que la balle ne heurte ni un mur ni la raquette.
  • Si elle heurte le mur gauche ou droit, la valeur ballDX de la balle s’inverse, et celle-ci rebondit dans la direction opposée.
  • De même, si elle heurte le plafond, la valeur ballDY de la balle s’inverse, et celle-ci rebondit dans la direction opposée.
  • Si elle heurte le sol, une vérification est effectuée pour déterminer si elle a heurté la raquette. Si tel est le cas, la valeur ballDY de la balle s’inverse pour que la balle rebondisse. En revanche, si la balle heurte le sol, mais pas la raquette, la partie est finie.
  • Si la partie est finie, la boucle de jeu est supprimée (ce qui arrête le déplacement de la balle) et une alerte s’affiche pour annoncer la fin de la partie.

Fonction whatKey

La fonction whatKey configure l’écouteur d’événements pour qu’il soit à l’écoute d’un événement keydown avec une instruction switch. Pour ce faire, il recherche deux codes de touche.

Si l’utilisateur appuie sur la flèche gauche, le code de touche 37 est reconnu et la valeur paddleX de la raquette est décrémentée de 20 pixels. Cependant, si le côté gauche de la raquette est inférieur à zéro, la raquette ne bouge pas, car sa valeur est définie sur 0 (zéro).

Si l’utilisateur appuie sur la flèche droite, le code de touche 39 est reconnu et la valeur paddleX de la raquette est incrémentée de 20 pixels. Toutefois, si le côté droit de la raquette est supérieur à la largeur du terrain, la raquette ne bouge pas, car sa valeur est définie sur celle du bord droit du terrain.

Exemple de code SVG


<!DOCTYPE HTML>
<html>
  
  <head>
    <script type="text/javascript">
      // Global variables
      var ballX = 150; // Ball x position.
      var ballY = 150; // Ball y position.
      var ballDX = 2; // Change in ball x position.
      var ballDY = 4; // Change in ball y position.
      var boardX = 300; // Board width.
      var boardY = 300; // Board height.
      var paddleX = 150; // Initial paddle location.
      var paddleH = 10; // Paddle height.
      var paddleD = boardY - paddleH; // Paddle depth.
      var paddleW = 150; // Paddle width.

      // This function is called on page load.


      function drawGameSVG() {

        // Play the game until the ball stops.
        gameLoop = setInterval(drawBall, 16);

        // Add keyboard listener.
        window.addEventListener('keydown', whatKey, true);
      }

      function drawBall() {


        // Change the ball location.
        ballX += ballDX;
        ballY += ballDY;
        ball.setAttribute("cx", ballX);
        ball.setAttribute("cy", ballY);


        // Bounce on a left or right edge.
        if (ballX + ballDX > boardX - 15 || ballX + ballDX < 15) ballDX = -ballDX;

        // If ball hits the top, bounce it. 
        if (ballY + ballDY < 15) ballDY = -ballDY;
        // If the ball hits the bottom, check see if it hits a paddle.
        else if (ballY + ballDY > boardY - 15) {
          // If the ball hits the paddle, bounce it.
          if (ballX > paddleX && ballX < paddleX + paddleW) ballDY = -ballDY;
          // Otherwise the game is over.
          else {
            clearInterval(gameLoop);
            alert("Game over!");
          }
        }
      }



      // Get key press.


      function whatKey(evt) {

        switch (evt.keyCode) {
          // Left arrow.
        case 37:
          paddleX = paddleX - 20;
          if (paddleX < 0) paddleX = 0;
          paddle.setAttribute("x", paddleX);
          break;

          // Right arrow.
        case 39:
          paddleX = paddleX + 20;
          if (paddleX > boardX - paddleW) paddleX = boardX - paddleW;
          paddle.setAttribute("x", paddleX);
          break;
        }
      }
    </script>
  </head>
  
  <body onload="drawGameSVG()">
    <h1>
      SVG Racketball
    </h1>
    <!-- Create the SVG pane. -->
    <svg xmlns="http://www.w3.org/2000/svg" height="300" width="300">
      <!-- Create the board. -->
      <rect x="1" y="1" width="298" height="298" fill="thistle" id="bpard" />
      <!-- Create the ball. -->
      <circle cx="150" cy="150" r="15" fill="tomato" id="ball" />
      <!-- Create the paddle. -->
      <rect x="150" y="290" width="150" height="10" fill="navy" id="paddle"
      />
    </svg>
  </body>

</html>


SVG - Commentaires sur l’exemple de code

La logique JavaScript utilisée dans l’exemple de jeu Canvas est adaptée à cet exemple de jeu SVG, avec quelques modifications seulement. Les sections suivantes détaillent les parties identiques et différentes.

Cet exemple utilise un en-tête HTML5 standard, <!doctype html>, pour que les navigateurs puissent l’identifier comme faisant partie de la spécification HTML5.

Ce code se divise en deux parties principales :

  • Code de corps
  • Code de script

Code de corps

Il contient les définitions des formes SVG utilisées par le jeu : un terrain, un cercle et une raquette.

Code de script

Le code du script contient les variables globales, ainsi que les fonctions drawGameSVG, drawBall et whatKey.

Variables globales

Elles sont identiques à celles de l’exemple Canvas.

Fonction drawGameSVG

Cette fonction est appelée lors du chargement de la page et remplace la fonction drawGameCanvas. Dans la mesure où le terrain, la raquette et la balle sont créés dans la section body, cette fonction ne fait qu’appeler la boucle de jeu drawBall et configurer l’écouteur d’événement whatKey.

Fonction drawBall

Cette fonction est en majeure partie identique à la fonction drawBall de Canvas, à l’exception des attributs x et y de la balle qui sont remplacés par setAttribute. En outre, contrairement à Canvas, la balle de SVG n’est pas redessinée à chaque fois : elle est seulement déplacée. Cette différence tire parti du mode retenu de SVG, la balle et ses attributs étant stockés en mémoire. Modifiez un attribut et l’objet est instantanément modifié. Le reste de la boucle du jeu contient la logique qui détermine où se trouvera la balle au prochain traitement de la boucle du jeu.

Fonction whatKey

Cette fonction est en majeure partie identique à la fonction drawBall de Canvas, à l’exception des attributs x et y de la balle qui sont remplacés par setAttribute. En outre, contrairement à Canvas, la balle de SVG n’est pas redessinée à chaque fois : elle est seulement déplacée. Cette différence tire parti du mode retenu de SVG, la balle et ses attributs étant stockés en mémoire. Modifiez un attribut et l’objet est instantanément modifié. Le reste de la boucle du jeu contient la logique qui détermine où se trouvera la balle au prochain traitement de la boucle du jeu.

Récapitulatif de la comparaison

Canvas et SVG permettent tous les deux de créer des jeux à action rapides. Les différences principales entre les exemples de codes discutés ici reposent sur la gestion de l’insertion d’images sur l’écran. Les images SVG en mode retenu sont créées dans le code de corps et sont modifiées en définissant les attributs de la balle et de la raquette via la méthode setAttribute. Le mode immédiat de Canvas nécessite que la balle soit redessinée à chaque appel de la boucle du jeu, tandis que SVG n’exige que quelques appels simples pour modifier la position de la raquette et de la balle.

Quand vous créez un jeu sur un terrain de petite taille ne contenant que peu d’objets, quasiment aucune différence de performance n’est visible entre Canvas et SVG. Le programme Canvas comporte 134 lignes et le programme SVG 115. Toutefois, à mesure que vous ajoutez des objets, le code Canvas augmente. De plus, comme les objets Canvas doivent être redessinés à chaque boucle de jeu, le jeu Canvas est plus lent.

Rubriques associées

Comment choisir entre Canvas et SVG pour créer des graphiques sur le Web

 

 

Cela vous a-t-il été utile ?
(1500 caractères restants)
Merci pour vos suggestions.
Afficher:
© 2014 Microsoft. Tous droits réservés.