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/camera.js · 4.5 Ko
/* ==========================================================================
* js/camera.js — LA « CAMÉRA » : vues, transitions douces, rotation auto
* --------------------------------------------------------------------------
* Zdog n'a pas de caméra : pour changer de point de vue, on FAIT TOURNER LA
* SCÈNE ENTIÈRE (illo.rotate). Ce fichier gère trois comportements :
*
* 1. allerVers('face' | 'cote' | 'dessus') : une transition animée avec
* easeInOut (démarrage et arrivée en douceur) ;
* 2. basculerAuto() : une rotation continue autour de la maison ;
* 3. arreter() : on coupe tout (appelé quand l'utilisateur glisse).
*
* La caméra ne dessine rien : on appelle camera.mettreAJour(dt) à chaque
* image depuis la boucle d'animation (main.js).
*
* Dépend de : Zdog, Maison.VUES, Maison.CAMERA, Maison.INCLINAISON_AUTO.
* ========================================================================== */
(function () {
'use strict';
var TAU = Zdog.TAU;
/**
* Fabrique une caméra pour une illustration.
*
* @param {Zdog.Illustration} illo La scène à faire tourner.
* @param {function(string)} [quandVueChange] Rappel appelé avec un texte
* décrivant l'état (« face », « rotation automatique »…).
* @returns {Object} La caméra, avec ses méthodes.
*/
function creerCamera(illo, quandVueChange) {
var reglages = Maison.CAMERA;
// L'état de la caméra. On le réutilise tout le temps : AUCUN nouvel objet
// n'est créé dans la boucle d'animation (bon pour les performances).
var etat = {
auto: false, // rotation automatique active ?
enTransition: false,
t: 0, // progression de la transition, de 0 à 1
departX: 0, departY: 0,
arriveeX: 0, arriveeY: 0,
};
/** Prévient l'interface du nouvel état, si un rappel a été fourni. */
function annoncer(texte) {
if (quandVueChange) { quandVueChange(texte); }
}
/**
* Lance une transition douce vers une des vues de Maison.VUES.
* @param {string} cle 'face', 'cote' ou 'dessus'.
*/
function allerVers(cle) {
var vue = Maison.VUES[cle];
if (!vue) { return; }
etat.auto = false;
etat.enTransition = true;
etat.t = 0;
etat.departX = illo.rotate.x;
etat.departY = illo.rotate.y;
etat.arriveeX = vue.x;
// CHEMIN LE PLUS COURT : si la scène a déjà tourné de 5 tours, on ne
// veut pas la faire revenir en arrière de 5 tours ! Zdog.modulo()
// ramène l'écart dans l'intervalle [-TAU/2 ; +TAU/2] (un demi-tour max).
var ecart = Zdog.modulo(vue.y - illo.rotate.y + TAU / 2, TAU) - TAU / 2;
etat.arriveeY = illo.rotate.y + ecart;
annoncer('vue de ' + vue.nom);
}
/** Active ou coupe la rotation automatique. @returns {boolean} le nouvel état. */
function basculerAuto() {
etat.auto = !etat.auto;
etat.enTransition = false;
annoncer(etat.auto ? 'rotation automatique' : 'vue libre');
return etat.auto;
}
/** Coupe transition et rotation auto (l'utilisateur prend la main). */
function arreter() {
etat.auto = false;
etat.enTransition = false;
annoncer('vue libre');
}
/**
* À appeler à chaque image.
* @param {number} dt Temps écoulé depuis l'image précédente, en secondes.
*/
function mettreAJour(dt) {
if (etat.enTransition) {
etat.t += dt / reglages.dureeTransition;
var alpha = Math.min(etat.t, 1);
// easeInOut transforme un avancement linéaire (0 -> 1) en avancement
// « doux » : lent au début, rapide au milieu, lent à la fin.
// Le 2e paramètre (3) est la puissance : plus grand = plus marqué.
var doux = Zdog.easeInOut(alpha, 3);
illo.rotate.x = Zdog.lerp(etat.departX, etat.arriveeX, doux);
illo.rotate.y = Zdog.lerp(etat.departY, etat.arriveeY, doux);
if (alpha >= 1) { etat.enTransition = false; }
} else if (etat.auto) {
illo.rotate.y += reglages.vitesseAuto * dt; // tourne en continu
// L'inclinaison se rapproche doucement de la valeur de confort.
illo.rotate.x += (Maison.INCLINAISON_AUTO - illo.rotate.x) * Math.min(dt * 2, 1);
}
}
return {
allerVers: allerVers,
basculerAuto: basculerAuto,
arreter: arreter,
mettreAJour: mettreAJour,
estAuto: function () { return etat.auto; },
};
}
Maison.creerCamera = creerCamera;
})();