Feature: books start levitating

This commit is contained in:
Dejvino
2025-11-16 16:32:13 +01:00
parent 6e2a59ce77
commit 2e1e6bddfa
3 changed files with 73 additions and 0 deletions
+60
View File
@@ -88,6 +88,65 @@ function updateVcr() {
}
}
function updateBooks() {
const LEVITATE_CHANCE = 0.001; // Chance for a resting book to start levitating per frame
const LEVITATE_DURATION_MIN = 100; // frames
const LEVITATE_DURATION_MAX = 300; // frames
const LEVITATE_AMPLITUDE = 0.02; // Max vertical displacement
const LEVITATE_SPEED_FACTOR = 0.03; // Speed of oscillation
const START_RATE = 0.05; // How quickly a book starts to levitate
const RETURN_RATE = 0.1; // How quickly a book returns to original position
const START_DURATION = 120; // frames for the starting transition
const levitation = state.bookLevitation;
// Manage the global levitation state
if (levitation.state === 'resting') {
if (Math.random() < LEVITATE_CHANCE) {
levitation.state = 'starting';
levitation.timer = START_DURATION;
}
} else if (levitation.state === 'starting') {
levitation.timer--;
if (levitation.timer <= 0) {
levitation.state = 'levitating';
levitation.timer = LEVITATE_DURATION_MIN + Math.random() * (LEVITATE_DURATION_MAX - LEVITATE_DURATION_MIN);
}
} else if (levitation.state === 'levitating') {
levitation.timer--;
if (levitation.timer <= 0) {
levitation.state = 'returning';
}
}
// Animate books based on the global state
let allBooksReturned = true;
state.books.forEach(book => {
const data = book.userData;
if (levitation.state === 'starting') {
allBooksReturned = false;
book.position.y = THREE.MathUtils.lerp(book.position.y, data.originalY + LEVITATE_AMPLITUDE/2, START_RATE);
data.oscillationTime = 0;
} else if (levitation.state === 'levitating') {
allBooksReturned = false;
data.oscillationTime += LEVITATE_SPEED_FACTOR;
data.levitateOffset = Math.sin(data.oscillationTime) * LEVITATE_AMPLITUDE;
book.position.y = data.originalY + data.levitateOffset + LEVITATE_AMPLITUDE/2;
} else if (levitation.state === 'returning') {
book.position.y = THREE.MathUtils.lerp(book.position.y, data.originalY, RETURN_RATE);
data.levitateOffset = book.position.y - data.originalY;
if (Math.abs(data.levitateOffset) > 0.001) {
allBooksReturned = false;
}
}
});
if (levitation.state === 'returning' && allBooksReturned) {
levitation.state = 'resting';
}
}
// --- Animation Loop ---
export function animate() {
requestAnimationFrame(animate);
@@ -98,6 +157,7 @@ export function animate() {
updateScreenLight();
updateVideo();
updateVcr();
updateBooks();
updateDoor();
// RENDER!