Devlog #1 โ€“ How Velocity Puck Started (From 2D Beginnings)


Hey everyone! ๐Ÿ‘‹

Welcome to the very first devlog for Velocity Puck, a fast-paced, physics-driven vertical air hockey-inspired game built for the web browser. In this post, I want to share how the project began, what the early development process looked like, and how the code powering the first version actually works under the hood.

๐ŸŽฎ From Simple 2D to Something Bigger

Velocity Puck started out as a 2D experiment. I wanted to recreate that satisfying feeling of smacking a puck around on an air hockey table — but with a twist: vertical gameplay, cool particle effects, and a future vision of multiplayer and power-ups.

To keep things light and accessible, I built the first version entirely with HTML, CSS, and JavaScript, no frameworks or engines. Just good old canvas and some physics logic to get things moving.

This foundation was key. Before adding arenas, themes, or complex mechanics, I needed a smooth, responsive core — something that felt good to play right away.

๐Ÿ”ง What's in the Code?

All of this lives in a single index.html file. Let me break it down:

1. ๐ŸŽจ HTML Structure

๐ŸŽฏ The Canvas

html
<canvas id="gameCanvas" width="800" height="600"></canvas>
  • The game runs inside a single HTML5 <canvas>.

  • I chose a vertical layout to differentiate it from traditional horizontal air hockey.

  • This approach gave direct control over rendering without relying on external libraries like Pixi.js or Three.js and keeps performance snappy on mobile and desktop.

2. ๐Ÿง  Game Logic in JavaScript

Within the <script> tags, youโ€™ll find:

a. Game Loop Setup

The game loop uses requestAnimationFrame to keep things smooth at 60 FPS:

js
function gameLoop() 
{      
    update();      
    draw();      
    requestAnimationFrame(gameLoop);  
}  
gameLoop();

 ๐Ÿฅ… Objects: Paddle, Puck, and AI

b. Basic Objects: Puck and Paddles
js
let puck = { x: 400, y: 300, vx: 3, vy: 3, radius: 10 }; 
let paddle1 = { x: 100, y: 300, radius: 20 }; 
let paddle2 = { x: 700, y: 300, radius: 20 };
  • Everything starts as simple objects—positions and velocities define movement.  
  • Each object is defined with simple properties.  
  • No classes yet; this keeps things lightweight and easy to debug early on.
  • Movements are handled by updating their positions based on velocity.

๐Ÿงฑ Collisions, Bouncing & Scoring 

c. Collision & Bouncing
js 
if (puck.x - puck.radius < 0 || puck.x + puck.radius > canvas.width) puck.vx *= -1; 
if (puck.y - puck.radius < 0 || puck.y + puck.radius > canvas.height) puck.vy *= -1;
  • Basic collision with the canvas boundaries gives the puck bounce.

  • Puck bounces off walls and interacts with the paddles.

  • More advanced collision logic will evolve from here—especially paddle interactions, deflection angles, and realistic friction.

  • If the puck enters the goal zone, a point is scored and the puck resets.

  • I added explosions using particles when goals are scored, which adds some satisfying feedback.

๐Ÿ•น๏ธ Controls

d. Input Handling
js
document.addEventListener('mousemove', function (e) {
     paddle1.y = e.clientY - canvas.getBoundingClientRect().top;
 });
  • Player moves their paddle using mouse or touch input.

  • AI paddle moves based on puck position with a bit of artificial delay to make things fair (but not too easy!).

  • This will eventually support keyboard/gamepad controls and two-player mechanics.

๐ŸŒˆ Customization

  • Thereโ€™s a color selector for both the paddle and the field.

  • You can also toggle between light and dark themes.

  • Itโ€™s a small touch, but it adds to the vibe and replayability.


๐ŸŽจ 1. Paddle Color Customization

โœ… Feature:

Players can choose their paddle color from a vertical menu of swatches on the left.

๐Ÿ’ก How It Works:

HTML:

Each color option is a button with a specific data-color value:

html
<div id="colorMenu">   
  <div class="colorBtn" style="background:#e74c3c" data-color="#e74c3c"></div>   
  <div class="colorBtn" style="background:#2ecc71" data-color="#2ecc71"></div>   
