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/outils.js · 6.5 Ko
/* ==========================================================================
* js/outils.js — PETITES FONCTIONS UTILITAIRES
* --------------------------------------------------------------------------
* Ces fonctions n'ont rien de « 3D » : elles servent aux autres fichiers.
* - nuancer() : éclaircir ou assombrir une couleur hexadécimale ;
* - generateurAleatoire() : un hasard REPRODUCTIBLE (même graine = mêmes valeurs) ;
* - fixerOrdreSol() : forcer une forme à être dessinée en premier ;
* - peindreBoite() : colorer les 6 faces d'une boîte avec de la lumière simulée ;
* - creerFenetre() : fabrique une fenêtre complète (cadre, vitre, volets).
* Dépend de : Zdog, Maison.COULEURS (config.js).
* ========================================================================== */
(function () {
'use strict';
/**
* Éclaircit (facteur > 0) ou assombrit (facteur < 0) une couleur '#rrggbb'.
* Principe : on mélange la couleur avec du blanc (éclaircir) ou du noir (assombrir).
*
* @param {string} hex Couleur de départ, par exemple '#f2d27a'.
* @param {number} facteur Entre -1 (noir) et +1 (blanc). 0 = inchangé.
* @returns {string} La nouvelle couleur au format '#rrggbb'.
*/
function nuancer(hex, facteur) {
// '#f2d27a' -> trois nombres de 0 à 255 (rouge, vert, bleu)
var n = parseInt(hex.slice(1), 16);
var canaux = [(n >> 16) & 255, (n >> 8) & 255, n & 255];
var cible = facteur >= 0 ? 255 : 0; // blanc ou noir
var force = Math.abs(facteur);
var texte = '#';
for (var i = 0; i < 3; i++) {
var v = Math.round(canaux[i] + (cible - canaux[i]) * force);
texte += (v < 16 ? '0' : '') + v.toString(16); // toujours 2 chiffres hexa
}
return texte;
}
/**
* Générateur de nombres pseudo-aléatoires reproductible (algorithme « mulberry32 »).
* Math.random() donnerait un arbre différent à chaque chargement ; ici, avec
* la même graine, on obtient TOUJOURS le même arbre.
*
* @param {number} graine Un entier de départ.
* @returns {function(): number} Fonction qui renvoie un nombre entre 0 et 1.
*/
function generateurAleatoire(graine) {
var a = graine >>> 0;
return function () {
a = (a + 0x6D2B79F5) >>> 0;
var t = a;
t = Math.imul(t ^ (t >>> 15), t | 1);
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
};
}
/**
* Force une forme à être dessinée AVANT toutes les autres (comme un sol).
*
* Pourquoi ? Zdog dessine les formes de la plus lointaine à la plus proche,
* en comparant le « z » du CENTRE de chaque forme. Un très grand sol plat
* a son centre au milieu de la scène : les objets situés derrière lui
* seraient donc cachés à tort ! On triche en remplaçant la méthode
* updateSortValue de CETTE forme par une valeur très basse.
*
* @param {Zdog.Shape} forme La forme à placer au fond.
* @param {number} rang 0 = tout au fond, 1 = juste au-dessus, etc.
*/
function fixerOrdreSol(forme, rang) {
forme.updateSortValue = function () {
this.sortValue = -1000000 + rang;
};
}
/**
* Colore les faces d'une Zdog.Box en simulant un éclairage venant du haut
* et de la droite : le dessus est plus clair, l'arrière plus sombre.
* (Affecter box.frontFace = '#xxxxxx' met à jour la couleur de la face.)
*
* @param {Zdog.Box} boite La boîte à peindre.
* @param {string} couleur Couleur de base du mur.
*/
function peindreBoite(boite, couleur) {
boite.frontFace = couleur;
boite.rearFace = nuancer(couleur, -0.22);
boite.leftFace = nuancer(couleur, -0.14);
boite.rightFace = nuancer(couleur, -0.06);
boite.topFace = nuancer(couleur, 0.25);
boite.bottomFace = nuancer(couleur, -0.3);
}
/**
* Fabrique une fenêtre : cadre + vitre + croisillons (+ volets en option).
*
* On utilise un Group (et pas un simple Anchor) : un Group dessine ses
* enfants DANS L'ORDRE où on les a ajoutés. Ainsi la vitre est toujours
* dessinée par-dessus le cadre, quel que soit l'angle de vue.
*
* @param {Zdog.Anchor} parent Où accrocher la fenêtre.
* @param {Object} o Options : x, y, z (position), rotY (orientation, en radians :
* 0 = vers l'avant, TAU/4 = vers la droite, -TAU/4 = vers la gauche,
* TAU/2 = vers l'arrière), largeur, hauteur, volets (booléen).
* @returns {Zdog.Group} Le groupe de la fenêtre.
*/
function creerFenetre(parent, o) {
var C = Maison.COULEURS;
var l = o.largeur || 14;
var h = o.hauteur || 18;
// Le groupe est placé sur le mur, tourné face à l'extérieur.
var g = new Zdog.Group({
addTo: parent,
translate: { x: o.x, y: o.y, z: o.z },
rotate: { y: o.rotY || 0 },
});
// 1) Le cadre en bois : un rectangle plein, un peu plus grand que la vitre.
// backface: false => invisible quand on le regarde « par derrière ».
new Zdog.Rect({
addTo: g, width: l + 4, height: h + 4, stroke: 1, fill: true,
color: C.boisFonce, backface: false,
});
// 2) La vitre, très légèrement devant le cadre (z = 0,4).
new Zdog.Rect({
addTo: g, width: l, height: h, stroke: 1, fill: true,
color: C.vitre, translate: { z: 0.4 }, backface: false,
});
// 3) Les croisillons : deux traits fins, vertical puis horizontal.
new Zdog.Shape({
addTo: g, path: [{ y: -h / 2 }, { y: h / 2 }], closed: false,
stroke: 1.2, color: C.boisFonce, translate: { z: 0.8 }, backface: false,
});
new Zdog.Shape({
addTo: g, path: [{ x: -l / 2 }, { x: l / 2 }], closed: false,
stroke: 1.2, color: C.boisFonce, translate: { z: 0.8 }, backface: false,
});
// 4) Les volets : deux petits rectangles de chaque côté (facultatif).
if (o.volets) {
var decalage = l / 2 + 2 + 3.5; // moitié de la fenêtre + cadre + moitié du volet
[-1, 1].forEach(function (cote) { // -1 = gauche, +1 = droite
new Zdog.Rect({
addTo: g, width: 7, height: h + 4, stroke: 1, fill: true,
color: C.volets, translate: { x: cote * decalage, z: 0.4 }, backface: false,
});
});
}
return g;
}
// On expose les fonctions dans l'espace de noms Maison.
Maison.nuancer = nuancer;
Maison.generateurAleatoire = generateurAleatoire;
Maison.fixerOrdreSol = fixerOrdreSol;
Maison.peindreBoite = peindreBoite;
Maison.creerFenetre = creerFenetre;
})();