Created
May 22, 2025 15:32
-
-
Save Studio1HQ/f5deb4c6bf3559a71b12d185961d4637 to your computer and use it in GitHub Desktop.
3D ping Pong Game by Grok 3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!doctype html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| <title>Tron Ping Pong</title> | |
| <script src="<https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.2/p5.min.js>"></script> | |
| <style> | |
| body { | |
| margin: 0; | |
| background: #111; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| height: 100vh; | |
| } | |
| canvas { | |
| border: 2px solid #0ff; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <script> | |
| let ball; | |
| let paddles; | |
| let particles = []; | |
| let sparks = []; | |
| function setup() { | |
| createCanvas(800, 600); | |
| ball = { | |
| pos: createVector(width / 2, height / 2), | |
| vel: createVector(random(-5, 5), random(-5, 5)), | |
| r: 10, | |
| color: color(0, 255, 255), | |
| }; | |
| paddles = [ | |
| { | |
| x: 50, | |
| y: height / 2 - 50, | |
| w: 10, | |
| h: 100, | |
| color: color(255, 0, 255), | |
| score: 0, | |
| speed: 5, | |
| }, | |
| { | |
| x: width - 60, | |
| y: height / 2 - 50, | |
| w: 10, | |
| h: 100, | |
| color: color(0, 255, 0), | |
| score: 0, | |
| speed: 5, | |
| }, | |
| ]; | |
| } | |
| function draw() { | |
| // Draw dark grid background | |
| background(10, 10, 20); | |
| stroke(0, 100, 100, 50); | |
| strokeWeight(1); | |
| for (let x = 0; x < width; x += 20) line(x, 0, x, height); | |
| for (let y = 0; y < height; y += 20) line(0, y, width, y); | |
| // Draw arena borders | |
| noFill(); | |
| stroke(0, 255, 255); | |
| strokeWeight(4); | |
| rect(10, 10, width - 20, height - 20); | |
| // Update and draw ball | |
| ball.pos.add(ball.vel); | |
| for (let i = 0; i < 2; i++) { | |
| let p = paddles[i]; | |
| if ( | |
| ball.pos.x - ball.r < p.x + p.w && | |
| ball.pos.x + ball.r > p.x && | |
| ball.pos.y > p.y && | |
| ball.pos.y < p.y + p.h | |
| ) { | |
| let hitPos = (ball.pos.y - (p.y + p.h / 2)) / (p.h / 2); | |
| let angle = map(hitPos, -1, 1, -PI / 4, PI / 4); | |
| let speed = ball.vel.mag(); | |
| ball.vel | |
| .set(cos(angle) * (i === 0 ? 1 : -1), sin(angle)) | |
| .setMag(speed * 1.05); | |
| createSparks(ball.pos.x, ball.pos.y, p.color); | |
| } | |
| } | |
| // Ball wall collisions | |
| if (ball.pos.y - ball.r < 10 || ball.pos.y + ball.r > height - 10) { | |
| ball.vel.y *= -1; | |
| createSparks(ball.pos.x, ball.pos.y, ball.color); | |
| } | |
| // Scoring | |
| if (ball.pos.x < 0) { | |
| paddles[1].score++; | |
| resetBall(); | |
| } else if (ball.pos.x > width) { | |
| paddles[0].score++; | |
| resetBall(); | |
| } | |
| // Draw ball with glow | |
| noStroke(); | |
| fill(ball.color); | |
| ellipse(ball.pos.x, ball.pos.y, ball.r * 2); | |
| fill(255, 255, 255, 100); | |
| ellipse(ball.pos.x, ball.pos.y, ball.r * 1.5); | |
| // Particle trail | |
| particles.push({ pos: ball.pos.copy(), life: 60 }); | |
| particles = particles.filter((p) => p.life > 0); | |
| for (let p of particles) { | |
| fill(0, 255, 255, map(p.life, 0, 60, 0, 100)); | |
| noStroke(); | |
| ellipse(p.pos.x, p.pos.y, 5); | |
| p.life--; | |
| } | |
| // Sparks | |
| sparks = sparks.filter((s) => s.life > 0); | |
| for (let s of sparks) { | |
| fill(s.color, map(s.life, 0, 30, 0, 200)); | |
| noStroke(); | |
| ellipse(s.pos.x, s.pos.y, s.size); | |
| s.pos.add(s.vel); | |
| s.life--; | |
| } | |
| // Update and draw paddles | |
| if (keyIsDown(87)) paddles[0].y -= paddles[0].speed; // W | |
| if (keyIsDown(83)) paddles[0].y += paddles[0].speed; // S | |
| if (keyIsDown(UP_ARROW)) paddles[1].y -= paddles[1].speed; | |
| if (keyIsDown(DOWN_ARROW)) paddles[1].y += paddles[1].speed; | |
| for (let p of paddles) { | |
| p.y = constrain(p.y, 10, height - p.h - 10); | |
| fill(p.color); | |
| noStroke(); | |
| rect(p.x, p.y, p.w, p.h); | |
| fill(255, 255, 255, 100); | |
| rect(p.x, p.y, p.w, p.h * 0.8); | |
| } | |
| // Draw scores | |
| textSize(32); | |
| textAlign(CENTER); | |
| fill(0, 255, 255); | |
| text(paddles[0].score, width / 4, 50); | |
| text(paddles[1].score, (3 * width) / 4, 50); | |
| } | |
| function resetBall() { | |
| ball.pos.set(width / 2, height / 2); | |
| ball.vel.set(random(-5, 5), random(-5, 5)); | |
| } | |
| function createSparks(x, y, c) { | |
| for (let i = 0; i < 10; i++) { | |
| sparks.push({ | |
| pos: createVector(x, y), | |
| vel: p5.Vector.random2D().mult(random(2, 5)), | |
| size: random(2, 6), | |
| life: 30, | |
| color: c, | |
| }); | |
| } | |
| } | |
| </script> | |
| </body> | |
| </html> | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment