ISN : Le jeu Frog

1. Objectifs

Ce tp reprendra le mise en place de la POO vue avec la carte de voeux où l’on faisait tomber de la neige sur Lille.
On va adapter quelque peu notre précédente création pour déplacer horizontalement des véhicules sur une route à 4 voies.
Puis on ajoutera une grenouille que l’on pourra déplacer en évitant les véhicules.
Objectifs : continuer à travailler la POO, la gestion d’événements, la gestion d’interaction entre différents objets.

a) Le html ne change pas beaucoup si ce n’est pour le titre et le texte

<!DOCTYPE html>
<html lang="fr" >

<head>
  <meta charset="UTF-8">
  <title>Frog</title>
<link rel="stylesheet" href="style.css">
<link href="https://fonts.googleapis.com/css?family=Amatic+SC|Titillium+Web:300,700" rel="stylesheet">
</head>
<body >
  <div id="conteneur">
      <header>
      Vous êtes une grenouille, à vous de traverser la route.
      </header>
     
    <article>
           <div>
              <canvas id="mon_canvas"></canvas>
           </div>
        </article>
<footer>SNT, Lycée Faidherbe 2020</footer>
</div>
</body>
<script src="script.js"></script>

</html>

b) Le CSS

Peu de modification ici, si ce n’est l’image de fond:


@media all  and (min-width: 600px) {
  body{
    

  }
#mon_canvas {
  background-image: url("images/fond.png");
  background-position: center top; /* On centre l'image */
  background-repeat: no-repeat; /* on ne la répète pas */
  background-size: cover; /* l'image recouvre l'élément */
  height: 600px; /* on fixe les dimensions du canvas */
  width: 900px;
}
    
  #conteneur{
    margin-left: 20px;
    width : 1000px;
  }
header,footer {
  font-family: 'Amatic SC', cursive;
  border-width:1px;
  border-style: outset;
  border-color: #000;
  margin-top: 15px;
  margin-bottom: 15px;
  font-size: 30px;
  padding-left: 50px;
  color: black;

}

article{
font-family: 'Titillium Web', sans-serif;
  display: flex;
  flex-direction: row;
  justify-content: space-around;
  border-width:1px;
  border-style: outset;
  border-color: #000;
  margin-top: 15px;
  margin-bottom: 15px;
}
article h1{
  font-size: 20px;
  font-weight: bold;
  text-decoration: underline;
}
}

@media all  and (max-width: 600px) {

    #mon_canvas {
  background-image: url("images/fond.png");
  background-position: center top; /* On centre l'image */
  background-repeat: no-repeat; /* on ne la répète pas */
  background-size: cover; /* l'image recouvre l'élément */
  height: 300px; /* on fixe les dimensions du canvas */
  width: 450px;
}
    
#conteneur{
    width : 95%;
    position : center;
  }
header,footer {
  font-family: 'Amatic SC', cursive;
  border-width:1px;
  border-style: outset;
  border-color: #000;
  margin-top: 15px;
  margin-bottom: 15px;
  font-size: 30px;
  padding-left: 50px;
  color: black;

}
header {
    height: 100px;

    }


article{
    font-family: 'Titillium Web', sans-serif;
  display: flex;
  flex-direction: column;
  align-items: center;
  
  border-width:1px;
  border-style: outset;
  border-color: #000;
  margin-top: 15px;
  margin-bottom: 15px;
}
article h1{
  font-size: 20px;
  font-weight: bold;
  text-decoration: underline;
}
img {
        width: 80%;
        position: center;
    }


}

c) Le js

On a apporté davantage de modifications :
– déplacement horizontal et plus vertical comme avec les flocons,
– positionnement vertical défini en fonction du type de véhicules,
– un gestion de la position des véhicules les uns en fonction des autres.

// on déclare un élément canvas qui correspond à l'élément dont l'id est tutoriel
   var canvas = document.getElementById("mon_canvas");
   // on déclare notre feuille de dessin ctx qui sera une version 2D du canvas
   ctx = canvas.getContext("2d");
  // On déclare une liste d'objets appelé vehicules
   var vehicules=[];
   // on crée 10 vehiculess
