◆ Portail Antalaha

Annuaire › Code ouvert

Pirogue d'Antalaha - jeu de vanille (p5.js)

tutorial · Voir le site ↗
Connectez-vous pour copier ce site

Code publié par son auteur, en lecture seule. « Copier dans mon espace » crée un nouveau site à vous (non publié) que vous pouvez modifier librement.

js/sketch.js · 6.8 Ko

/* ============================================================
   sketch.js - point d'entrée : setup(), draw() et entrées
   ============================================================
   Ce fichier fait le lien entre p5.js et la classe Jeu :
     - setup()    : crée le canevas et l'objet Jeu (une fois) ;
     - draw()     : lit les entrées, met à jour et dessine (60 fois/s) ;
     - touches, souris, doigt : transmis à Jeu ;
     - windowResized() : adapte le canevas à l'écran.

   POURQUOI scale() ? Le jeu "pense" en 360 x 640 unités. Le canevas
   réel a une autre taille (téléphone, ordinateur...). scale(f)
   agrandit tout le dessin du facteur f ; et pour les positions du
   doigt, on fait l'opération inverse (division par f).
   ============================================================ */

/* ---------- Variables globales ---------- */
let jeu;                       // l'unique objet Jeu
let facteurEchelle = 1;        // rapport canevas réel / monde logique
let dernierAppui = -1000;      // instant (ms) du dernier appui : évite de compter deux fois un même toucher
let erreurSignalee = false;    // pour n'afficher une éventuelle erreur qu'une fois dans la console

/* ------------------------------------------------------------
   calculerTaille()
   But : calculer la taille du canevas, toujours au format 9:16 (portrait),
         en respectant la largeur ET la hauteur disponibles.
   Retour : {w, h} en pixels
   ------------------------------------------------------------ */
function calculerTaille() {
  const boite = document.getElementById('conteneur-jeu');
  const dispo = boite ? boite.clientWidth : windowWidth;      // largeur disponible dans la page

  let w = Math.min(dispo, LARGEUR_CANVAS_MAX);
  // On limite aussi pour que le canevas tienne dans la hauteur de la fenêtre.
  const largeurMaxSelonHauteur = (windowHeight - MARGE_VERTICALE) * LARGEUR_JEU / HAUTEUR_JEU;
  w = Math.min(w, largeurMaxSelonHauteur);
  w = Math.max(w, LARGEUR_CANVAS_MIN);

  const largeurEntiere = Math.floor(w);
  return { w: largeurEntiere, h: Math.floor(largeurEntiere * HAUTEUR_JEU / LARGEUR_JEU) };
}

/* ------------------------------------------------------------
   setup() : appelée UNE fois au démarrage par p5.
   ------------------------------------------------------------ */
function setup() {
  const t = calculerTaille();
  createCanvas(t.w, t.h).parent('conteneur-jeu');
  facteurEchelle = t.w / LARGEUR_JEU;

  frameRate(60);                  // 60 images par seconde visées
  textFont(POLICE);
  jeu = new Jeu();

  describe("Jeu : une pirogue à balancier, vue du dessus, glisse sur l'eau. Il faut ramasser des gousses de vanille et éviter les rochers et les vagues. Se joue aux flèches, à Q et D, ou au doigt.");
}

/* ------------------------------------------------------------
   draw() : appelée en boucle par p5 (≈ 60 fois par seconde).
   deltaTime = millisecondes écoulées depuis l'image précédente.
   On le convertit en secondes et on le BORNE à 0,05 s : si l'onglet
   était en pause, on évite un énorme "saut" de la pirogue ou des obstacles.
   ------------------------------------------------------------ */
function draw() {
  try {
    const dt = Math.min(deltaTime / 1000, 0.05);
    jeu.mettreAJour(dt, lireEntrees());

    push();
    scale(facteurEchelle);        // à partir d'ici, on dessine en unités logiques
    jeu.dessiner();
    pop();
  } catch (e) {
    // Filet de sécurité : une erreur ne doit pas figer la boucle d'animation.
    if (!erreurSignalee) {
      console.error('Erreur dans draw() :', e);
      erreurSignalee = true;
    }
    resetMatrix();
  }
}

/* ------------------------------------------------------------
   lireEntrees()
   But : lire clavier et doigt/souris, et les résumer en deux valeurs.
   Retour : {direction, cibleX}
     direction : -1 (gauche), 0, +1 (droite) d'après le clavier
     cibleX    : abscisse (monde logique) du doigt/souris appuyé, sinon null
   keyIsDown(code) : vrai tant qu'une touche est maintenue.
   Codes : LEFT_ARROW / RIGHT_ARROW (flèches) ; 81 = Q, 65 = A, 68 = D.
   ------------------------------------------------------------ */
function lireEntrees() {
  let direction = 0;
  if (keyIsDown(LEFT_ARROW) || keyIsDown(81) || keyIsDown(65)) direction -= 1;
  if (keyIsDown(RIGHT_ARROW) || keyIsDown(68)) direction += 1;

  let cibleX = null;
  if (touches.length > 0) {
    cibleX = touches[0].x / facteurEchelle;      // `touches` : liste des doigts posés
  } else if (mouseIsPressed) {
    cibleX = mouseX / facteurEchelle;            // souris : bouton enfoncé
  }
  return { direction: direction, cibleX: cibleX };
}

/* ------------------------------------------------------------
   gererAppui(px, py)
   But : traiter un appui (souris ou doigt) en coordonnées canevas.
   Retour : false si l'appui était sur le canevas (cela bloque le
            comportement par défaut du navigateur : défilement, etc.),
            true sinon (la page garde son comportement normal).
   ------------------------------------------------------------ */
function gererAppui(px, py) {
  if (px < 0 || px > width || py < 0 || py > height) return true;   // hors du canevas
  // Sur certains appareils, un toucher déclenche aussi un "clic" simulé :
  // on ignore le second événement s'il arrive tout de suite après le premier.
  if (millis() - dernierAppui < 350) return false;
  dernierAppui = millis();
  jeu.appuyer(px / facteurEchelle, py / facteurEchelle);            // division : retour au monde logique
  return false;
}

/* Fonctions appelées automatiquement par p5 : */
function mousePressed() {
  return gererAppui(mouseX, mouseY);
}

function touchStarted() {
  if (touches.length > 0) return gererAppui(touches[0].x, touches[0].y);
  return true;
}

/* ------------------------------------------------------------
   keyPressed() : appelée une fois à chaque pression de touche.
   Variables p5 : key (le caractère), keyCode (le code de la touche).
   ------------------------------------------------------------ */
function keyPressed() {
  jeu.sons.activer();
  if (keyCode === ENTER || keyCode === 32) {          // 32 = barre d'espace
    jeu.actionPrincipale();
  }
  if (key === 'm' || key === 'M') {
    jeu.sons.basculerMuet();
  }
  // Pour les flèches et l'espace, on empêche le défilement de la page.
  if (keyCode === LEFT_ARROW || keyCode === RIGHT_ARROW ||
      keyCode === UP_ARROW || keyCode === DOWN_ARROW || keyCode === 32) {
    return false;
  }
}

/* ------------------------------------------------------------
   windowResized() : adapte le canevas si la fenêtre change
   (rotation du téléphone...). Le jeu garde son monde logique.
   ------------------------------------------------------------ */
function windowResized() {
  const t = calculerTaille();
  resizeCanvas(t.w, t.h);
  facteurEchelle = t.w / LARGEUR_JEU;
}