Feature: add rats running on a path from a hole around the room
This commit is contained in:
parent
dceb37a8dd
commit
43e746a5a0
92
magic-mirror/src/scene/rat.js
Normal file
92
magic-mirror/src/scene/rat.js
Normal file
@ -0,0 +1,92 @@
|
||||
import * as THREE from 'three';
|
||||
import { state } from '../state.js';
|
||||
|
||||
const SLEEP_WAIT = 1;
|
||||
|
||||
export class Rat {
|
||||
constructor(path, initialDelay) {
|
||||
this.path = path;
|
||||
this.speed = 0.002 + Math.random() * 0.002;
|
||||
this.progress = -initialDelay; // Start with a negative progress as a delay
|
||||
|
||||
// The rat's body
|
||||
const bodyGeo = new THREE.CapsuleGeometry(0.02, 0.07, 4, 8);
|
||||
const bodyMat = new THREE.MeshPhongMaterial({ color: 0x2a1d1d, shininess: 10 });
|
||||
this.mesh = new THREE.Mesh(bodyGeo, bodyMat);
|
||||
this.mesh.castShadow = true;
|
||||
this.mesh.rotation.z = Math.PI / 2;
|
||||
this.mesh.rotation.y = Math.PI / 2;
|
||||
this.mesh.position.y = 0;
|
||||
|
||||
this.actor = new THREE.Group();
|
||||
this.actor.visible = false; // Start invisible
|
||||
this.actor.add(this.mesh);
|
||||
|
||||
state.scene.add(this.actor);
|
||||
}
|
||||
|
||||
update() {
|
||||
this.progress += this.speed;
|
||||
|
||||
// If the rat has finished its path, reset with a new delay
|
||||
if (this.progress > 1.0) {
|
||||
this.progress = -(Math.random() * SLEEP_WAIT); // wait some seconds before going again
|
||||
this.actor.visible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't do anything if we are in the delay period
|
||||
if (this.progress < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// First time it becomes visible
|
||||
if (!this.actor.visible) {
|
||||
this.actor.visible = true;
|
||||
}
|
||||
|
||||
// Move along the path
|
||||
const position = this.path.getPointAt(this.progress);
|
||||
this.actor.position.copy(position);
|
||||
|
||||
// Orient along the path
|
||||
const tangent = this.path.getTangentAt(this.progress).normalize();
|
||||
const lookAtPosition = position.clone().add(tangent);
|
||||
this.actor.lookAt(lookAtPosition);
|
||||
}
|
||||
}
|
||||
|
||||
export function createRats(x, y, z, rotY) {
|
||||
// --- 9.5 Rat Hole ---
|
||||
const holeGeo = new THREE.CircleGeometry(0.15, 16);
|
||||
const holeMat = new THREE.MeshBasicMaterial({ color: 0x000000 });
|
||||
const ratHole = new THREE.Mesh(holeGeo, holeMat);
|
||||
ratHole.position.set(x, y + 0.1, z);
|
||||
ratHole.rotation.y = rotY;
|
||||
state.scene.add(ratHole);
|
||||
|
||||
// Define a path for the rats to follow
|
||||
const ratPath = new THREE.CatmullRomCurve3([
|
||||
new THREE.Vector3(x, y, z), // Start at the hole
|
||||
new THREE.Vector3(x-2.0, 0, z),
|
||||
new THREE.Vector3(0, 0, 1.0),
|
||||
new THREE.Vector3(-1.0, 0, 1.8),
|
||||
new THREE.Vector3(-1.5, 0, 0.5),
|
||||
new THREE.Vector3(0.5, 0, 0.5),
|
||||
new THREE.Vector3(1.8, 0, 1.0),
|
||||
new THREE.Vector3(x, y, z), // End at the hole
|
||||
]);
|
||||
|
||||
// Create a few rats with different starting delays
|
||||
state.rats.push(new Rat(ratPath, 0.5));
|
||||
state.rats.push(new Rat(ratPath, 3.0));
|
||||
state.rats.push(new Rat(ratPath, 5.0));
|
||||
}
|
||||
|
||||
export function updateRats() {
|
||||
if (!state.rats || state.rats.length === 0) return;
|
||||
|
||||
state.rats.forEach(rat => {
|
||||
rat.update();
|
||||
});
|
||||
}
|
||||
@ -6,6 +6,7 @@ import { createMagicMirror } from './magic-mirror.js';
|
||||
import { createFireplace } from './fireplace.js';
|
||||
import { createTable } from './table.js';
|
||||
import { createCauldron } from './cauldron.js';
|
||||
import { createRats } from './rat.js';
|
||||
import { PictureFrame } from './PictureFrame.js';
|
||||
import painting1 from '/textures/painting1.jpg';
|
||||
import painting2 from '/textures/painting2.jpg';
|
||||
@ -140,6 +141,8 @@ export function createSceneObjects() {
|
||||
// --- 9. Fireplace ---
|
||||
createFireplace(state.roomSize / 2 - 0.5, -1, -Math.PI / 2);
|
||||
|
||||
createRats(state.roomSize/2 - 0.01, 0, 0.37, -Math.PI / 2);
|
||||
|
||||
createBookshelf(-state.roomSize/2 + 0.2, state.roomSize/2*0.2, Math.PI/2, 0);
|
||||
createBookshelf(-state.roomSize/2 + 0.2, state.roomSize/2*0.7, Math.PI/2, 0);
|
||||
createBookshelf(-state.roomSize/2 * 0.7, -state.roomSize/2+0.3, 0, 1);
|
||||
@ -151,6 +154,7 @@ export function createSceneObjects() {
|
||||
imageUrls: [painting1, painting2],
|
||||
rotationY: Math.PI / 2
|
||||
});
|
||||
|
||||
state.pictureFrames.push(pictureFrame);
|
||||
|
||||
const pictureFrame2 = new PictureFrame(state.scene, {
|
||||
|
||||
@ -54,6 +54,7 @@ export function initState() {
|
||||
loader: new THREE.TextureLoader(),
|
||||
landingSurfaces: [],
|
||||
crawlSurfaces: [], // Surfaces for spiders to crawl on
|
||||
rats: [], // Array to hold rats
|
||||
bookLevitation: {
|
||||
state: 'resting', // 'resting', 'levitating', 'returning'
|
||||
timer: 0,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user