diff --git a/CLAUDE.md b/CLAUDE.md
index a29f1e0..2a4d4c2 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -16,7 +16,7 @@ This is a client-side JavaScript application that runs directly in the browser:
The project uses an **Entity-Component-System (ECS)** pattern with event-driven communication:
- **Entities**: `Player` and `Puck` classes represent game objects
-- **Systems**: Modular systems handle specific concerns (rendering, physics, AI, rules, audio)
+- **Systems**: Modular systems handle specific concerns (rendering, physics, AI, rules)
- **Game Engine**: Central orchestrator that manages all systems and entities
- **Game State**: Centralized state management for scores, time, penalties, etc.
@@ -25,7 +25,7 @@ The application loads scripts in a specific order due to class dependencies:
1. **Utilities**: `vector.js`, `physics.js` (foundational math/physics)
2. **Entities**: `player.js`, `puck.js` (game objects)
-3. **Systems**: `renderer.js`, `physics-system.js`, `ai-system.js`, `rules-system.js`, `audio-system.js`
+3. **Systems**: `renderer.js`, `physics-system.js`, `ai-system.js`, `rules-system.js`
4. **Engine**: `game-state.js`, `game-engine.js`, `main.js` (orchestration)
### Key Classes and Responsibilities
@@ -46,7 +46,6 @@ The engine runs at 60 FPS using `requestAnimationFrame` with these phases:
3. AI decision making
4. Rules enforcement
5. Rendering
-6. Audio updates
### Hockey-Specific Features
- **12 players** (6 per team) with distinct roles: Center (C), Left/Right Wing (LW/RW), Left/Right Defense (LD/RD), Goalie (G)
diff --git a/index.html b/index.html
index ea2b1c7..7d70e63 100644
--- a/index.html
+++ b/index.html
@@ -35,7 +35,6 @@
Play/Pause
Speed: 1x
- Sound: ON
Reset
@@ -48,7 +47,6 @@
-
diff --git a/src/engine/game-engine.js b/src/engine/game-engine.js
index 50cafc4..8800f65 100644
--- a/src/engine/game-engine.js
+++ b/src/engine/game-engine.js
@@ -3,7 +3,6 @@ class GameEngine {
this.canvas = canvas;
this.gameState = new GameState();
this.renderer = new Renderer(canvas);
- this.audioSystem = new AudioSystem();
this.players = [];
this.puck = new Puck(500, 300);
@@ -75,7 +74,6 @@ class GameEngine {
startTime: Date.now()
});
- this.audioSystem.onGoal(data.team);
setTimeout(() => {
this.startFaceoff();
@@ -90,7 +88,6 @@ class GameEngine {
startTime: Date.now()
});
- this.audioSystem.onSave();
});
this.gameState.on('penalty', (data) => {
@@ -99,11 +96,9 @@ class GameEngine {
penalizedPlayer.state.penaltyTime = data.duration;
}
- this.audioSystem.onPenalty();
});
this.gameState.on('period-end', () => {
- this.audioSystem.onPeriodEnd();
});
this.gameState.on('faceoff-start', (data) => {
@@ -132,10 +127,6 @@ class GameEngine {
e.target.textContent = `Speed: ${speeds[nextIndex]}x`;
});
- document.getElementById('sound-toggle').addEventListener('click', (e) => {
- const enabled = this.audioSystem.toggle();
- e.target.textContent = `Sound: ${enabled ? 'ON' : 'OFF'}`;
- });
document.getElementById('reset-game').addEventListener('click', () => {
this.resetGame();
diff --git a/src/systems/audio-system.js b/src/systems/audio-system.js
deleted file mode 100644
index 7d0382a..0000000
--- a/src/systems/audio-system.js
+++ /dev/null
@@ -1,245 +0,0 @@
-class AudioSystem {
- constructor() {
- this.audioContext = null;
- this.sounds = {};
- this.volume = 0.7;
- this.enabled = true;
- this.initialized = false;
-
- this.initializeAudio();
- }
-
- async initializeAudio() {
- try {
- this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
- this.generateSounds();
- this.initialized = true;
- } catch (error) {
- console.warn('Audio initialization failed:', error);
- this.enabled = false;
- }
- }
-
- generateSounds() {
- this.sounds = {
- puckHit: this.createPuckHitSound(),
- stick: this.createStickSound(),
- goal: this.createGoalSound(),
- save: this.createSaveSound(),
- whistle: this.createWhistleSound(),
- crowd: this.createCrowdSound(),
- skate: this.createSkateSound(),
- board: this.createBoardSound()
- };
- }
-
- createPuckHitSound() {
- return this.createPercussiveSound(150, 0.1, 'sawtooth');
- }
-
- createStickSound() {
- return this.createPercussiveSound(200, 0.05, 'square');
- }
-
- createGoalSound() {
- return this.createMelodicSound([400, 500, 600], 0.8, 'sine');
- }
-
- createSaveSound() {
- return this.createPercussiveSound(100, 0.3, 'triangle');
- }
-
- createWhistleSound() {
- return this.createMelodicSound([800, 900], 0.5, 'sine');
- }
-
- createCrowdSound() {
- return this.createNoiseSound(0.2, 2.0);
- }
-
- createSkateSound() {
- return this.createNoiseSound(0.1, 0.2);
- }
-
- createBoardSound() {
- return this.createPercussiveSound(80, 0.2, 'triangle');
- }
-
- createPercussiveSound(frequency, duration, waveType = 'sine') {
- return () => {
- if (!this.enabled || !this.audioContext) return;
-
- const oscillator = this.audioContext.createOscillator();
- const gainNode = this.audioContext.createGain();
-
- oscillator.connect(gainNode);
- gainNode.connect(this.audioContext.destination);
-
- oscillator.type = waveType;
- oscillator.frequency.setValueAtTime(frequency, this.audioContext.currentTime);
- oscillator.frequency.exponentialRampToValueAtTime(
- frequency * 0.5,
- this.audioContext.currentTime + duration
- );
-
- gainNode.gain.setValueAtTime(this.volume * 0.3, this.audioContext.currentTime);
- gainNode.gain.exponentialRampToValueAtTime(
- 0.001,
- this.audioContext.currentTime + duration
- );
-
- oscillator.start(this.audioContext.currentTime);
- oscillator.stop(this.audioContext.currentTime + duration);
- };
- }
-
- createMelodicSound(frequencies, duration, waveType = 'sine') {
- return () => {
- if (!this.enabled || !this.audioContext) return;
-
- frequencies.forEach((freq, index) => {
- const delay = index * 0.1;
- const oscillator = this.audioContext.createOscillator();
- const gainNode = this.audioContext.createGain();
-
- oscillator.connect(gainNode);
- gainNode.connect(this.audioContext.destination);
-
- oscillator.type = waveType;
- oscillator.frequency.setValueAtTime(freq, this.audioContext.currentTime + delay);
-
- gainNode.gain.setValueAtTime(0, this.audioContext.currentTime + delay);
- gainNode.gain.linearRampToValueAtTime(
- this.volume * 0.2,
- this.audioContext.currentTime + delay + 0.05
- );
- gainNode.gain.exponentialRampToValueAtTime(
- 0.001,
- this.audioContext.currentTime + delay + duration
- );
-
- oscillator.start(this.audioContext.currentTime + delay);
- oscillator.stop(this.audioContext.currentTime + delay + duration);
- });
- };
- }
-
- createNoiseSound(volume, duration) {
- return () => {
- if (!this.enabled || !this.audioContext) return;
-
- const bufferSize = this.audioContext.sampleRate * duration;
- const buffer = this.audioContext.createBuffer(1, bufferSize, this.audioContext.sampleRate);
- const data = buffer.getChannelData(0);
-
- for (let i = 0; i < bufferSize; i++) {
- data[i] = (Math.random() * 2 - 1) * volume * this.volume;
- }
-
- const source = this.audioContext.createBufferSource();
- const gainNode = this.audioContext.createGain();
- const filter = this.audioContext.createBiquadFilter();
-
- source.buffer = buffer;
- source.connect(filter);
- filter.connect(gainNode);
- gainNode.connect(this.audioContext.destination);
-
- filter.type = 'lowpass';
- filter.frequency.setValueAtTime(2000, this.audioContext.currentTime);
-
- gainNode.gain.setValueAtTime(1, this.audioContext.currentTime);
- gainNode.gain.exponentialRampToValueAtTime(0.001, this.audioContext.currentTime + duration);
-
- source.start(this.audioContext.currentTime);
- };
- }
-
- playSound(soundName, volume = 1) {
- if (!this.enabled || !this.sounds[soundName]) return;
-
- try {
- if (this.audioContext.state === 'suspended') {
- this.audioContext.resume();
- }
- this.sounds[soundName]();
- } catch (error) {
- console.warn('Failed to play sound:', soundName, error);
- }
- }
-
- onPuckHit(velocity) {
- const intensity = Math.min(1, velocity / 500);
- if (intensity > 0.1) {
- this.playSound('puckHit', intensity);
- }
- }
-
- onStickContact() {
- this.playSound('stick');
- }
-
- onGoal(team) {
- this.playSound('goal');
- setTimeout(() => this.playSound('crowd'), 500);
- }
-
- onSave() {
- this.playSound('save');
- }
-
- onPenalty() {
- this.playSound('whistle');
- }
-
- onPeriodEnd() {
- this.playSound('whistle');
- }
-
- onBoardCollision(velocity) {
- const intensity = Math.min(1, velocity / 300);
- if (intensity > 0.2) {
- this.playSound('board', intensity);
- }
- }
-
- onPlayerMovement(speed) {
- if (speed > 100 && Math.random() < 0.01) {
- this.playSound('skate', 0.3);
- }
- }
-
- setVolume(volume) {
- this.volume = Math.max(0, Math.min(1, volume));
- }
-
- setEnabled(enabled) {
- this.enabled = enabled;
- }
-
- toggle() {
- this.enabled = !this.enabled;
- return this.enabled;
- }
-
- resume() {
- if (this.audioContext && this.audioContext.state === 'suspended') {
- return this.audioContext.resume();
- }
- }
-
- suspend() {
- if (this.audioContext && this.audioContext.state === 'running') {
- return this.audioContext.suspend();
- }
- }
-
- getState() {
- return {
- enabled: this.enabled,
- volume: this.volume,
- initialized: this.initialized,
- contextState: this.audioContext ? this.audioContext.state : 'not-initialized'
- };
- }
-}
\ No newline at end of file