From 48dbd14541d7e3471ddd23e6c57e38501a4062c0 Mon Sep 17 00:00:00 2001 From: MVA Global Fret Date: Tue, 5 May 2026 12:15:59 +0200 Subject: [PATCH] =?UTF-8?q?Plane=20drifts=20forward=20at=20cruise=20speed,?= =?UTF-8?q?=20reverse=20trajectory=20right=E2=86=92left?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two adjustments to the intro plane: 1. Autonomous cruise speed. Adds BASE_SPEED (1/28 per second of wallclock) to targetProgress on every frame, so the plane crosses the screen on its own in ~28 s without any input. Mouse motion still adds a boost (one full traversal per ~4500 px of cursor travel), which feels like the plane "speeding up" when the user interacts. Time delta clamped to 0.1 s so the plane doesn't jump forward after the tab returns from background. 2. Reverse direction. Plane now enters from upper-right (x = +16), traverses to upper-left (x = -16), nose pointing -X. Wrapper rot.y flipped to +π/2; px formula flipped; banking angles inverted so the plane still rolls "into the turn" along its new direction. Co-Authored-By: Claude Opus 4.6 --- js/intro-scene.js | 53 ++++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/js/intro-scene.js b/js/intro-scene.js index 05ddd31..f6f2152 100644 --- a/js/intro-scene.js +++ b/js/intro-scene.js @@ -56,8 +56,9 @@ loader.load( wrapper.add(model); const targetSize = 8.5; wrapper.scale.setScalar(targetSize / Math.max(size.x, size.y, size.z)); - /* Pivote le modèle pour que le nez pointe vers la droite (+X) */ - wrapper.rotation.y = -Math.PI / 2; + /* Pivote le modèle pour que le nez pointe vers la gauche (-X) : + l'avion entre par la droite et sort par la gauche. */ + wrapper.rotation.y = Math.PI / 2; planeHolder.add(wrapper); }, undefined, @@ -65,17 +66,16 @@ loader.load( ); /* ── Souris ───────────────────────────────────────────────────────────── - La souris fait AVANCER l'avion sur sa trajectoire : on accumule la - distance parcourue par le curseur. Une fois que l'avion est sorti à - droite (progress = 1), il reste sorti — la souris ne le ramène pas. - - On garde aussi mouseX (0..1) pour la parallaxe légère de la photo. + L'avion avance automatiquement à vitesse de croisière (BASE_SPEED). + Bouger la souris ajoute un boost qui le pousse plus vite vers la fin. + Une fois sorti à droite (progress = 1), il reste sorti. */ -const FULL_DISTANCE = 3500; // pixels de souris pour traverser tout l'écran +const BASE_SPEED = 1 / 28; // 28 s pour traverser sans toucher la souris +const MOUSE_BOOST = 1 / 4500; // pixels de souris → progress (0..1) const mouse = { - targetProgress: 0, // accumulé, croissant - progress: 0, // suit avec lerp - px: 0.5, py: 0.5 // dernier point connu (parallaxe fond) + targetProgress: 0, + progress: 0, + px: 0.5, py: 0.5 }; let lastX = null, lastY = null; @@ -83,21 +83,21 @@ window.addEventListener('mousemove', (e) => { if (lastX !== null) { const dx = e.clientX - lastX; const dy = e.clientY - lastY; - mouse.targetProgress = Math.min(1, mouse.targetProgress + Math.hypot(dx, dy) / FULL_DISTANCE); + mouse.targetProgress = Math.min(1, mouse.targetProgress + Math.hypot(dx, dy) * MOUSE_BOOST); } lastX = e.clientX; lastY = e.clientY; mouse.px = e.clientX / window.innerWidth; mouse.py = e.clientY / window.innerHeight; }, { passive: true }); -/* Mobile : la rotation du device fait progresser l'avion */ +/* Mobile : la rotation du device pousse l'avion plus vite vers la fin */ let lastGamma = null, lastBeta = null; window.addEventListener('deviceorientation', (e) => { if (e.gamma == null || e.beta == null) return; if (lastGamma !== null) { const dg = e.gamma - lastGamma; const db = e.beta - lastBeta; - mouse.targetProgress = Math.min(1, mouse.targetProgress + Math.hypot(dg, db) / 90); + mouse.targetProgress = Math.min(1, mouse.targetProgress + Math.hypot(dg, db) / 120); } lastGamma = e.gamma; lastBeta = e.beta; mouse.px = Math.max(0, Math.min(1, (e.gamma + 30) / 60)); @@ -109,32 +109,37 @@ const root = document.documentElement; /* ── Render loop ───────────────────────────────────────────────────────── */ const clock = new THREE.Clock(); +let lastT = 0; function tick() { const t = clock.getElapsedTime(); + const dt = Math.min(0.1, t - lastT); // clamp pour éviter les bonds après onglet en arrière-plan + lastT = t; - /* Lerp doux vers la cible (progrès cumulé) */ + /* Avance autonome + cible cumulée par la souris, le tout limité à 1 */ + mouse.targetProgress = Math.min(1, mouse.targetProgress + BASE_SPEED * dt); + /* Lerp doux pour fluidifier */ mouse.progress += (mouse.targetProgress - mouse.progress) * 0.06; const p = mouse.progress; - /* Variables CSS pour la parallaxe légère de la photo de fond */ + /* Parallaxe légère de la photo de fond */ root.style.setProperty('--mx', ((mouse.px - 0.5) * 2).toFixed(4)); root.style.setProperty('--my', ((mouse.py - 0.5) * 2).toFixed(4)); - /* Trajectoire : - - p = 0 → arrive haut-gauche (hors champ) + /* Trajectoire droite → gauche : + - p = 0 → entre par la droite (hors champ) - p = 0.5 → traverse au centre haut - - p = 1 → sortie à droite (hors champ) + - p = 1 → sort par la gauche (hors champ) */ - const px = -16 + p * 32; - const py = 7 - p * 5; + const px = 16 - p * 32; + const py = 7 - p * 5; const bob = Math.sin(t * 0.9) * 0.12; planeHolder.position.set(px, py + bob, 0); - /* Banking subtil — penche en pivotant */ - const targetRoll = -0.18 - (p - 0.5) * 0.25; + /* Banking subtil — direction inversée par rapport à un vol gauche→droite */ + const targetRoll = 0.18 + (p - 0.5) * 0.25; const targetPitch = -0.18 - p * 0.10; - const targetYaw = (p - 0.5) * 0.10; + const targetYaw = -(p - 0.5) * 0.10; planeHolder.rotation.z += (targetRoll - planeHolder.rotation.z) * 0.08; planeHolder.rotation.x += (targetPitch - planeHolder.rotation.x) * 0.08; planeHolder.rotation.y += (targetYaw - planeHolder.rotation.y) * 0.08;