feat: Introduce footstep audio effects with context activation and set camera rotation order.
This commit is contained in:
@@ -6,6 +6,7 @@ import { PointerLockControls } from 'three/examples/jsm/controls/PointerLockCont
|
|||||||
export class Player {
|
export class Player {
|
||||||
constructor(camera, colliders) {
|
constructor(camera, colliders) {
|
||||||
this.camera = camera;
|
this.camera = camera;
|
||||||
|
this.camera.rotation.order = 'YXZ'; // Standard FPS rotation order to prevent gimbal lock
|
||||||
this.colliders = colliders;
|
this.colliders = colliders;
|
||||||
|
|
||||||
// Player stats
|
// Player stats
|
||||||
@@ -35,6 +36,14 @@ export class Player {
|
|||||||
this.battery = 100.0;
|
this.battery = 100.0;
|
||||||
this.baseDrain = 0.5; // Drain per second at base intensity
|
this.baseDrain = 0.5; // Drain per second at base intensity
|
||||||
|
|
||||||
|
// Animation
|
||||||
|
this.headBobTimer = 0;
|
||||||
|
this.lastStepTime = 0;
|
||||||
|
|
||||||
|
// Audio
|
||||||
|
this.ctx = new (window.AudioContext || window.webkitAudioContext)();
|
||||||
|
this.audioEnabled = false;
|
||||||
|
|
||||||
// Animation
|
// Animation
|
||||||
this.headBobTimer = 0;
|
this.headBobTimer = 0;
|
||||||
|
|
||||||
@@ -59,6 +68,12 @@ export class Player {
|
|||||||
|
|
||||||
setupInput() {
|
setupInput() {
|
||||||
const onKeyDown = (event) => {
|
const onKeyDown = (event) => {
|
||||||
|
// Resume Audio Context on first interaction
|
||||||
|
if (this.ctx && this.ctx.state === 'suspended') {
|
||||||
|
this.ctx.resume();
|
||||||
|
this.audioEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
switch (event.code) {
|
switch (event.code) {
|
||||||
case 'KeyW': this.moveForward = true; break;
|
case 'KeyW': this.moveForward = true; break;
|
||||||
case 'KeyA': this.moveLeft = true; break;
|
case 'KeyA': this.moveLeft = true; break;
|
||||||
@@ -166,8 +181,21 @@ export class Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep player on ground
|
// Keep player on ground (Base height)
|
||||||
this.camera.position.y = this.height;
|
const baseHeight = this.height;
|
||||||
|
playerPos.y = baseHeight;
|
||||||
|
|
||||||
|
// Audio Only Trigger
|
||||||
|
if (this.moveForward || this.moveBackward || this.moveLeft || this.moveRight) {
|
||||||
|
// Step every 0.6 seconds
|
||||||
|
this.lastStepTime += dt;
|
||||||
|
if (this.lastStepTime > 0.6) {
|
||||||
|
this.lastStepTime = 0;
|
||||||
|
this.playFootstep();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.lastStepTime = 0.5; // Ready to step properly next time
|
||||||
|
}
|
||||||
|
|
||||||
// Flashlight flicker effect (subtle) & Battery Logic
|
// Flashlight flicker effect (subtle) & Battery Logic
|
||||||
if (this.flashlight && this.flashlightOn) {
|
if (this.flashlight && this.flashlightOn) {
|
||||||
@@ -216,4 +244,39 @@ export class Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
playFootstep() {
|
||||||
|
if (!this.ctx) return;
|
||||||
|
|
||||||
|
const t = this.ctx.currentTime;
|
||||||
|
const osc = this.ctx.createOscillator();
|
||||||
|
const gain = this.ctx.createGain();
|
||||||
|
const filter = this.ctx.createBiquadFilter();
|
||||||
|
|
||||||
|
// Noise buffer for texture
|
||||||
|
const bufferSize = this.ctx.sampleRate * 0.1; // 0.1s duration
|
||||||
|
const buffer = this.ctx.createBuffer(1, bufferSize, this.ctx.sampleRate);
|
||||||
|
const data = buffer.getChannelData(0);
|
||||||
|
for (let i = 0; i < bufferSize; i++) {
|
||||||
|
data[i] = (Math.random() * 2 - 1) * 0.5;
|
||||||
|
}
|
||||||
|
const noise = this.ctx.createBufferSource();
|
||||||
|
noise.buffer = buffer;
|
||||||
|
|
||||||
|
// Filter to make it sound dull (floor/carpet)
|
||||||
|
filter.type = 'lowpass';
|
||||||
|
filter.frequency.setValueAtTime(400, t); // Low muffled thud
|
||||||
|
|
||||||
|
// Envelope
|
||||||
|
gain.gain.setValueAtTime(0.3, t);
|
||||||
|
gain.gain.exponentialRampToValueAtTime(0.01, t + 0.1);
|
||||||
|
|
||||||
|
// Connect
|
||||||
|
noise.connect(filter);
|
||||||
|
filter.connect(gain);
|
||||||
|
gain.connect(this.ctx.destination);
|
||||||
|
|
||||||
|
noise.start();
|
||||||
|
noise.stop(t + 0.1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user