Annuaire › Code ouvert
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/obstacle.js · 4.8 Ko
/* ============================================================
obstacle.js - la classe Obstacle (rochers et vagues)
============================================================
Un seul moule pour deux sortes d'obstacles, distingués par la
propriété `type` :
'rocher' : un rocher à fleur d'eau, immobile par rapport à l'eau ;
'vague' : une vague déferlante, large, qui dérive un peu de côté.
Toucher un obstacle fait perdre une vie.
============================================================ */
class Obstacle {
/* ----------------------------------------------------------
constructor(type, x, y)
Paramètres :
type : 'rocher' ou 'vague'
x, y : position de départ (centre)
---------------------------------------------------------- */
constructor(type, x, y) {
this.type = type;
this.x = x;
this.y = y;
this.mort = false; // passe à true après une collision
if (type === 'rocher') {
this.rayon = random(18, 28);
this.rx = this.rayon; // demi-largeur (pour éviter les chevauchements au spawn)
this.vx = 0;
// Forme irrégulière : 9 sommets autour du centre, chacun à une
// distance un peu différente. On les calcule UNE fois (pas à chaque image).
this.sommets = [];
const n = 9;
for (let i = 0; i < n; i++) {
const a = i * TWO_PI / n;
const r = this.rayon * random(0.8, 1.15);
this.sommets.push({ x: cos(a) * r, y: sin(a) * r });
}
} else {
this.largeur = random(70, 110);
this.rx = this.largeur / 2;
this.vx = random(-25, 25); // dérive latérale lente (unités par seconde)
}
}
/* ----------------------------------------------------------
mettreAJour(dt, vitesse)
But : déplacer l'obstacle avec le défilement de l'eau.
Paramètres : dt = secondes écoulées ; vitesse = vitesse de l'eau
---------------------------------------------------------- */
mettreAJour(dt, vitesse) {
this.y += vitesse * dt;
if (this.type === 'vague') {
this.x += this.vx * dt;
// Rebond sur les rives : on inverse la vitesse horizontale.
const gauche = RIVE + 8 + this.rx;
const droite = LARGEUR_JEU - RIVE - 8 - this.rx;
if (this.x < gauche || this.x > droite) {
this.vx = -this.vx;
this.x = constrain(this.x, gauche, droite);
}
}
}
/* estSorti() : true si l'obstacle est passé sous l'écran. */
estSorti() {
return this.y > HAUTEUR_JEU + 60;
}
/* ----------------------------------------------------------
boite()
But : rectangle de collision (légèrement plus petit que le dessin).
Retour : {x, y, l, h}
---------------------------------------------------------- */
boite() {
if (this.type === 'rocher') {
const d = this.rayon * 1.5;
return { x: this.x - d / 2, y: this.y - d / 2, l: d, h: d };
}
return { x: this.x - this.largeur / 2 + 4, y: this.y - 18, l: this.largeur - 8, h: 20 };
}
/* dessiner() : appelle le bon dessin selon le type. */
dessiner() {
if (this.type === 'rocher') this.dessinerRocher();
else this.dessinerVague();
}
/* ----------------------------------------------------------
dessinerRocher()
But : un anneau d'écume, puis le rocher (polygone gris) avec
une zone claire en haut à gauche (la lumière).
---------------------------------------------------------- */
dessinerRocher() {
push();
translate(this.x, this.y);
// Écume autour du rocher
noStroke();
fill(255, 255, 255, 110);
ellipse(0, 2, this.rayon * 3, this.rayon * 2.6);
// Rocher : polygone fermé
fill(COULEURS.rocher);
stroke('#3f4348');
strokeWeight(2);
beginShape();
for (const s of this.sommets) vertex(s.x, s.y);
endShape(CLOSE);
// Reflet de lumière : même forme, plus petite, décalée et plus claire
noStroke();
fill(COULEURS.rocherClair);
beginShape();
for (const s of this.sommets) vertex(s.x * 0.55 - 3, s.y * 0.55 - 4);
endShape(CLOSE);
pop();
}
/* ----------------------------------------------------------
dessinerVague()
But : une vague déferlante : demi-ellipse bleue + crête blanche.
arc(x, y, l, h, début, fin, mode) : de PI à TWO_PI on obtient la
moitié HAUTE de l'ellipse.
---------------------------------------------------------- */
dessinerVague() {
push();
translate(this.x, this.y);
noStroke();
fill(COULEURS.vague);
arc(0, 0, this.largeur, 46, PI, TWO_PI, CHORD);
noFill();
stroke(255);
strokeWeight(5);
strokeCap(ROUND);
arc(0, 0, this.largeur, 46, PI, TWO_PI); // crête d'écume
strokeWeight(2);
stroke(255, 255, 255, 170);
arc(0, 4, this.largeur * 0.7, 28, PI + 0.2, TWO_PI - 0.2); // 2e ligne d'écume
pop();
}
}