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 { createFireplace } from './fireplace.js';
|
||||||
import { createTable } from './table.js';
|
import { createTable } from './table.js';
|
||||||
import { createCauldron } from './cauldron.js';
|
import { createCauldron } from './cauldron.js';
|
||||||
|
import { createRats } from './rat.js';
|
||||||
import { PictureFrame } from './PictureFrame.js';
|
import { PictureFrame } from './PictureFrame.js';
|
||||||
import painting1 from '/textures/painting1.jpg';
|
import painting1 from '/textures/painting1.jpg';
|
||||||
import painting2 from '/textures/painting2.jpg';
|
import painting2 from '/textures/painting2.jpg';
|
||||||
@ -140,6 +141,8 @@ export function createSceneObjects() {
|
|||||||
// --- 9. Fireplace ---
|
// --- 9. Fireplace ---
|
||||||
createFireplace(state.roomSize / 2 - 0.5, -1, -Math.PI / 2);
|
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.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.2, state.roomSize/2*0.7, Math.PI/2, 0);
|
||||||
createBookshelf(-state.roomSize/2 * 0.7, -state.roomSize/2+0.3, 0, 1);
|
createBookshelf(-state.roomSize/2 * 0.7, -state.roomSize/2+0.3, 0, 1);
|
||||||
@ -151,6 +154,7 @@ export function createSceneObjects() {
|
|||||||
imageUrls: [painting1, painting2],
|
imageUrls: [painting1, painting2],
|
||||||
rotationY: Math.PI / 2
|
rotationY: Math.PI / 2
|
||||||
});
|
});
|
||||||
|
|
||||||
state.pictureFrames.push(pictureFrame);
|
state.pictureFrames.push(pictureFrame);
|
||||||
|
|
||||||
const pictureFrame2 = new PictureFrame(state.scene, {
|
const pictureFrame2 = new PictureFrame(state.scene, {
|
||||||
|
|||||||
@ -54,6 +54,7 @@ export function initState() {
|
|||||||
loader: new THREE.TextureLoader(),
|
loader: new THREE.TextureLoader(),
|
||||||
landingSurfaces: [],
|
landingSurfaces: [],
|
||||||
crawlSurfaces: [], // Surfaces for spiders to crawl on
|
crawlSurfaces: [], // Surfaces for spiders to crawl on
|
||||||
|
rats: [], // Array to hold rats
|
||||||
bookLevitation: {
|
bookLevitation: {
|
||||||
state: 'resting', // 'resting', 'levitating', 'returning'
|
state: 'resting', // 'resting', 'levitating', 'returning'
|
||||||
timer: 0,
|
timer: 0,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user