Feature: books start levitating
This commit is contained in:
@@ -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!
|
||||
|
||||
Reference in New Issue
Block a user