Posted May 30, 2025 by SteelCycloneStudios
#Air Hockey #devlog #html #javascript #game development
Hey puck champs! 👋
It’s been an exciting ride building Velocity Puck, and with this third update, we’ve taken the biggest leap yet: from flat 2D gameplay to a full 3D arena using Three.js!
This post is all about how the new 3D version works under the hood, key challenges we tackled, and quality-of-life upgrades that make the game smoother, smarter, and better to look at. Let’s break it all down.
The original versions of Velocity Puck were rendered using the HTML5 <canvas> element in 2D. While that gave us quick iteration speed and simplicity, it also limited how immersive the experience could feel.
So for this update, we converted the core gameplay into 3D using Three.js.
The air hockey table, paddles, puck, walls, and goals are now full 3D Mesh objects.
The puck and paddle use cylindrical geometries and the table is a sleek BoxGeometry.
The camera hovers above at an angle, giving you a clean top-down view of the action.
Movement and collisions are now handled in 3D space (especially the z-axis for depth).
js const tableGeometry = new THREE.BoxGeometry(40, 2, 60); const paddleGeometry = new THREE.CylinderGeometry(2.5, 2.5, 1, 32); const puckGeometry = new THREE.CylinderGeometry(1.5, 1.5, 1, 32);
Goals are now physical 3D objects (BoxGeometry) placed at the far ends of the rink. The scoring logic was rewritten to trigger only if:
The puck enters the scoring zone
Its x-position is within goal width range
js
if (puck.position.z <= -28 && Math.abs(puck.position.x) < 7.5) {
playerScore++;
resetPuck('player');
} else if (puck.position.z >= 28 && Math.abs(puck.position.x) < 7.5) {
aiScore++;
resetPuck('ai');
}
This fixed earlier bugs where the puck could bounce inside a goal area without scoring.
One of the first things I noticed when switching to 3D was... it was dark.
So I introduced a trio of lights to fix that:
Ambient Light – softens everything globally
Spotlight – mimics an overhead arena light
Fill Light – adds contrast and prevents harsh shadows
js const ambientLight = new THREE.AmbientLight(0xffffff, 1.0); const spotLight = new THREE.SpotLight(0xffffff, 2.0); const fillLight = new THREE.DirectionalLight(0xffffff, 0.8);
All objects (walls, paddles, puck, etc.) also got a Phong material with shininess and specular reflection to make them visually pop.
Previously, color selections for the paddle and table were floating on the screen. Now they live inside the side panel menu, making the UI cleaner and more game-like.
html
<div id="colorOptionsContainer">
<div class="color-section">
<div class="color-section-title">Paddle Colors</div>
<div id="colorMenu">…</div> </div>
<div class="color-section">
<div class="color-section-title">Field Colors</div>
<div id="fieldColorMenu">…</div>
</div>
</div>
Clicking “Colors” in the menu toggles these options, and they respond instantly via JavaScript to update the scene:
js
function updatePaddleColor(color) {
playerPaddleMaterial.color.setStyle(color);
aiPaddleMaterial.color.setStyle(color);
}
One new smart feature I’m really proud of:
If the field is white, the puck becomes black to stay visible. Otherwise, it defaults to light gray.
js
function updateFieldColor(color) {
tableMaterial.color.setStyle(color);
if (color === '#ffffff') {
puckMaterial.color.setStyle('#000000');
} else {
puckMaterial.color.setStyle('#ecf0f1');
}
}
It’s a small change that improves readability and contrast, especially for users with visual sensitivities or when playing in light mode.
| Feature | Description |
|---|---|
| 🧱 3D Environment | All assets converted using Three.js |
| 💡 Lighting | Ambient, spotlight, and directional fill |
| 🥅 Fixed Goals | Accurate scoring and reset mechanics |
| 🎨 Color Menus | Tucked inside the side panel for cleanliness |
| ⚫ Smart Puck Color | Adjusts for white backgrounds automatically |
| 🛑 Pause / Theme | Still works from the menu with updated UI |
Now that we’re in 3D territory, I’m exploring:
Real-time shadows and reflections
3D goal animations (e.g., particle burst or screen shake)
Multiplayer mode (LAN or online)
A true match settings screen with difficulty and score limit
Velocity Puck is starting to look and feel like a real arena sport now, and your feedback has been awesome so far. If you’ve played the new version, let me know what you think!
Thanks again for reading — and for skating with me through this journey.
— Jordon, Steel Cyclone Studios