feat(02-01): extend GameConfig, GameState, and Input for two-player support
- Add WIN_SCORE, AI_EASY, AI_MEDIUM, AI_HARD to GameConfig - Add paddle2, score1, score2, mode, difficulty, gameState, winner to GameState - Replace anonymous Input handlers with named refs + cleanup() method - Add Input.getVerticalInput2() for ArrowUp/ArrowDown keys - Position paddle2 on right side in Physics.init() - Update Physics.onResize() to call init() for full repositioning
This commit is contained in:
67
index.html
67
index.html
@@ -16,7 +16,13 @@
|
|||||||
const GameConfig = {
|
const GameConfig = {
|
||||||
initialBallSpeed: 220, // px/s — starting speed per serve
|
initialBallSpeed: 220, // px/s — starting speed per serve
|
||||||
speedIncrement: 18, // px/s added per paddle hit
|
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 = {
|
const Renderer = {
|
||||||
@@ -99,28 +105,50 @@
|
|||||||
vx: 0, vy: 0, // Set on Physics.init()
|
vx: 0, vy: 0, // Set on Physics.init()
|
||||||
speed: 0, // Current scalar speed
|
speed: 0, // Current scalar speed
|
||||||
color: '#fff'
|
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 = {
|
const Input = {
|
||||||
keys: { w: false, s: false },
|
keys: { w: false, s: false, arrowUp: false, arrowDown: false },
|
||||||
|
_handleKeyDown: null,
|
||||||
|
_handleKeyUp: null,
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
document.addEventListener('keydown', (e) => {
|
this._handleKeyDown = (e) => {
|
||||||
if (e.code === 'KeyW') { this.keys.w = true; e.preventDefault(); }
|
if (e.code === 'KeyW') { this.keys.w = true; e.preventDefault(); }
|
||||||
if (e.code === 'KeyS') { this.keys.s = true; e.preventDefault(); }
|
if (e.code === 'KeyS') { this.keys.s = true; e.preventDefault(); }
|
||||||
});
|
if (e.code === 'ArrowUp') { this.keys.arrowUp = true; e.preventDefault(); }
|
||||||
document.addEventListener('keyup', (e) => {
|
if (e.code === 'ArrowDown') { this.keys.arrowDown = true; e.preventDefault(); }
|
||||||
if (e.code === 'KeyW') this.keys.w = false;
|
};
|
||||||
if (e.code === 'KeyS') this.keys.s = false;
|
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() {
|
cleanup() {
|
||||||
if (this.keys.w) return -1;
|
document.removeEventListener('keydown', this._handleKeyDown);
|
||||||
if (this.keys.s) return 1;
|
document.removeEventListener('keyup', this._handleKeyUp);
|
||||||
return 0;
|
},
|
||||||
}
|
|
||||||
|
getVerticalInput() { return this.keys.w ? -1 : this.keys.s ? 1 : 0; },
|
||||||
|
getVerticalInput2() { return this.keys.arrowUp ? -1 : this.keys.arrowDown ? 1 : 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
const Physics = {
|
const Physics = {
|
||||||
@@ -134,13 +162,16 @@
|
|||||||
GameState.paddle1.x = 30;
|
GameState.paddle1.x = 30;
|
||||||
GameState.paddle1.y = height / 2 - GameState.paddle1.height / 2;
|
GameState.paddle1.y = height / 2 - GameState.paddle1.height / 2;
|
||||||
GameState.paddle1.speed = GameConfig.paddleSpeed;
|
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
|
// Serve ball from center
|
||||||
this.serveBall();
|
this.serveBall();
|
||||||
},
|
},
|
||||||
|
|
||||||
onResize(width, height) {
|
onResize(width, height) {
|
||||||
this.width = width;
|
this.init(width, height);
|
||||||
this.height = height;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
serveBall() {
|
serveBall() {
|
||||||
|
|||||||
Reference in New Issue
Block a user