<!-- more colors --> 
</div> 

JavaScript:

Each button updates the paddle.color when clicked:

js
document.querySelectorAll('#colorMenu .colorBtn').forEach(btn => {   
  btn.addEventListener('click', function () {    
    // Remove 'selected' from all buttons     
    document.querySelectorAll('#colorMenu .colorBtn').forEach(b => b.classList.remove('selected'));  
        
    // Add 'selected' style to the clicked one     
    this.classList.add('selected');          
    // Update the paddle color     
    paddle.color = this.dataset.color;   
  }); 
}); 

Rendering:

In the drawPaddle() function, the selected color is used every frame:

js
drawPaddle(paddle.x, paddle.y, paddle.radius, paddle.color); 

๐ŸŸฉ 2. Field Color Customization

โœ… Feature:

Players can also change the background color of the hockey table (the field).

๐Ÿ’ก How It Works:

HTML:

On the right, another vertical menu contains swatches for the field:

html
<div id="fieldColorMenu">   
  <div class="colorBtn" style="background:#00366d" data-field-color="#00366d"></div>   
<!-- more colors --> 
</div> 

JavaScript:

Clicking one of these buttons updates the global fieldColor variable:

js
document.querySelectorAll('#fieldColorMenu .colorBtn').forEach(btn => {
  btn.addEventListener('click', function () {     
    // Unselect previous    
    document.querySelectorAll('#fieldColorMenu .colorBtn').forEach(b => b.classList.remove('selected')); 
    // Highlight this one     
    this.classList.add('selected');  
        
    // Change field color     
    fieldColor = this.dataset.fieldColor;  
  }); 
}); 

Rendering:

The background color is drawn every frame in drawTable():

js
ctx.fillStyle = fieldColor; 
ctx.fillRect(0, 0, canvas.width, canvas.height); 

โœจ Styling Feedback with .selected

Both color menus use this visual cue:

css
.colorBtn.selected {   
  transform: scale(1.2);  
  box-shadow: 0 0 10px white; 
} 

When a color is active, it grows slightly and glows, giving instant feedback.


๐Ÿงช Bonus: Menu Toggles for UI Cleanliness

You also added toggles to show/hide the color menus via the side-panel menu:

js
case 1: // Colors   
document.getElementById('colorMenu').style.display =      
document.getElementById('colorMenu').style.display === 'none' ? 'flex' : 'none';   
break; 
case 2: // Field Colors   
document.getElementById('fieldColorMenu').style.display =      
document.getElementById('fieldColorMenu').style.display === 'none' ? 'flex' : 'none';   
break; 

๐Ÿง  Summary

CustomizationVariableMenu IDEvent LogicDraw Function
Paddle Color paddle.color #colorMenu data-color drawPaddle()
Field Background fieldColor #fieldColorMenu data-field-color drawTable()


These systems are super extensible—you can easily add avatar styles, puck skins, or particle trails later using the same pattern.

โœจ Why Keep It Simple?

Starting with a single HTML file let me:

  • Test mechanics quickly

  • Debug easily without a build system or complex architecture

  • Avoid setup overhead and to establish a clear visual and interactive baseline

  • Keep the prototype fun, flexible and test fast without overengineering

  • Get something playable now instead of perfecting too early

This minimal setup makes iteration super easy and perfect for deploying to sites like itch.io, CrazyGames, or Facebook Instant Games later.

๐Ÿš€ Whatโ€™s Coming Next?

Hereโ€™s what Iโ€™m planning for future updates:

  • A Menu system

  • Smarter AI with different difficulty levels

  • More arena environments with unique themes

  • Power-ups and puck modifiers

  • Multiplayer support (eventually)

  • Custom game modes (tournament, party mode, etc.)

Iโ€™m also considering expanding to a 3D version using Three.js later on — but only once the 2D mechanics are perfect.

๐Ÿงช Try It Out & Stay Tuned

If youโ€™re reading this on itch.io, feel free to try the current build and let me know what you think! Your feedback means a lot and helps shape what comes next.

Thanks for checking out the first devlog — more updates soon!

Jordon McClain
 Steel Cyclone Studios LLC

Leave a comment

Log in with itch.io to leave a comment.