summaryrefslogtreecommitdiffstats
path: root/static/pong
diff options
context:
space:
mode:
authorRose Hogenson <rosehogenson@posteo.net>2026-07-24 19:07:10 -0700
committerRose Hogenson <rosehogenson@posteo.net>2026-07-25 10:59:30 -0700
commit0e9b550cbeec4192dff7f760936fe1d85056a5f6 (patch)
tree4afe4b66e4e7da8a2bd9ab55228006c3381c9086 /static/pong
parentFix path for URL and package indexes (diff)
downloadroseh.moe-0e9b550cbeec4192dff7f760936fe1d85056a5f6.tar.zst
Move pong into games/ subdirectory
Diffstat (limited to 'static/pong')
-rw-r--r--static/pong/icon.webpbin1060 -> 0 bytes
-rw-r--r--static/pong/ping.mp3bin4016 -> 0 bytes
-rw-r--r--static/pong/pong.js286
3 files changed, 0 insertions, 286 deletions
diff --git a/static/pong/icon.webp b/static/pong/icon.webp
deleted file mode 100644
index 03ab77e..0000000
--- a/static/pong/icon.webp
+++ /dev/null
Binary files differ
diff --git a/static/pong/ping.mp3 b/static/pong/ping.mp3
deleted file mode 100644
index 87145b8..0000000
--- a/static/pong/ping.mp3
+++ /dev/null
Binary files differ
diff --git a/static/pong/pong.js b/static/pong/pong.js
deleted file mode 100644
index b8bdc2d..0000000
--- a/static/pong/pong.js
+++ /dev/null
@@ -1,286 +0,0 @@
-const ticksPerSecond = 300;
-const ballSpeed = 10 * 60 / ticksPerSecond;
-const paddleSpeed = 10 * 60 / ticksPerSecond;
-
-const canvas = document.getElementById("pong");
-const ctx = canvas.getContext("2d");
-
-class Vector2 {
- constructor(x, y) {
- this.x = x;
- this.y = y;
- }
-
- add(v) {
- return new Vector2(this.x + v.x, this.y + v.y);
- }
-}
-
-class Rect {
- constructor(x, y, w, h) {
- this.x = x;
- this.y = y;
- this.w = w;
- this.h = h;
- }
-
- bottom() {
- return this.y + this.h;
- }
-
- right() {
- return this.x + this.w;
- }
-
- intersects(r) {
- return r.x <= this.right() && r.right() >= this.x && r.y <= this.bottom() && r.bottom() >= this.y;
- }
-
- fill() {
- ctx.clearRect(this.x, this.y, this.w, this.h);
- }
-}
-
-const digitSegments = [0x77, 0x24, 0x5d, 0x6d, 0x2e, 0x6b, 0x7b, 0x25, 0x7f, 0x6f];
-
-function drawNumber(n, x, y) {
- const width = 60;
- const height = 100;
- const thickness = 10;
- const padding = 20;
-
- const digits = n.toString();
- for (let i = 0; i < digits.length; i++) {
- const segments = digitSegments[digits[i] - '0'];
- for (let j = 0; j < 7; j++) {
- if ((segments & 1 << j) === 0) {
- continue;
- }
- switch (j) {
- case 0:
- new Rect(x, y, width, thickness).fill();
- break;
- case 1:
- new Rect(x, y, thickness, height / 2).fill();
- break;
- case 2:
- new Rect(x + width - thickness, y, thickness, height / 2).fill();
- break;
- case 3:
- new Rect(x, y + height / 2 - thickness / 2, width, thickness).fill();
- break;
- case 4:
- new Rect(x, y + height / 2, thickness, height / 2).fill();
- break;
- case 5:
- new Rect(x + width - thickness, y + height / 2, thickness, height / 2).fill();
- break;
- case 6:
- new Rect(x, y + height - thickness, width, thickness).fill();
- break;
- }
- }
- x += width + padding;
- }
-}
-
-class Ball {
- constructor() {
- this.reset('left');
- }
-
- bounds() {
- const ballSize = 30;
-
- return new Rect(
- this.pos.x - ballSize / 2,
- this.pos.y - ballSize / 2,
- ballSize,
- ballSize,
- );
- }
-
- predictIntersection(targetX) {
- if (this.velocity.x <= 0) {
- return null;
- }
- const dist = targetX - this.pos.x;
- const prediction = this.pos.y + this.velocity.y * dist / this.velocity.x;
- if (prediction < 0) {
- const bounces = Math.floor(-prediction / canvas.height);
- if (bounces % 2 === 0) {
- return -prediction - canvas.height * bounces;
- }
- return prediction + canvas.height * (bounces + 1);
- }
- if (prediction > canvas.height) {
- const bounces = Math.floor(prediction / canvas.height);
- if (bounces % 2 === 0) {
- return prediction - canvas.height * bounces;
- }
- return -prediction + canvas.height * (bounces + 1);
- }
- return prediction;
- }
-
- reset(side) {
- this.pos = new Vector2(canvas.width / 2, canvas.height / 2);
- this.velocity = new Vector2(ballSpeed, 0);
- if (side === 'left') {
- this.velocity.x = -this.velocity.x;
- }
- }
-}
-
-class Paddle {
- constructor(side) {
- this.pos = canvas.height / 2;
- this.side = side;
- }
-
- bounds() {
- const paddleHeight = 200;
- const thickness = 10;
- const padding = 100;
-
- let r = new Rect(
- padding - thickness / 2,
- this.pos - paddleHeight / 2,
- thickness,
- paddleHeight,
- );
- if (this.side === 'right') {
- r.x = canvas.width - padding - thickness / 2;
- }
- return r;
- }
-}
-
-function updateCanvasSize() {
- canvas.width = window.innerWidth;
- canvas.height = window.innerHeight;
-}
-
-const pingAudio = new Audio('/static/pong/ping.mp3');
-
-function ping() {
- pingAudio.pause();
- pingAudio.currentTime = 0;
- pingAudio.play();
-}
-
-function main() {
- updateCanvasSize();
-
- let playerScore = 0;
- let aiScore = 0;
-
- const ball = new Ball();
-
- const paddle1 = new Paddle('left');
- const paddle2 = new Paddle('right');
-
- const keys = {};
- window.addEventListener('keydown', (e) => keys[e.key] = true);
- window.addEventListener('keyup', (e) => delete keys[e.key]);
- let mousePressed = false;
- let mouseY = 0;
- window.addEventListener('mousedown', () => mousePressed = true);
- window.addEventListener('mouseup', () => mousePressed = false);
- window.addEventListener('mousemove', (e) => mouseY = e.y);
- let touchPressed = false;
- let touchY = 0;
- window.addEventListener('touchstart', (e) => {
- touchPressed = true;
- if (e.changedTouches.length > 0) {
- touchY = e.changedTouches[0].clientY;
- }
- });
- window.addEventListener('touchmove', (e) => {
- touchPressed = true;
- if (e.changedTouches.length > 0) {
- touchY = e.changedTouches[0].clientY;
- }
- });
- window.addEventListener('touchend', () => touchPressed = false);
- window.addEventListener('touchcancel', () => touchPressed = false);
-
- let lastFrameTime = performance.now();
- let accumulator = 0;
-
- function gameLoop() {
- updateCanvasSize();
-
- const now = performance.now();
- const frameTime = now - lastFrameTime;
- lastFrameTime = now;
- accumulator += frameTime;
-
- const simulationSpeed = 1000 / ticksPerSecond;
- for (; accumulator >= simulationSpeed; accumulator -= simulationSpeed) {
- if ((keys["w"] || keys["ArrowUp"] || mousePressed && paddle1.pos >= mouseY + paddleSpeed || touchPressed && paddle1.pos >= touchY + paddleSpeed) && paddle1.bounds().y >= 0) {
- paddle1.pos -= paddleSpeed;
- } else if ((keys["s"] || keys["ArrowDown"] || mousePressed && paddle1.pos <= mouseY - paddleSpeed || touchPressed && paddle1.pos <= touchY - paddleSpeed) && paddle1.bounds().bottom() <= canvas.height) {
- paddle1.pos += paddleSpeed;
- }
-
- const prediction = ball.predictIntersection(paddle2.bounds().x);
- if (prediction !== null) {
- if (paddle2.pos <= prediction - paddleSpeed && paddle2.bounds().bottom() <= canvas.height) {
- paddle2.pos += paddleSpeed;
- } else if (paddle2.pos >= prediction + paddleSpeed && paddle2.bounds().y >= 0) {
- paddle2.pos -= paddleSpeed;
- }
- }
-
- ball.pos = ball.pos.add(ball.velocity);
- if (ball.bounds().intersects(paddle1.bounds()) && ball.velocity.x <= 0) {
- ping();
- let d = (ball.pos.y - paddle1.pos) / (paddle1.bounds().h / 2 + ball.bounds().h);
- if (d < 0) {
- d = -d;
- }
- let angle = d * 75 * 2 * Math.PI / 360;
- if (ball.pos.y < paddle1.pos) {
- angle = -angle;
- }
- const speed = ballSpeed * (1 + 4 * d);
- ball.velocity = new Vector2(speed * Math.cos(angle), speed * Math.sin(angle));
- } else if (ball.bounds().intersects(paddle2.bounds()) && ball.velocity.x >= 0) {
- ping();
- let d = (ball.pos.y - paddle2.pos) / (paddle2.bounds().h / 2 + ball.bounds().h);
- if (d < 0) {
- d = -d;
- }
- let angle = d * 75 * 2 * Math.PI / 360;
- if (ball.pos.y < paddle2.pos) {
- angle = -angle;
- }
- angle += Math.PI;
- const speed = ballSpeed * (1 + 4 * d);
- ball.velocity = new Vector2(speed * Math.cos(angle), speed * Math.sin(angle));
- } else if (ball.bounds().right() <= 0) {
- aiScore++;
- ball.reset('right');
- } else if (ball.bounds().x >= canvas.width) {
- playerScore++;
- ball.reset('left');
- } else if (ball.bounds().y <= 0 && ball.velocity.y < 0 || ball.bounds().bottom() >= canvas.height && ball.velocity.y > 0) {
- ping();
- ball.velocity.y = -ball.velocity.y;
- }
- }
-
- ctx.fillRect(0, 0, canvas.width, canvas.height);
- paddle1.bounds().fill();
- paddle2.bounds().fill();
- ball.bounds().fill();
- drawNumber(playerScore, 150, 30)
- drawNumber(aiScore, canvas.width / 2 + 150, canvas.height - 130);
-
- requestAnimationFrame(gameLoop);
- }
- gameLoop();
-}
-
-main();