Spaces:
Running
Running
Codex CLI
feat(player): enhance movement mechanics with sliding, jump buffering, and wall bounce features
d6dfcf1
import { G } from './globals.js'; | |
import { CFG } from './config.js'; | |
import { showOverlay } from './hud.js'; | |
import { initAudio, resumeAudio } from './audio.js'; | |
import { primeGrenade, releaseGrenade } from './grenades.js'; | |
export function setupEvents({ startGame, restartGame, beginReload, updateWeaponAnchor }) { | |
const overlay = document.getElementById('overlay'); | |
if (!overlay) return; | |
overlay.addEventListener('click', () => { | |
// Initialize audio on user gesture | |
initAudio(); | |
if (G.state === 'menu') { | |
G.controls.lock(); | |
} else if (G.state === 'paused') { | |
G.controls.lock(); | |
} else if (G.state === 'gameover') { | |
// Restart on click after game over | |
restartGame(); | |
} | |
}); | |
G.controls.addEventListener('lock', () => { | |
if (G.state === 'menu') { | |
startGame(); | |
} else if (G.state === 'paused') { | |
G.state = 'playing'; | |
overlay.classList.add('hidden'); | |
} else if (G.state === 'gameover') { | |
// Treat lock like a fresh start after game over | |
startGame(); | |
} | |
}); | |
G.controls.addEventListener('unlock', () => { | |
if (G.state === 'playing') { | |
G.state = 'paused'; | |
showOverlay('paused'); | |
} | |
}); | |
document.addEventListener('keydown', (e) => { | |
switch (e.code) { | |
case 'KeyW': G.input.w = true; break; | |
case 'KeyA': G.input.a = true; break; | |
case 'KeyS': G.input.s = true; break; | |
case 'KeyD': G.input.d = true; break; | |
case 'ShiftLeft': G.input.sprint = true; break; | |
case 'KeyC': G.input.crouch = true; break; | |
case 'KeyG': | |
if (G.state === 'playing') { | |
G.input.grenade = true; | |
primeGrenade(); | |
} | |
break; | |
case 'Space': | |
if (G.state === 'playing') { | |
// Use buffered jump handled in player physics | |
G.input.jump = true; | |
} | |
break; | |
case 'KeyF': | |
if (G.state === 'playing' && G.flashlight) { | |
G.flashlight.visible = !G.flashlight.visible; | |
} | |
break; | |
case 'KeyP': | |
case 'Escape': | |
if (G.state === 'playing') { | |
G.controls.unlock(); | |
} | |
break; | |
case 'KeyR': | |
if (G.state === 'playing') { | |
beginReload(); | |
} | |
break; | |
} | |
}); | |
document.addEventListener('keyup', (e) => { | |
switch (e.code) { | |
case 'KeyW': G.input.w = false; break; | |
case 'KeyA': G.input.a = false; break; | |
case 'KeyS': G.input.s = false; break; | |
case 'KeyD': G.input.d = false; break; | |
case 'ShiftLeft': G.input.sprint = false; break; | |
case 'KeyC': G.input.crouch = false; break; | |
case 'KeyG': | |
if (G.input.grenade) { | |
G.input.grenade = false; | |
releaseGrenade(); | |
} | |
break; | |
case 'Space': | |
G.input.jump = false; | |
break; | |
} | |
}); | |
document.addEventListener('mousedown', (e) => { | |
if (e.button === 0 && G.state === 'playing') { | |
// Ensure audio context is running on interaction | |
resumeAudio(); | |
G.input.shoot = true; | |
} | |
}); | |
document.addEventListener('mouseup', (e) => { | |
if (e.button === 0) { | |
G.input.shoot = false; | |
} | |
}); | |
window.addEventListener('resize', () => { | |
G.camera.aspect = window.innerWidth / window.innerHeight; | |
G.camera.updateProjectionMatrix(); | |
G.renderer.setSize(window.innerWidth, window.innerHeight); | |
updateWeaponAnchor(); | |
}); | |
} | |