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() {