on_met_en_place_les_vehicules(20)

   

   // on définit le constructeur et les propriétés et méthodes associées
  function Vehicule(x,y,type,sens) {
    // un vehicule est défini par 4 propriétés
    // position : x et y
    // type
    // 0 : camion, 1 : voiture, 2 : moto
    // sens : 1 : se déplace de la gauche vers la droite
    //        -1 : se déplace de la droite vers la gauche
    this.x=x;
    this.y=y;
    this.type=type;
    this.sens=sens;
    // on crée 2 méthodes
    // la méthode deplacement en fonction du type de vehicules : 0 gros, 1 moyens, 2 petits
    this.deplacement=function(){
      switch (this.type) {
        // cas 0 : camion
        case 0:
        vitesse=0.3*this.sens;
          break;
       // cas 1 : voiture
        case 1:
        vitesse=0.6*this.sens;
        break;
        // cas 2 : moto
        case 2:
        vitesse=0.8*this.sens;
        break;
      }
      this.x=this.x+vitesse;
        // si le vehicule sort à droite on le renvoie à gauche
      if ((this.x>canvas.width) && (sens==1))
        {this.x=position_vehicule_plus_a_gauche();}
        // si le vehicule sort à gauche on le renvoie à droite
      if ((this.x<0) && (sens==-1))
        {this.x=position_vehicule_plus_a_droite();}
    }
    // la méthode dessiner en fonction du type
    this.dessiner=function(){

      var taille;
      var transparences;
      switch (this.type) {
        // cas 0 : on dessine un cercle non rempli
        case 0:
        hauteur=canvas.height/12;
        largeur=canvas.width/10;
        couleur='rgb(150,100,100)';
          break;
       // cas 1 : on dessine un cercle colorié en noir
        case 1:
        hauteur=canvas.height/12;
        largeur=canvas.width/20;
        couleur='rgb(100,150,100)';
        break;
        // cas 2 : un demi-cercle vers le bas
        case 2:
        hauteur=canvas.height/12;
        largeur=canvas.width/25;
        couleur='rgb(100,100,150)';
        
        break;
      }
        
        
      ctx.beginPath();
      ctx.rect(this.x-largeur/2,this.y-hauteur/2,largeur,hauteur);
      ctx.fillStyle = couleur;
      ctx.fill();
     ctx.stokeStyle = "rgb(255,255,255)";
      ctx.stroke();
      ctx.closePath();
    }

// fin du constructeur
}

// fonction qui permet de créer les véhicules avec des propriétés aléatoires
function on_met_en_place_les_vehicules(n){
    var nbe_aleatoire;
    
  var type;
    
    for (i=0;i<n;i++){
         nbe_aleatoire=Math.random();
    if (nbe_aleatoire<0.4){type=0;}
    if (nbe_aleatoire>=0.4 && nbe_aleatoire<0.8){type=1;}
      if (nbe_aleatoire>=0.8){type=2;}
      // on détermine aléatoire le sens de déplacement
         nbe_aleatoire=Math.random();
if (nbe_aleatoire<0.5){
    sens=1;
} 
else
        {sens=-1;}
        //alert(nbe_aleatoire+" "+i+" sens "+sens+" type "+type);
        
      // on positionne les véhicules en fonction de leur sens
      // de déplacement et de leur type
if (sens==1){
    x=position_vehicule_plus_a_gauche();
    if (type==0) {
        
        y=canvas.height*9/12;
    }
    if (type==1) {
        y=canvas.height*7/12;
    }
    if (type==2) {
        y=canvas.height*7/12;
    }   
}
else {
    x=position_vehicule_plus_a_droite();
    if (type==0) {
        y=canvas.height*3/12;
    }
    if (type==1) {
        y=canvas.height*5/12;
    }
    if (type==2) {
        y=canvas.height*5/12;
    }   
}
        
    vehicules[vehicules.length]= new Vehicule(x,y,type,sens);
        distance_securite+=20;
        
    }
    
}

function position_vehicule_plus_a_gauche(){
    distance_securite=50;
    min=0;
    for (var i=0;i<vehicules.length;i++){
        if (vehicules[i].x<min){
            min=vehicules[i].x
        }
    }
    return min-distance_securite;
}
function position_vehicule_plus_a_droite(){
    distance_securite=50;
    max=canvas.width;
    for (var i=0;i<vehicules.length;i++){
        if (vehicules[i].x>max){
            max=vehicules[i].x
        }
    }
    return max+distance_securite;
}

function dessiner_la_jeu(){
  
  // on efface avec un fond noir
    ctx.clearRect(0, 0, canvas.width, canvas.height);
  for (var i=0;i<vehicules.length;i++){
      
  vehicules[i].dessiner();
  vehicules[i].deplacement();
                        }
  window.requestAnimationFrame(dessiner_la_jeu);
 }

2. La mise en place d’une grenouille et la gestion d’événements au clavier.

a) Définir les propriétés et méthodes qui seront associées à notre ( ou nos ) grenouille(s).

Mettre en place, en vous inspirant de la classe Vehicule, une classe Grenouille.
Définir les propriétés qui seront nécessaires ainsi que les méthodes ( on peut s’inspirer, là encore de la classe Vehicule )..
On pourra penser à un nombre de vies déterminé.
On n’oubliera pas de demander à afficher notre grenouille dans la fonction dessiner_la_jeu().

b) Attacher des événements à certaines touches du clavier.

Pour gérer les événements liés au clavier, on va utiliser un appel fléché à une fonction anonyme.
Insérer dans le js, avant la déclaration des classes et des fonctions, le code suivant :

document.addEventListener('keydown', (event) => {
  const nomTouche = event.key;
      alert(nomTouche);
}, false);

Tester ce code, et le modifier pour gérer les déplacements de votre grenouille.

c) Gérer les collisions.

Le plus simple pour gérer la collision est de gérer ce cas lors du déplacement des véhicules.
A vous de jouer avant de pouvoir jouer.

d) Pour aller plus loin.

  • modifier les formes très simples associées à nos objets ( on peut remplacer nos dessins dans le canvas par des images ),
  • penser à une autre gestion des événements pour une version pour un téléphone portable ( pas d’accès au clavier),
  • à un placement aléatoire de la grenouille,
  • à un jeu avec plusieurs grenouilles….