diff --git a/index.html b/index.html index c0c9e1a..815cea5 100644 --- a/index.html +++ b/index.html @@ -16,7 +16,13 @@ const GameConfig = { initialBallSpeed: 220, // px/s — starting speed per serve speedIncrement: 18, // px/s added per paddle hit - paddleSpeed: 400 // px/s — Player 1 paddle movement + paddleSpeed: 400, // px/s — Player 1 paddle movement + + WIN_SCORE: 7, + + AI_EASY: { speed: 200, reactionDelay: 0.3, errorMargin: 20 }, + AI_MEDIUM: { speed: 320, reactionDelay: 0.1, errorMargin: 5 }, + AI_HARD: { speed: 400, reactionDelay: 0.05, errorMargin: 2 } }; const Renderer = { @@ -99,28 +105,50 @@ vx: 0, vy: 0, // Set on Physics.init() speed: 0, // Current scalar speed color: '#fff' - } + }, + paddle2: { + x: 0, y: 0, // Set on Physics.init() + width: 12, height: 80, + speed: 400, + color: '#fff' + }, + score1: 0, + score2: 0, + mode: null, // null = mode select screen; 'ai' = Solo vs AI; '2p' = 2-Player local + difficulty: 'medium', // 'easy', 'medium', 'hard' + gameState: 'modeSelect',// 'modeSelect', 'diffSelect', 'playing', 'scored', 'gameover' + winner: null // null, 'player1', 'player2', 'ai' }; const Input = { - keys: { w: false, s: false }, + keys: { w: false, s: false, arrowUp: false, arrowDown: false }, + _handleKeyDown: null, + _handleKeyUp: null, init() { - document.addEventListener('keydown', (e) => { - if (e.code === 'KeyW') { this.keys.w = true; e.preventDefault(); } - if (e.code === 'KeyS') { this.keys.s = true; e.preventDefault(); } - }); - document.addEventListener('keyup', (e) => { - if (e.code === 'KeyW') this.keys.w = false; - if (e.code === 'KeyS') this.keys.s = false; - }); + this._handleKeyDown = (e) => { + if (e.code === 'KeyW') { this.keys.w = true; e.preventDefault(); } + if (e.code === 'KeyS') { this.keys.s = true; e.preventDefault(); } + if (e.code === 'ArrowUp') { this.keys.arrowUp = true; e.preventDefault(); } + if (e.code === 'ArrowDown') { this.keys.arrowDown = true; e.preventDefault(); } + }; + this._handleKeyUp = (e) => { + if (e.code === 'KeyW') this.keys.w = false; + if (e.code === 'KeyS') this.keys.s = false; + if (e.code === 'ArrowUp') this.keys.arrowUp = false; + if (e.code === 'ArrowDown') this.keys.arrowDown = false; + }; + document.addEventListener('keydown', this._handleKeyDown); + document.addEventListener('keyup', this._handleKeyUp); }, - getVerticalInput() { - if (this.keys.w) return -1; - if (this.keys.s) return 1; - return 0; - } + cleanup() { + document.removeEventListener('keydown', this._handleKeyDown); + document.removeEventListener('keyup', this._handleKeyUp); + }, + + getVerticalInput() { return this.keys.w ? -1 : this.keys.s ? 1 : 0; }, + getVerticalInput2() { return this.keys.arrowUp ? -1 : this.keys.arrowDown ? 1 : 0; } }; const Physics = { @@ -134,13 +162,16 @@ GameState.paddle1.x = 30; GameState.paddle1.y = height / 2 - GameState.paddle1.height / 2; GameState.paddle1.speed = GameConfig.paddleSpeed; + // Position paddle2 on right side, vertically centered + GameState.paddle2.x = width - 30 - GameState.paddle2.width; + GameState.paddle2.y = height / 2 - GameState.paddle2.height / 2; + GameState.paddle2.speed = GameConfig.paddleSpeed; // Serve ball from center this.serveBall(); }, onResize(width, height) { - this.width = width; - this.height = height; + this.init(width, height); }, serveBall() {