Avez-vous une question? (216) 97 656 803 hajjriadh@gmail.com
JavaScript

TP 15 : Dessin et animation avec Canvas

Dessin et animation avec Canvas. Dans cette leçon du cours JavaScript, vous apprendrez à : dessiner une scène complète avec l'API Canvas ; construire une boucle d'animation avec un temps écoulé dt ; g...

0 chapitres 0 QCM Accès gratuit
Dans cet article

À propos de ce cours

Dessin et animation avec Canvas. Dans cette leçon du cours JavaScript, vous apprendrez à : dessiner une scène complète avec l'API Canvas ; construire une boucle d'animation avec un temps écoulé dt ; gérer clavier, souris et collisions ; organiser un petit jeu en objets et en états.

Chapitre 15 — Animations et graphismes avec Canvas · 15.5 TP 15 : Dessin et animation avec Canvas

🎯 Objectifs de la leçon
• dessiner une scène complète avec l'API Canvas ;
• construire une boucle d'animation avec un temps écoulé dt;
• gérer clavier, souris et collisions ;
• organiser un petit jeu en objets et en états.

Présentation

Vous allez programmer un casse-briques: une balle rebondit sur les murs et sur une raquette pilotée par le joueur, et casse des briques. Le jeu mobilise tout le chapitre : dessin (15.2), animation (15.3), interaction et collisions (15.4). Vous pourrez aussi réutiliser les classes du chapitre 16.

Voici le résultat attendu. Les questions de chaque partie vous guident ; aucune solution n'est donnée.

Le casse-briques en cours de partie
Figure 1 — Le jeu à obtenir (en cours de partie).

Fichiers de départ

⬇ Télécharger les fichiers de départ du TP (tp15-depart.zip)

index.html (à ne pas modifier)
<!DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="UTF-8">
  <title>Casse-briques</title>
  <style>
    body { margin: 0; min-height: 100vh; display: grid; place-items: center; background: #0f172a; color: #e2e8f0; font-family: system-ui, sans-serif; }
    canvas { background: #111827; border-radius: 10px; box-shadow: 0 10px 30px rgba(0,0,0,.5); max-width: 95vw; }
    p { text-align: center; color: #94a3b8; }
  </style>
</head>
<body>
  <main>
    <canvas id="jeu" width="640" height="420"></canvas>
    <p>← → ou souris : déplacer · Espace : lancer · P : pause</p>
  </main>
  <script src="jeu.js"></script>
</body>
</html>
jeu.js (à compléter)
// =====================================================================
//  TP 15 — Casse-briques : fichier de départ
//  Complétez ce fichier en suivant les parties du TP.
// =====================================================================

const canvas = document.querySelector("#jeu");
const ctx = canvas.getContext("2d");

// ---- Réglages du jeu (vous pouvez les modifier) ----
const CONFIG = {
  raquette: { largeur: 100, hauteur: 14, vitesse: 480, marge: 30 },     // vitesse en px/s
  balle: { rayon: 8, vitesse: 320 },                                    // px/s
  briques: { lignes: 5, colonnes: 10, largeur: 56, hauteur: 20, espace: 6, haut: 50 },
  couleurs: ["#ef4444", "#f97316", "#eab308", "#22c55e", "#3b82f6"],    // une par ligne
  points: [50, 40, 30, 20, 10],                                          // une par ligne
  vies: 3,
};

// PARTIE 2 — Dessiner la scène


// PARTIE 3 — La boucle d'animation


// PARTIE 4 — Les commandes (clavier et souris)


// PARTIE 5 — Les collisions


// PARTIE 6 — Score, vies et états du jeu

Calcul de la grille de briques et rebond sur la raquette
Figure 2 — Deux calculs à préparer sur papier.

🛠 TP · Partie 1 — Préparer et observer

Mission : Ouvrez index.html avec un serveur local, lisez CONFIG et préparez votre plan.

Questions pour avancer (répondez dans votre compte rendu, puis appliquez dans votre projet) :

  1. Listez les objets du jeu et, pour chacun, ses données (position, taille, vitesse…) et ce qu'il doit savoir faire. Allez-vous écrire des classes ou de simples objets ? Justifiez.
  2. Le jeu passe par plusieurs états: en attente du lancer, en jeu, en pause, perdu, gagné. Dessinez le schéma des états avec les événements qui font passer de l'un à l'autre (touche Espace, touche P, dernière brique, dernière vie).
  3. Avec CONFIG.briques, calculez la largeur totale de la grille. Quelle valeur de « gauche » la centre dans un canvas de 640 px ? (figure 2)

Je vérifie / je rends :

  • ☐ Le plan des objets et le schéma des états.

🛠 TP · Partie 2 — Dessiner la scène

Mission : Dessinez la scène immobile : la grille de briques colorées, la raquette, la balle posée sur la raquette, le score et les vies.

Questions pour avancer (répondez dans votre compte rendu, puis appliquez dans votre projet) :

  1. Écrivez une fonction (ou une méthode) qui crée toutes les briques avec deux boucles imbriquées. Où rangez-vous la couleur et les points de chaque brique ?
  2. La raquette a des coins arrondis : cherchez la méthode roundRect du contexte. Que faire si un navigateur ancien ne la connaît pas ?
  3. Comment placer la balle exactement au centre et juste au-dessus de la raquette ?
  4. Affichez le score à gauche, le record au centre et les vies (♥) à droite. Quelle propriété du contexte permet d'aligner un texte à droite ?

Je vérifie / je rends :

  • ☐ Une capture de la scène immobile, conforme à la figure 1.

🛠 TP · Partie 3 — La boucle d'animation

Mission : Mettez la scène en mouvement : la balle part vers le haut quand on appuie sur Espace et rebondit sur les murs.

Questions pour avancer (répondez dans votre compte rendu, puis appliquez dans votre projet) :

  1. Écrivez la boucle avec requestAnimationFrame et un dt en secondes. Pourquoi limiter dt à une petite valeur ?
  2. Au lancer, la balle part vers le haut avec un angle aléatoire entre −30° et +30° par rapport à la verticale. Comment calculez-vous vx et vy à partir de l'angle et de la vitesse (indice : Math.cos, Math.sin, radians) ?
  3. Faites rebondir la balle sur les murs gauche, droit et haut. Pourquoi est-il plus sûr d'écrire vx = Math.abs(vx) que vx = -vx sur le mur gauche ?
  4. Avant le lancer, la balle doit rester collée à la raquette. Où gérez-vous ce cas dans votre boucle ?

Je vérifie / je rends :

  • ☐ La balle rebondit sans jamais sortir par le haut ni par les côtés.

🛠 TP · Partie 4 — Les commandes

Mission : Le joueur déplace la raquette avec les flèches et avec la souris.

Questions pour avancer (répondez dans votre compte rendu, puis appliquez dans votre projet) :

  1. Utilisez un Set de touches enfoncées. Pourquoi faut-il preventDefault() pour les flèches et la barre d'espace ?
  2. La raquette ne doit jamais sortir du canvas. Écrivez cette contrainte en une seule ligne avec Math.max et Math.min.
  3. Avec la souris, la raquette doit être centrée sur le pointeur. Comment convertir la position de la souris si le canvas est réduit sur un petit écran ?
  4. Ajoutez la pause avec la touche P. Pendant la pause, la souris doit-elle encore déplacer la raquette ?

Je vérifie / je rends :

  • ☐ Commandes clavier et souris fonctionnelles, pause comprise.

🛠 TP · Partie 5 — Les collisions

Mission : Faites rebondir la balle sur la raquette et casser les briques.

Questions pour avancer (répondez dans votre compte rendu, puis appliquez dans votre projet) :

  1. Quel test de collision utilisez-vous entre la balle et un rectangle ? Écrivez-le une fois et réutilisez-le pour la raquette et les briques.
  2. Pour pouvoir viser, l'angle de rebond dépend du point d'impact sur la raquette (figure 2). Exprimez l'impact entre −1 et +1, puis transformez-le en angle entre −60° et +60°. Écrivez les formules de vx et vy.
  3. Pourquoi ne tester la raquette que lorsque la balle descend (vy > 0) ? Que se passerait-il sinon ?
  4. Quand la balle touche une brique, doit-on inverser vx ou vy? Comment savoir si elle a frappé le dessous ou le côté ?
  5. Faut-il supprimer la brique du tableau ou la marquer comme cassée ? Comparez les deux solutions.
  6. Pourquoi est-il prudent de ne casser qu'une seule brique par image ?

Je vérifie / je rends :

  • ☐ La balle rebondit sur la raquette avec un angle qui dépend de l'impact et casse les briques.

🛠 TP · Partie 6 — Score, vies et fin de partie

Mission : Ajoutez le score, les vies, la victoire, la défaite et le record.

Questions pour avancer (répondez dans votre compte rendu, puis appliquez dans votre projet) :

  1. Quand la balle sort par le bas, que doit-il se passer s'il reste des vies ? Et s'il n'en reste plus ?
  2. Comment détectez-vous la victoire ? (indice : every)
  3. Affichez un message centré sur un voile sombre semi-transparent pour la pause, la victoire et la défaite. Espace relance une partie après la fin.
  4. Enregistrez le meilleur score dans le localStorage. Quand faut-il l'enregistrer : à chaque point, ou à la fin de la partie ?
  5. La balle accélère de 2 % à chaque brique cassée. Comment augmenter la vitesse sans changer la direction ?

Je vérifie / je rends :

  • ☐ Une partie complète jouable de bout en bout, avec le record conservé après un rechargement.

🛠 TP · Partie 7 — Bonus

Mission : Améliorez votre jeu.

Questions pour avancer (répondez dans votre compte rendu, puis appliquez dans votre projet) :

  1. Ajoutez des éclats (particules) quand une brique se casse. Quelle leçon réutilisez-vous ?
  2. Ajoutez des briques solides qui demandent deux coups, avec un changement de couleur au premier coup. Quelle donnée ajoutez-vous à la classe Brique?
  3. Ajoutez un niveau 2 avec une autre disposition des briques, décrite par un tableau de chaînes ("XX..XX..XX").
  4. Ajoutez des sons avec new Audio("rebond.mp3").play(). Pourquoi le navigateur refuse-t-il parfois de jouer un son avant la première action du joueur ?
  5. Rendez le jeu jouable au doigt sur téléphone.

Je vérifie / je rends :

  • ☐ Les améliorations choisies, décrites dans votre compte rendu.

Grille d'évaluation indicative

CritèrePoints
Partie 1 — plan des objets et schéma des états2
Partie 2 — scène dessinée, grille centrée par le calcul3
Partie 3 — boucle avec dt, lancer, rebonds sur les murs3
Partie 4 — clavier, souris (avec conversion), pause3
Partie 5 — collisions raquette (angle) et briques4
Partie 6 — score, vies, victoire, défaite, record3
Qualité du code et compte rendu2
Total (bonus partie 7 : jusqu'à +3)20

← 15.4 Interagir avec le canvas : souris, clavier et collisions