How i made Ping Pong in 1 night.
Sometimes, inspiration for a coding project strikes in the most unexpected places. For me, it wasn’t at a hackathon or a tech conference, but at a unique cultural festival in rural Germany, surrounded by my family. This is the story of how a cool analog game I saw at the “Kulturelle Landpartie” inspired me to build my own digital version with JavaScript, and how you can do it too.
A Spark of Inspiration at the Kulturelle Landpartie
Every year, in the Wendland region near the Lüneburger Heide, a massive, decentralized art and culture event called the Kulturelle Landpartie takes place. It’s a fascinating mix of open-air galleries, craft markets, political discourse, and music, spread across dozens of villages. The event has deep roots in the local anti-nuclear movement, which protested against the storage of radioactive waste (“Atom-Müll”) in nearby Gorleben. This gives the whole festival a unique, grassroots, and slightly rebellious vibe that you can’t find anywhere else.
While wandering through one of the many “Wunderpunkte” (wonder points) with my family, we stumbled upon a beautifully simple, mechanically operated Ping Pong installation. It wasn’t digital; it was all levers, wood, and ingenuity. It was creative, engaging, and just plain fun. Watching people play, I felt that familiar programmer’s itch: “I wonder if I could build this.”
That idea stuck with me. I wanted to capture the simple joy of that game and create something I could share with anyone, anywhere.
Bringing the Game to Life with Code
When I got back to my computer, I decided to take on the challenge. My goal was to create a classic Ping Pong game that was simple, fun, and accessible. I chose to build it with technologies I was comfortable with but also wanted to explore further. The beauty of this project is its simplicity; the entire game consists of just three core files!
The Tech Stack & File Structure:
index.html
(The Stage): This is the foundation. It’s a minimal HTML file that contains a single<canvas>
element. This canvas is the “stage” where the entire game is drawn and played.renderer.js
(The Game Engine): This is where all the magic happens. The core logic of the game is written in plain vanilla JavaScript. It handles the game loop, the movement of the ball and paddles, collision detection, and scoring.package.json
(The Blueprint): This file defines the project and its dependencies. It tells Electron what the main file is and what the application is called, essentially serving as the blueprint for the desktop app.- Electron: To make it feel like a real desktop game, I wrapped the web app in an Electron container. Electron allows you to build cross-platform desktop apps with web technologies (HTML, JS, and CSS), which is perfect for this kind of project.
The Development Process:
- Setting up the Board: The first step was creating the game world. I used the
<canvas>
element inindex.html
and then, inrenderer.js
, I grabbed that canvas and its 2D rendering context. This context is what allows you to draw shapes. I started by drawing a black rectangle to fill the whole canvas and a dotted white line down the center to mimic a real ping pong table. - Creating the Paddles and Ball: The paddles and the ball are simple rectangles drawn on the canvas. I created JavaScript objects for each, holding their state: position (
x
,y
), dimensions (width
,height
), and velocity (velocityX
,velocityY
). The user’s paddle is controlled by mouse movement; an event listener tracks the cursor’s position and updates the paddle’sy
coordinate accordingly. - The Game Loop: This is the heartbeat of the game. Instead of
setInterval
, I usedrequestAnimationFrame
. This is a better practice for animations as it tells the browser you want to perform an animation and requests that the browser schedule a repaint of the window for the next animation frame. It’s more efficient and results in smoother animations. This loop runs repeatedly, updating the game state on each “tick.” In every tick, it:- Clears the canvas.
- Moves the ball based on its current velocity.
- Moves the computer-controlled paddle to follow the ball (with a slight delay to make it beatable!).
- Redraws the paddles, ball, and score on the canvas.
- Collision Detection: This was the most interesting part to code. I wrote logic to detect when the ball hits a paddle, the top/bottom walls, or the left/right walls (which means a player scored).
- Wall Collision: If the ball hits the top or bottom wall, I simply reverse its vertical velocity (
ball.velocityY = -ball.velocityY
). - Paddle Collision: When the ball’s coordinates overlap with a paddle’s coordinates, I reverse its horizontal velocity (
ball.velocityX = -ball.velocityX
). To make it more interesting, I also slightly increase the ball’s speed after each paddle hit, making the game progressively harder. - Score: If the ball goes past a paddle and hits the left or right wall, the appropriate player gets a point, and the ball is reset to the center, ready for the next serve.
- Wall Collision: If the ball hits the top or bottom wall, I simply reverse its vertical velocity (
Try It Yourself!
What started as a flicker of an idea at a German art festival has turned into a fully playable game that I’m proud to share. The project was a fantastic learning experience and a fun reminder that inspiration can come from anywhere.
I’ve made the game available for everyone to play online and put the entire source code on GitHub.
- Play the game in your browser: nyra.lol/pingpong
- Check out the code on GitHub: https://github.com/jvxjo/ping-pong
Feel free to fork the repository, suggest improvements, or just see how it all works. Happy coding!
Leave a Reply