Knight Pong
body {
background-color: #f4e4c1; /* Parchment color */
margin: 0;
padding: 0;
font-family: “Georgia”, serif;
user-select: none;
}
#gameCanvas {
display: block;
margin: 0 auto;
background-color: #f4e4c1; /* Matches background for a seamless look */
border: 5px solid #654321; /* Brown “wooden frame” border */
}
h1 {
text-align: center;
color: #654321;
margin-top: 10px;
margin-bottom: 5px;
font-size: 32px;
text-transform: uppercase;
letter-spacing: 2px;
}
#scoreboard {
text-align: center;
color: #654321;
font-size: 20px;
margin-bottom: 20px;
}
Knight Pong
// ———————
// Canvas & Context
// ———————
const canvas = document.getElementById(‘gameCanvas’);
const ctx = canvas.getContext(‘2d’);
// ———————
// Constants & Settings
// ———————
const CANVAS_WIDTH = canvas.width;
const CANVAS_HEIGHT = canvas.height;
// Paddle (Shield) settings
const PADDLE_WIDTH = 20;
const PADDLE_HEIGHT = 100;
const PADDLE_SPEED = 5;
// Ball (Sword) settings
const BALL_RADIUS = 10;
const BALL_SPEED_X = 4;
const BALL_SPEED_Y = 3;
// Colors for our medieval look
const LEFT_SHIELD_COLOR = “#9b7653”; // Brownish (wooden shield)
const RIGHT_SHIELD_COLOR = “#aaa9ad”; // Grayish (metal shield)
const BALL_COLOR = “#b4b4b4”; // Sword/lance color (gray metal)
// Scores
let leftScore = 0;
let rightScore = 0;
// Track who scored last
let lastScorer = null;
// Pause flag: ball won’t move until H is pressed
let waitingForLaunch = true;
// ———————
// Paddle Positions
// ———————
let leftPaddleY = (CANVAS_HEIGHT – PADDLE_HEIGHT) / 2;
let rightPaddleY = (CANVAS_HEIGHT – PADDLE_HEIGHT) / 2;
// ———————
// Ball Position & Velocity
// ———————
let ballX, ballY, ballDX, ballDY;
// ———————
// Key Press States
// ———————
let leftUpPressed = false; // Key “1”
let leftDownPressed = false; // Key “2”
let rightUpPressed = false; // Key “-”
let rightDownPressed = false; // Key “=”
// ———————
// Event Listeners
// ———————
document.addEventListener(‘keydown’, keyDownHandler);
document.addEventListener(‘keyup’, keyUpHandler);
function keyDownHandler(e) {
// Paddle controls
if (e.key === ‘1’) {
leftUpPressed = true;
}
if (e.key === ‘2’) {
leftDownPressed = true;
}
if (e.key === ‘-‘) {
rightUpPressed = true;
}
if (e.key === ‘=’) {
rightDownPressed = true;
}
// Press ‘h’ to launch ball
if (e.key === ‘h’ && waitingForLaunch) {
waitingForLaunch = false;
giveBallVelocity();
}
}
function keyUpHandler(e) {
if (e.key === ‘1’) {
leftUpPressed = false;
}
if (e.key === ‘2’) {
leftDownPressed = false;
}
if (e.key === ‘-‘) {
rightUpPressed = false;
}
if (e.key === ‘=’) {
rightDownPressed = false;
}
}
// ———————
// Game Loop
// ———————
function update() {
movePaddles();
if (!waitingForLaunch) {
moveBall();
}
draw();
requestAnimationFrame(update);
}
// ———————
// Initialize Game
// ———————
function init() {
resetBall();
update();
}
// ———————
// Move Paddles
// ———————
function movePaddles() {
if (leftUpPressed && leftPaddleY > 0) {
leftPaddleY -= PADDLE_SPEED;
}
if (leftDownPressed && leftPaddleY < CANVAS_HEIGHT - PADDLE_HEIGHT) {
leftPaddleY += PADDLE_SPEED;
}
if (rightUpPressed && rightPaddleY > 0) {
rightPaddleY -= PADDLE_SPEED;
}
if (rightDownPressed && rightPaddleY < CANVAS_HEIGHT - PADDLE_HEIGHT) {
rightPaddleY += PADDLE_SPEED;
}
}
// ---------------------
// Move Ball
// ---------------------
function moveBall() {
ballX += ballDX;
ballY += ballDY;
// Top/Bottom wall collision
if (ballY - BALL_RADIUS < 0 || ballY + BALL_RADIUS > CANVAS_HEIGHT) {
ballDY = -ballDY;
}
// Left paddle collision
if (
ballX – BALL_RADIUS < PADDLE_WIDTH &&
ballY > leftPaddleY &&
ballY < leftPaddleY + PADDLE_HEIGHT
) {
ballDX = -ballDX;
// Slight speed change
if (ballDX < 0) {
ballDX -= 0.2;
} else {
ballDX += 0.2;
}
}
// Right paddle collision
else if (
ballX + BALL_RADIUS > CANVAS_WIDTH – PADDLE_WIDTH &&
ballY > rightPaddleY &&
ballY < rightPaddleY + PADDLE_HEIGHT
) {
ballDX = -ballDX;
// Slight speed change
if (ballDX < 0) {
ballDX -= 0.2;
} else {
ballDX += 0.2;
}
}
// Left/Right scoring
if (ballX + BALL_RADIUS < 0) {
rightScore++;
lastScorer = 'right';
resetBall();
} else if (ballX - BALL_RADIUS > CANVAS_WIDTH) {
leftScore++;
lastScorer = ‘left’;
resetBall();
}
}
// ———————
// Reset Ball After Score
// ———————
function resetBall() {
waitingForLaunch = true;
// Place ball near the last scorer’s side
if (lastScorer === ‘left’) {
// Place the ball near left paddle
ballX = PADDLE_WIDTH + BALL_RADIUS + 10;
ballY = leftPaddleY + PADDLE_HEIGHT / 2;
} else if (lastScorer === ‘right’) {
// Place the ball near right paddle
ballX = CANVAS_WIDTH – PADDLE_WIDTH – BALL_RADIUS – 10;
ballY = rightPaddleY + PADDLE_HEIGHT / 2;
} else {
// If no one scored yet (start of game), place ball in center
ballX = CANVAS_WIDTH / 2;
ballY = CANVAS_HEIGHT / 2;
}
// Temporarily zero velocity until H is pressed
ballDX = 0;
ballDY = 0;
}
// ———————
// Launch the Ball
// ———————
function giveBallVelocity() {
// If left side scored last, push ball to the right
if (lastScorer === ‘left’) {
ballDX = BALL_SPEED_X;
}
// If right side scored last, push ball to the left
else if (lastScorer === ‘right’) {
ballDX = -BALL_SPEED_X;
}
// If no one scored yet, pick random direction
else {
ballDX = (Math.random() < 0.5 ? 1 : -1) * BALL_SPEED_X;
}
// Random up/down direction
ballDY = (Math.random() < 0.5 ? 1 : -1) * BALL_SPEED_Y;
}
// ---------------------
// Drawing
// ---------------------
function draw() {
ctx.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
// Draw left shield (paddle)
ctx.fillStyle = LEFT_SHIELD_COLOR;
drawShield(0, leftPaddleY, PADDLE_WIDTH, PADDLE_HEIGHT);
// Draw right shield (paddle)
ctx.fillStyle = RIGHT_SHIELD_COLOR;
drawShield(CANVAS_WIDTH - PADDLE_WIDTH, rightPaddleY, PADDLE_WIDTH, PADDLE_HEIGHT);
// Draw the sword (ball)
ctx.fillStyle = BALL_COLOR;
drawSword(ballX, ballY, BALL_RADIUS);
// Score display
const scoreboard = document.getElementById('scoreboard');
let msg = `Left: ${leftScore} | Right: ${rightScore}`;
if (waitingForLaunch) {
msg += " — Press 'H' to Launch";
}
scoreboard.textContent = msg;
}
// ---------------------
// Helper: Draw Shield
// ---------------------
function drawShield(x, y, w, h) {
ctx.beginPath();
ctx.moveTo(x + w/2, y);
ctx.arcTo(x + w, y, x + w, y + h/2, w/2);
ctx.arcTo(x + w, y + h, x + w/2, y + h, w/2);
ctx.arcTo(x, y + h, x, y + h/2, w/2);
ctx.arcTo(x, y, x + w/2, y, w/2);
ctx.closePath();
ctx.fill();
}
// ---------------------
// Helper: Draw Sword (Ball)
// ---------------------
function drawSword(cx, cy, r) {
ctx.beginPath();
ctx.arc(cx, cy, r, 0, Math.PI * 2);
ctx.fill();
}
// Start
init();
\n\n[/cs_content_seo][/cs_element_layout_div][/cs_content]