chore: initial commit — CS2 Simulator
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
// Sound effects system using Web Audio API - no external files needed
|
||||
const SoundManager = {
|
||||
_ctx: null,
|
||||
_enabled: true,
|
||||
_volume: 0.3,
|
||||
|
||||
init() {
|
||||
try {
|
||||
this._ctx = new (window.AudioContext || window.webkitAudioContext)();
|
||||
} catch (e) {
|
||||
console.warn('Web Audio API not supported');
|
||||
this._enabled = false;
|
||||
}
|
||||
const saved = localStorage.getItem('sound_enabled');
|
||||
if (saved !== null) this._enabled = saved === 'true';
|
||||
},
|
||||
|
||||
setEnabled(on) {
|
||||
this._enabled = on;
|
||||
localStorage.setItem('sound_enabled', on);
|
||||
},
|
||||
|
||||
toggle() {
|
||||
this.setEnabled(!this._enabled);
|
||||
return this._enabled;
|
||||
},
|
||||
|
||||
_play(freq, duration, type = 'sine', volume = 1) {
|
||||
if (!this._enabled || !this._ctx) return;
|
||||
if (this._ctx.state === 'suspended') this._ctx.resume();
|
||||
|
||||
const osc = this._ctx.createOscillator();
|
||||
const gain = this._ctx.createGain();
|
||||
osc.type = type;
|
||||
osc.frequency.setValueAtTime(freq, this._ctx.currentTime);
|
||||
gain.gain.setValueAtTime(this._volume * volume, this._ctx.currentTime);
|
||||
gain.gain.exponentialRampToValueAtTime(0.001, this._ctx.currentTime + duration);
|
||||
osc.connect(gain);
|
||||
gain.connect(this._ctx.destination);
|
||||
osc.start();
|
||||
osc.stop(this._ctx.currentTime + duration);
|
||||
},
|
||||
|
||||
_noise(duration, volume = 1) {
|
||||
if (!this._enabled || !this._ctx) return;
|
||||
if (this._ctx.state === 'suspended') this._ctx.resume();
|
||||
|
||||
const bufferSize = this._ctx.sampleRate * 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;
|
||||
}
|
||||
const source = this._ctx.createBufferSource();
|
||||
source.buffer = buffer;
|
||||
const gain = this._ctx.createGain();
|
||||
gain.gain.setValueAtTime(this._volume * volume, this._ctx.currentTime);
|
||||
gain.gain.exponentialRampToValueAtTime(0.001, this._ctx.currentTime + duration);
|
||||
source.connect(gain);
|
||||
gain.connect(this._ctx.destination);
|
||||
source.start();
|
||||
},
|
||||
|
||||
caseOpen() {
|
||||
// Descending sweep with click
|
||||
this._play(800, 0.1, 'square', 0.3);
|
||||
setTimeout(() => this._play(400, 0.15, 'sawtooth', 0.2), 80);
|
||||
setTimeout(() => this._play(200, 0.2, 'sine', 0.15), 180);
|
||||
this._noise(0.05, 0.4);
|
||||
},
|
||||
|
||||
caseRare() {
|
||||
// Ascending bright chime for rare items
|
||||
this._play(523, 0.15, 'sine', 0.3);
|
||||
setTimeout(() => this._play(659, 0.15, 'sine', 0.3), 100);
|
||||
setTimeout(() => this._play(784, 0.15, 'sine', 0.3), 200);
|
||||
setTimeout(() => this._play(1047, 0.3, 'sine', 0.4), 300);
|
||||
},
|
||||
|
||||
caseCovert() {
|
||||
// Epic sound for covert/knife
|
||||
this._play(392, 0.2, 'sawtooth', 0.3);
|
||||
setTimeout(() => this._play(523, 0.2, 'sawtooth', 0.3), 150);
|
||||
setTimeout(() => this._play(659, 0.2, 'sawtooth', 0.3), 300);
|
||||
setTimeout(() => this._play(784, 0.4, 'sine', 0.5), 450);
|
||||
setTimeout(() => this._play(1047, 0.6, 'sine', 0.6), 600);
|
||||
},
|
||||
|
||||
slotSpin() {
|
||||
// Ratcheting sound for slot reels
|
||||
for (let i = 0; i < 8; i++) {
|
||||
setTimeout(() => {
|
||||
this._play(300 + Math.random() * 400, 0.05, 'square', 0.15);
|
||||
}, i * 80);
|
||||
}
|
||||
},
|
||||
|
||||
slotMatch() {
|
||||
// Win jingle
|
||||
this._play(523, 0.1, 'sine', 0.3);
|
||||
setTimeout(() => this._play(659, 0.1, 'sine', 0.3), 100);
|
||||
setTimeout(() => this._play(784, 0.1, 'sine', 0.3), 200);
|
||||
setTimeout(() => this._play(1047, 0.4, 'sine', 0.5), 300);
|
||||
},
|
||||
|
||||
contractSubmit() {
|
||||
// Mechanical sound
|
||||
this._play(150, 0.3, 'sawtooth', 0.2);
|
||||
setTimeout(() => this._play(200, 0.2, 'square', 0.2), 200);
|
||||
setTimeout(() => this._play(250, 0.1, 'square', 0.15), 350);
|
||||
},
|
||||
|
||||
contractResult() {
|
||||
// Rising success
|
||||
this._play(400, 0.15, 'sine', 0.3);
|
||||
setTimeout(() => this._play(600, 0.15, 'sine', 0.3), 120);
|
||||
setTimeout(() => this._play(800, 0.3, 'sine', 0.4), 240);
|
||||
},
|
||||
|
||||
wheelSpin() {
|
||||
// Ticking as wheel rotates
|
||||
this._play(200, 0.03, 'square', 0.1);
|
||||
},
|
||||
|
||||
wheelWin() {
|
||||
// Celebration
|
||||
this._play(523, 0.15, 'sine', 0.3);
|
||||
setTimeout(() => this._play(659, 0.15, 'sine', 0.3), 120);
|
||||
setTimeout(() => this._play(784, 0.2, 'sine', 0.35), 240);
|
||||
setTimeout(() => this._play(1047, 0.5, 'sine', 0.5), 360);
|
||||
},
|
||||
|
||||
wheelLose() {
|
||||
// Sad trombone
|
||||
this._play(400, 0.2, 'sine', 0.2);
|
||||
setTimeout(() => this._play(350, 0.2, 'sine', 0.2), 150);
|
||||
setTimeout(() => this._play(300, 0.3, 'sine', 0.15), 300);
|
||||
},
|
||||
|
||||
achievement() {
|
||||
// Achievement unlock
|
||||
this._play(659, 0.1, 'sine', 0.3);
|
||||
setTimeout(() => this._play(523, 0.1, 'sine', 0.3), 100);
|
||||
setTimeout(() => this._play(784, 0.1, 'sine', 0.3), 200);
|
||||
setTimeout(() => this._play(659, 0.1, 'sine', 0.3), 300);
|
||||
setTimeout(() => this._play(1047, 0.4, 'sine', 0.5), 400);
|
||||
},
|
||||
|
||||
crashBet() {
|
||||
this._play(300, 0.1, 'square', 0.15);
|
||||
},
|
||||
|
||||
crashTick() {
|
||||
this._play(500 + Math.random() * 500, 0.03, 'sine', 0.08);
|
||||
},
|
||||
|
||||
crashCrashed() {
|
||||
// Explosion
|
||||
this._noise(0.3, 0.6);
|
||||
this._play(80, 0.5, 'sawtooth', 0.4);
|
||||
setTimeout(() => this._play(50, 0.8, 'sine', 0.3), 100);
|
||||
},
|
||||
|
||||
crashCashout() {
|
||||
// Cashout success
|
||||
this._play(600, 0.1, 'sine', 0.3);
|
||||
setTimeout(() => this._play(800, 0.1, 'sine', 0.3), 80);
|
||||
setTimeout(() => this._play(1000, 0.2, 'sine', 0.4), 160);
|
||||
},
|
||||
|
||||
click() {
|
||||
this._play(800, 0.03, 'sine', 0.1);
|
||||
},
|
||||
|
||||
error() {
|
||||
this._play(200, 0.15, 'square', 0.2);
|
||||
},
|
||||
|
||||
balanceUpdate() {
|
||||
this._play(1000, 0.05, 'sine', 0.1);
|
||||
}
|
||||
};
|
||||
|
||||
// Auto-init
|
||||
document.addEventListener('DOMContentLoaded', () => SoundManager.init());
|
||||
Reference in New Issue
Block a user