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/maison.js · 10.2 Ko
/* ==========================================================================
* js/maison.js — LE CORPS DE LA MAISON : murs, fenêtres, portes et toit
* --------------------------------------------------------------------------
* Fonction fabrique : Maison.creerCorps(parent, facade) construit
* - le soubassement (petit socle en pierre) ;
* - le rez-de-chaussée (une boîte) ;
* - l'étage (une boîte moins profonde : devant, il y aura la véranda) ;
* - les fenêtres et les portes ;
* - le toit à deux pans en tôle, avec ses deux pignons triangulaires.
*
* Croquis vu de côté (y vers le bas, donc les hauteurs sont NÉGATIVES) :
*
* faîtage y = -136
* /\
* / \ toit
* -------/----\------- bords du toit y = -99
* | étage | de y = -99 à -52
* |-------------| plancher y = -52
* | rez-de-ch. | de y = -52 à -6
* |_____________| socle de y = -6 à 0 (le sol)
*
* Dépend de : Zdog, Maison.DIM, Maison.COULEURS, Maison.peindreBoite,
* Maison.creerFenetre, Maison.nuancer (config.js et outils.js).
* ========================================================================== */
(function () {
'use strict';
var TAU = Zdog.TAU;
/**
* Construit les murs, ouvertures et le toit.
*
* @param {Zdog.Anchor} parent Où accrocher la maison (un Group).
* @param {Object} facade Un élément de Maison.FACADES (clé « mur » = couleur).
* @returns {Object} { rez, etage, pignons } : les pièces qu'il faudra repeindre
* quand l'utilisateur change la couleur de la façade.
*/
function creerCorps(parent, facade) {
var D = Maison.DIM;
var C = Maison.COULEURS;
// ---- Calculs de hauteurs (rappel : le haut est NÉGATIF) ----
var yHautSocle = -D.soubassement; // -6
var yHautRez = yHautSocle - D.hauteurRez; // -52
var yHautEtage = yHautRez - D.hauteurEtage; // -99
var zAvant = D.profondeur / 2; // +40 (côté spectateur)
var zArriere = -D.profondeur / 2; // -40
var zAvantEtage = zArriere + D.profondeurEtage; // +14 : façade de l'étage
// 1) LE SOUBASSEMENT ----------------------------------------------------
// Une boîte plate, un peu plus large que la maison, en pierre grise.
// Une Box est centrée sur sa position (translate) : son centre vertical
// est donc à -3 pour couvrir de y = -6 à y = 0.
new Zdog.Box({
addTo: parent,
width: D.largeur + 6,
height: D.soubassement,
depth: D.profondeur + 6,
translate: { y: -D.soubassement / 2 },
stroke: 1,
color: C.pierre,
topFace: Maison.nuancer(C.pierre, 0.2),
});
// 2) LE REZ-DE-CHAUSSÉE -------------------------------------------------
// Centre de la boîte = milieu entre le haut du socle (-6) et le plancher (-52).
var rez = new Zdog.Box({
addTo: parent,
width: D.largeur,
height: D.hauteurRez,
depth: D.profondeur,
translate: { y: (yHautSocle + yHautRez) / 2 },
stroke: 1,
color: facade.mur,
});
Maison.peindreBoite(rez, facade.mur);
// 3) L'ÉTAGE ------------------------------------------------------------
// Moins profond que le rez-de-chaussée : il part de l'arrière (z = -40)
// et s'arrête à z = +14. Son centre en z est donc au milieu : -13.
var etage = new Zdog.Box({
addTo: parent,
width: D.largeur,
height: D.hauteurEtage,
depth: D.profondeurEtage,
translate: { y: (yHautRez + yHautEtage) / 2, z: (zArriere + zAvantEtage) / 2 },
stroke: 1,
color: facade.mur,
});
Maison.peindreBoite(etage, facade.mur);
// 4) FENÊTRES ET PORTES DU REZ-DE-CHAUSSÉE ------------------------------
// On pose chaque ouverture 0,3 unité DEVANT le mur pour qu'elle ne soit
// pas « mangée » par lui (sinon Zdog hésiterait sur qui dessiner d'abord).
var xMur = D.largeur / 2 + 0.3;
var yRez = (yHautSocle + yHautRez) / 2 + 1; // milieu du rez, un peu plus bas
Maison.creerFenetre(parent, { x: -44, y: yRez, z: zAvant + 0.3, rotY: 0, volets: true });
Maison.creerFenetre(parent, { x: 52, y: yRez, z: zAvant + 0.3, rotY: 0, largeur: 12 });
// La porte d'entrée : un simple rectangle brun (largeur 18, hauteur 34)
// dont le bas touche le socle (y = -6) : son centre est à -6 - 17 = -23.
new Zdog.Rect({
addTo: parent, width: 18, height: 34, stroke: 1, fill: true,
color: C.boisFonce, backface: false,
translate: { x: -12, y: yHautSocle - 17, z: zAvant + 0.3 },
});
// Un petit bouton de porte : un point épais jaune.
new Zdog.Shape({
addTo: parent, stroke: 2, color: '#e8c15a', backface: false,
translate: { x: -6, y: yHautSocle - 17, z: zAvant + 0.8 },
});
// Fenêtres sur les côtés (rotY = ±TAU/4) et à l'arrière (rotY = TAU/2).
Maison.creerFenetre(parent, { x: xMur, y: yRez, z: 0, rotY: TAU / 4 });
Maison.creerFenetre(parent, { x: -xMur, y: yRez, z: 0, rotY: -TAU / 4 });
Maison.creerFenetre(parent, { x: -30, y: yRez, z: zArriere - 0.3, rotY: TAU / 2 });
Maison.creerFenetre(parent, { x: 30, y: yRez, z: zArriere - 0.3, rotY: TAU / 2 });
// 5) FENÊTRES ET PORTE DE L'ÉTAGE ---------------------------------------
var yEtage = (yHautRez + yHautEtage) / 2 + 1; // milieu de l'étage
var zFacadeEtage = zAvantEtage + 0.3; // devant le mur de l'étage
Maison.creerFenetre(parent, { x: -40, y: yEtage, z: zFacadeEtage, rotY: 0, volets: true });
Maison.creerFenetre(parent, { x: 40, y: yEtage, z: zFacadeEtage, rotY: 0, volets: true });
// Porte-fenêtre de l'étage : une porte vitrée qui donne sur la véranda.
new Zdog.Rect({
addTo: parent, width: 20, height: 36, stroke: 1, fill: true,
color: C.boisFonce, backface: false,
translate: { y: yHautRez - 18, z: zFacadeEtage },
});
new Zdog.Rect({
addTo: parent, width: 14, height: 28, stroke: 1, fill: true,
color: C.vitre, backface: false,
translate: { y: yHautRez - 19, z: zFacadeEtage + 0.4 },
});
Maison.creerFenetre(parent, { x: xMur, y: yEtage, z: -13, rotY: TAU / 4 });
Maison.creerFenetre(parent, { x: -xMur, y: yEtage, z: -13, rotY: -TAU / 4 });
Maison.creerFenetre(parent, { x: -30, y: yEtage, z: zArriere - 0.3, rotY: TAU / 2 });
Maison.creerFenetre(parent, { x: 30, y: yEtage, z: zArriere - 0.3, rotY: TAU / 2 });
// 6) LE TOIT ------------------------------------------------------------
var pignons = creerToit(parent, facade, yHautEtage);
return { rez: rez, etage: etage, pignons: pignons };
}
/**
* Construit le toit à deux pans (« en bâtière ») et les deux pignons.
*
* Un « pan » est un quadrilatère : on le dessine avec un Shape dont le path
* contient 4 points 3D. Le faîtage (la crête) est à z = 0, les bords bas
* (les égouts) sont à l'avant et à l'arrière.
*
* @param {Zdog.Anchor} parent Où accrocher le toit.
* @param {Object} facade Pour colorer les pignons comme les murs.
* @param {number} yEgout Hauteur (négative) du haut des murs de l'étage.
* @returns {Zdog.Shape[]} Les deux pignons (à repeindre au changement de façade).
*/
function creerToit(parent, facade, yEgout) {
var D = Maison.DIM;
var C = Maison.COULEURS;
var demiLong = D.largeur / 2 + D.debordToit; // demi-longueur du toit (x)
var zEgout = D.profondeur / 2 + D.debordToit; // bord avant du toit : +44
var yE = yEgout + 1; // bords bas du toit
var yF = yE - D.hauteurToit; // faîtage (crête)
// On ajoute chaque pan avec ses nervures dans un Group : l'ordre de dessin
// est alors garanti (d'abord le pan, ensuite les nervures par-dessus).
[{ z: zEgout, couleur: C.toit }, { z: -zEgout, couleur: C.toitArriere }].forEach(function (pan) {
var groupe = new Zdog.Group({ addTo: parent });
// Le pan de toit : 4 coins (bas gauche, bas droite, haut droite, haut gauche).
new Zdog.Shape({
addTo: groupe,
path: [
{ x: -demiLong, y: yE, z: pan.z },
{ x: demiLong, y: yE, z: pan.z },
{ x: demiLong, y: yF, z: 0 },
{ x: -demiLong, y: yF, z: 0 },
],
stroke: 3,
fill: true,
color: pan.couleur,
});
// Les nervures de la tôle ondulée : une ligne tous les 8 unités.
// (Une boucle for évite d'écrire 16 formes à la main.)
for (var x = -demiLong + 8; x < demiLong; x += 8) {
new Zdog.Shape({
addTo: groupe,
path: [{ x: x, y: yE, z: pan.z }, { x: x, y: yF, z: 0 }],
closed: false,
stroke: 0.8,
color: Maison.nuancer(pan.couleur, -0.25),
});
}
});
// La crête du toit : un trait épais et sombre tout le long du faîtage.
new Zdog.Shape({
addTo: parent,
path: [{ x: -demiLong, y: yF, z: 0 }, { x: demiLong, y: yF, z: 0 }],
closed: false,
stroke: 4,
color: C.faitage,
});
// Les pignons : deux triangles qui ferment le toit à gauche et à droite,
// juste à l'intérieur du débord (x = ±(largeur/2 + 2)).
var pignons = [];
[-1, 1].forEach(function (cote) {
var x = cote * (D.largeur / 2 + 2);
pignons.push(new Zdog.Shape({
addTo: parent,
path: [
{ x: x, y: yE, z: -zEgout + 2 },
{ x: x, y: yE, z: zEgout - 2 },
{ x: x, y: yF, z: 0 },
],
stroke: 2,
fill: true,
color: Maison.nuancer(facade.mur, -0.1),
}));
});
return pignons;
}
/**
* Repeint la maison avec une nouvelle façade (sans rien reconstruire).
*
* @param {Object} corps L'objet renvoyé par creerCorps().
* @param {Object} facade Un élément de Maison.FACADES.
*/
function peindreFacade(corps, facade) {
Maison.peindreBoite(corps.rez, facade.mur);
Maison.peindreBoite(corps.etage, facade.mur);
corps.pignons.forEach(function (p) {
p.color = Maison.nuancer(facade.mur, -0.1);
});
}
Maison.creerCorps = creerCorps;
Maison.peindreFacade = peindreFacade;
})();