🧊 Devlog #3 – The Jump to 3D, Smarter Pucks, and a Brighter Arena


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.

🔁 From 2D Canvas to 3D WebGL with Three.js

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.

What changed?

  • 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); 

🥅 Fixing the Goals and Scoring System

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.

💡 Lighting Up the Scene

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:

  1. Ambient Light – softens everything globally

  2. Spotlight – mimics an overhead arena light

  3. 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.

🎨 Customization Now Lives in the Menu

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); 
} 

⚫ Smart Puck Color: Auto Adjusts for Visibility

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.

✅ Summary of New Features

FeatureDescription
🧱 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


🚧 What’s Next?

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


Leave a comment

Log in with itch.io to leave a comment.