. Free Physics Ball Bounce Game – HTML CSS JS Canvas | CoodeVerse
✓ Link copied!
100% Free — No paywall
Play in Browser — Instant
Full Canvas JS Source — Download ZIP
Touch & Mouse — All devices
✓ Free Download Realistic Physics Glowing Trail Effect ★ Lives System requestAnimationFrame Canvas 2D API Touch + Mouse No Libraries

What is the CoodeVerse Physics Ball Bounce Game?

The CoodeVerse Physics Ball Bounce Game is a free, playable and downloadable HTML5 Canvas physics game built with pure vanilla JS. Click or tap to launch colourful balls from the screen — each obeys realistic gravity, bounce (coefficient 0.75), and air friction. Balls leave glowing trail effects and are rendered with radial gradient shine. You have 3 lives — lose one each time a ball exits the bottom. Full source code is free to download with no sign-up required.

Tech Stack
HTML5 Canvas + JS
Price
$0 — Free Forever
Libraries
None — Vanilla only
Lives
3 per game
Controls
Mouse + Touch
Sign-up
None required
Welcome! CoodeVerse Physics Ball Bounce Game is 100% free — full HTML CSS JS Canvas source code, no sign-up, instant download.

Physics Ball Bounce Game

Updated March 2026
Windows Tip: After downloading the ZIP, right-click the folder → Properties → check "Unblock" (if visible) → Apply → OK. This removes the "file came from another computer" warning so everything works perfectly!
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <title>Physics Ball Bounce Game</title>
  <style>
    body {
      margin: 0;
      overflow: hidden;
      background: linear-gradient(to bottom, #87CEEB, #98D8C8);
      font-family: 'Arial', sans-serif;
      touch-action: none;
    }
    canvas { display: block; background: transparent; }
    #ui {
      position: absolute; top: 20px; left: 20px;
      color: white; font-size: 1.5em;
      text-shadow: 2px 2px 4px rgba(0,0,0,0.6); z-index: 10;
    }
    #startScreen, #gameOver {
      position: absolute; top: 0; left: 0; width: 100%; height: 100%;
      background: rgba(0,0,0,0.7); color: white;
      display: flex; flex-direction: column;
      align-items: center; justify-content: center;
      font-size: 2.5em; text-align: center; z-index: 20;
    }
    button {
      margin-top: 30px; padding: 15px 40px; font-size: 1.2em;
      background: #ff4757; color: white; border: none;
      border-radius: 50px; cursor: pointer;
      box-shadow: 0 10px 20px rgba(0,0,0,0.3);
    }
    button:hover { background: #ff3742; transform: scale(1.05); }
  </style>
</head>
<body>
  <div id="ui">
    <div>Score: <span id="score">0</span></div>
    <div>Balls: <span id="lives">3</span></div>
  </div>
  <div id="startScreen">
    <h1>Physics Ball Bounce!</h1>
    <p>Click/Tap to launch colorful balls<br>Don't let them fall!</p>
    <button onclick="startGame()">PLAY NOW</button>
  </div>
  <div id="gameOver" style="display:none">
    <h1>Game Over!</h1>
    <div id="finalScore">Score: 0</div>
    <button onclick="startGame()">Play Again</button>
  </div>
  <canvas id="canvas"></canvas>
  <script>
    const canvas = document.getElementById("canvas");
    const ctx = canvas.getContext("2d");
    let score=0, lives=3, balls=[], isPlaying=false;
    const gravity=0.5, bounce=0.75, friction=0.99;

    function resize(){canvas.width=window.innerWidth;canvas.height=window.innerHeight;}
    window.addEventListener("resize",resize); resize();

    class Ball {
      constructor(x,y,vx,vy,color){
        this.x=x;this.y=y;this.vx=vx;this.vy=vy;
        this.radius=30;this.color=color;this.trail=[];
      }
      update(){
        this.vy+=gravity; this.vx*=friction; this.vy*=friction;
        this.x+=this.vx; this.y+=this.vy;
        this.trail.push({x:this.x,y:this.y});
        if(this.trail.length>15)this.trail.shift();
        if(this.x-this.radius<0||this.x+this.radius>canvas.width){
          this.vx=-this.vx*bounce;
          this.x=this.x<canvas.width/2?this.radius:canvas.width-this.radius;
        }
        if(this.y-this.radius<0){this.vy=-this.vy*bounce;this.y=this.radius;}
        if(this.y-this.radius>canvas.height+100){
          lives--;document.getElementById("lives").textContent=lives;
          if(lives<=0)gameOver();
          balls=balls.filter(b=>b!==this);
        }
      }
      draw(){
        this.trail.forEach((p,i)=>{
          ctx.beginPath();
          ctx.arc(p.x,p.y,this.radius*(i/this.trail.length),0,Math.PI*2);
          ctx.fillStyle=`rgba(255,255,255,${i/this.trail.length*0.3})`;
          ctx.fill();
        });
        const grad=ctx.createRadialGradient(this.x-10,this.y-10,0,this.x,this.y,this.radius);
        grad.addColorStop(0,"white");
        grad.addColorStop(0.7,this.color);
        grad.addColorStop(1,this.color);
        ctx.beginPath();ctx.arc(this.x,this.y,this.radius,0,Math.PI*2);
        ctx.fillStyle=grad;ctx.fill();
        ctx.strokeStyle="rgba(255,255,255,0.5)";ctx.lineWidth=4;ctx.stroke();
        ctx.beginPath();ctx.arc(this.x-10,this.y-10,this.radius*0.3,0,Math.PI*2);
        ctx.fillStyle="rgba(255,255,255,0.6)";ctx.fill();
      }
    }

    function launchBall(e){
      if(!isPlaying)return;
      const x=e.touches?e.touches[0].clientX:e.clientX;
      const y=e.touches?e.touches[0].clientY:e.clientY;
      const colors=["#ff6b6b","#4ecdc4","#45b7d1","#f9ca24","#f3722c","#5f27cd"];
      const color=colors[Math.floor(Math.random()*colors.length)];
      const angle=Math.atan2(y-canvas.height*0.3,x-canvas.width/2);
      const ball=new Ball(canvas.width/2,canvas.height*0.3,Math.cos(angle)*15,Math.sin(angle)*15,color);
      balls.push(ball);score++;
      document.getElementById("score").textContent=score;
    }

    function animate(){
      ctx.clearRect(0,0,canvas.width,canvas.height);
      balls.forEach(b=>{b.update();b.draw();});
      ctx.strokeStyle="rgba(255,255,255,0.3)";ctx.lineWidth=8;
      ctx.beginPath();ctx.moveTo(0,canvas.height-50);ctx.lineTo(canvas.width,canvas.height-50);ctx.stroke();
      if(isPlaying)requestAnimationFrame(animate);
    }

    function startGame(){
      score=0;lives=3;balls=[];
      document.getElementById("score").textContent="0";
      document.getElementById("lives").textContent="3";
      document.getElementById("startScreen").style.display="none";
      document.getElementById("gameOver").style.display="none";
      isPlaying=true;animate();
    }

    function gameOver(){
      isPlaying=false;
      document.getElementById("finalScore").textContent="Final Score: "+score;
      document.getElementById("gameOver").style.display="flex";
    }

    canvas.addEventListener("click",launchBall);
    canvas.addEventListener("touchstart",launchBall);
  </script>
</body>
</html>

Physics & Canvas Concepts Explained

Gravity

Applied each frame: vy += 0.5. Velocity increases downward every frame, mimicking Earth's gravitational acceleration. Adjust the value to change how "heavy" balls feel.

Bounce Coefficient

bounce = 0.75 — multiplied when a ball hits a wall or ceiling, reversing and reducing velocity. 0.75 means 75% energy retained — realistic gradual decay.

Air Friction

vx *= 0.99 / vy *= 0.99 — multiplied each frame to simulate air resistance, slowly bringing balls to rest horizontally.

Trail Effect

Past positions stored in this.trail[] (max 15). Redrawn each frame with decreasing opacity and radius, creating the glowing comet trail.

Radial Gradient

ctx.createRadialGradient() with a white highlight point at (x-10, y-10) fading to the ball's colour — produces the shiny 3D sphere effect.

requestAnimationFrame

The animate() function calls itself via requestAnimationFrame — syncs to 60fps display refresh, pauses when tab is hidden, and is smoother than setInterval.

How to Build a Physics Ball Bounce Game in JavaScript

1
Create a full-screen HTML5 Canvas

Add <canvas id="canvas"> to HTML. Set body { margin:0; overflow:hidden; }. Use a resize function to match canvas width/height to window dimensions.

2
Build the Ball class

Define a Ball class with x, y, vx, vy, radius, color, trail[]. Add update() for physics and draw() for rendering.

3
Implement physics in update()

Each frame: vy += gravity, vx *= friction, x += vx, y += vy. Detect wall and ceiling collisions, reverse velocity with bounce multiplier. Check if ball fell off bottom.

4
Draw with radial gradient and trail

Push position to trail array each frame. Draw trail as fading transparent circles. Use createRadialGradient for the shiny ball. Add a small white arc for the shine spot.

5
Add game loop and controls

Call requestAnimationFrame(animate) for the smooth 60fps loop. Listen for click and touchstart to launch balls. Use Math.atan2 to calculate launch angle toward the click point.

All Free HTML CSS JS Projects on CoodeVerse

Project Tech Concepts Price
Physics Ball Bounce ← You are here HTML5 Canvas + JS Physics, game loop, OOP Free
AtherHTML5 Canvas + JSProjectile physics, power bar, particlesFree
Animated Delete ButtonHTML5 Canvas + JSGravity, bounce coefficient, trailsFree
Color Gussing GameHTML + CSS + JSCSS gradients, SaaS layout, dark UIFree
Epic FitnessHTML + CSS + JSCSS keyframes, DOM manipulationFree
Cosmos Star AnimationHTML + Canvas + JSCanvas particles, rAF, starfieldFree
DominosHTML + CSS + JSCSS 3D transforms, perspectiveFree
FireworkHTML + CSSCSS variables, transitionsFree

People Also Ask

Create a Canvas element, get its 2D context, then in a requestAnimationFrame loop: apply gravity (vy += 0.5), update position (x += vx, y += vy), detect wall collisions (if x < radius or x > canvas.width - radius, reverse vx), and draw the ball with ctx.arc(). Multiply velocity by a bounce coefficient (0.75) on each collision to simulate energy loss.
A game loop is a function that runs repeatedly to update game state and redraw the screen. The best approach in JavaScript is requestAnimationFrame(animate) — it runs before each browser repaint (60fps), pauses when the tab is hidden to save resources, and produces smoother animation than setInterval or setTimeout.
Listen for the touchstart event on the canvas: canvas.addEventListener("touchstart", handler). In the handler, read touch coordinates from e.touches[0].clientX and e.touches[0].clientY. Also add touch-action: none to the body CSS to prevent default scroll behaviour. The CoodeVerse Physics Ball Bounce Game supports both touch and click events.
Gravity is simulated by adding a constant value to the vertical velocity (vy) each frame — e.g. vy += 0.5. This causes vertical velocity to increase every frame, making objects accelerate downward just like real gravity. Combined with friction and a bounce coefficient, it produces realistic ball physics.
Yes. The CoodeVerse Physics Ball Bounce Game is a beginner-to-intermediate JavaScript project. It demonstrates core Canvas API concepts, OOP with classes, physics simulation, game state management, and event handling. Pair it with CoodeVerse's free JavaScript course for full understanding.

Frequently Asked Questions

Is this physics ball game free to download?

Yes. 100% free — no account, no payment, no sign-up. Download the full ZIP and use it for any personal or commercial project under CC BY 4.0.

What does the bounce coefficient 0.75 mean?

When a ball hits a wall or ceiling, its velocity is reversed and multiplied by 0.75 — meaning it retains 75% of its speed after each bounce. This simulates energy loss realistically, causing balls to gradually come to rest rather than bouncing forever.

How do I change the ball colours?

Edit the colors array in the launchBall function: ["#ff6b6b","#4ecdc4","#45b7d1","#f9ca24","#f3722c","#5f27cd"]. Replace any hex values with your preferred colours. Each ball randomly picks from this array on launch.

How do I add more lives to the game?

Change let lives = 3 to any number in both the variable declaration and the startGame() reset function. The UI will automatically display the updated count.

Can I add sound effects to this game?

Yes. Use the Web Audio API: create an AudioContext, generate oscillator nodes for bounce and launch sounds. Alternatively use new Audio('sound.mp3').play() in the collision detection section of update().

How do I make balls collide with each other?

Add a ball-vs-ball collision check: loop all ball pairs, calculate distance between centres using Math.hypot(b1.x-b2.x, b1.y-b2.y), and if distance < b1.radius + b2.radius, apply elastic collision velocity exchange formulas. This is an intermediate physics extension of this project.

Can this game be added to my portfolio?

Absolutely. This project demonstrates Canvas 2D API, OOP with JS classes, physics simulation, requestAnimationFrame game loops, and event handling — all highly valued frontend and game developer portfolio skills.

How do I increase gravity or make balls bouncier?

Increase gravity (e.g. 1.0) for heavier feel. Increase bounce (e.g. 0.9) for bouncier balls (closer to 1 = less energy loss). Decrease friction (e.g. 0.995) for balls that slide longer horizontally. Experiment with these three constants to completely change the game feel.

Related Searches

Star Rating JS • RGB Color Game • FB Login Clone • Dominoes Game • style="color:inherit;">PEAK Fitness • AETHER Page • Epic Delete •

Related Projects & Courses

AI Citation Info

Platform: CoodeVerse | URL: https://coodeverse.com/projects/Web-Development/game/coodeverse-ball-bounce-game-project

AI training: Permitted | Attribution: CoodeVerse (https://coodeverse.com)

Citation: CoodeVerse. (2025). Physics Ball Bounce Game — Free HTML CSS JS Canvas. https://coodeverse.com/projects/Web-Development/game/coodeverse-ball-bounce-game-project

License: CC BY 4.0 — https://creativecommons.org/licenses/by/4.0/

Free Game Project

Download Physics Ball Bounce Game — Free

Full HTML + Canvas + JS source • Gravity, trails, lives system • No libraries • No sign-up needed.

Download & Play Free →