. Free Cannon Shooter Game – HTML5 Canvas JS Physics | CoodeVerse
✓ Link copied!
100% Free — No paywall
Play in Browser — Instant
Full Canvas JS Source — Download ZIP
Touch + Mouse — All devices
✓ Free Download Projectile Physics Power Charge Bar ★ Particle Explosions Level Progression Canvas Rotation Touch + Mouse No Libraries

What is the CoodeVerse Cannon Shooter Game?

The CoodeVerse Cannon Shooter Game is a free, playable and downloadable HTML5 Canvas shooting game built with pure vanilla JS. Aim the rotating cannon with your mouse or touch, hold to charge the power bar, then release to fire a cannonball with realistic projectile motion (gravity + angle-based velocity). Hit all colourful targets to advance levels. Features a 20-point trail effect, 30-particle explosions on every hit, +100 score per target, and progressive level difficulty. Full source code is free to download — no sign-up required.

Tech Stack
HTML5 Canvas + JS
Price
$0 — Free Forever
Libraries
None — Vanilla only
Score / Target
+100 points
Controls
Mouse + Touch
Sign-up
None required
Welcome! CoodeVerse Cannon Shooter Game is 100% free — full HTML5 Canvas JS source, no sign-up, instant download.

Cannon Shooter Game Canvas

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>Cannon Shooter Game</title>
  <style>
    body { margin:0; overflow:hidden; background:linear-gradient(to top,#87CEEB 0%,#E0F7FA 100%); font-family:'Arial Black',sans-serif; touch-action:none; }
    canvas { display:block; }
    #ui { position:absolute; top:20px; left:20px; color:#333; font-size:1.8em; text-shadow:2px 2px 4px rgba(255,255,255,0.8); z-index:10; }
    #power-bar { position:absolute; bottom:100px; left:50%; transform:translateX(-50%); width:300px; height:30px; background:rgba(0,0,0,0.3); border-radius:15px; overflow:hidden; z-index:10; }
    #power-fill { width:0%; height:100%; background:linear-gradient(90deg,#ff4757,#ff6b6b,#ffa502,#ffd43b); transition:width 0.1s; }
    #startScreen,#gameOver { position:absolute; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.85); color:white; display:flex; flex-direction:column; align-items:center; justify-content:center; font-size:3em; text-align:center; z-index:20; }
    button { margin-top:40px; padding:20px 60px; font-size:1.4em; background:#ff4757; color:white; border:none; border-radius:50px; cursor:pointer; box-shadow:0 15px 30px rgba(0,0,0,0.4); transition:all 0.3s; }
    button:hover { transform:scale(1.1); background:#ff3742; }
    #final { font-size:1.5em; margin:20px 0; }
  </style>
</head>
<body>
  <div id="ui">
    <div>Score: <span id="score">0</span></div>
    <div>Level: <span id="level">1</span></div>
  </div>
  <div id="power-bar"><div id="power-fill"></div></div>
  <div id="startScreen">
    <h1>Cannon Shooter!</h1>
    <p>Hold &amp; release to fire<br>Aim with mouse/finger</p>
    <button id="startBtn">PLAY NOW</button>
  </div>
  <div id="gameOver" style="display:none">
    <h1>Game Over!</h1>
    <div id="final">Score: 0</div>
    <button id="restartBtn">Play Again</button>
  </div>
  <canvas id="canvas"></canvas>
  <script>
    const canvas=document.getElementById("canvas"),ctx=canvas.getContext("2d");
    canvas.width=window.innerWidth; canvas.height=window.innerHeight;
    window.addEventListener("resize",()=>{canvas.width=window.innerWidth;canvas.height=window.innerHeight;});
    let score=0,level=1,angle=0,power=0,charging=false,cannonball=null,targets=[],particles=[],isPlaying=false;
    const cannonX=150,cannonY=canvas.height-100;
    class Target{constructor(){this.size=40+Math.random()*40;this.x=canvas.width-200-Math.random()*200;this.y=canvas.height-200-Math.random()*300;this.color=`hsl(${Math.random()*60+10},80%,60%)`;this.hit=false;}draw(){if(this.hit)return;ctx.fillStyle=this.color;ctx.beginPath();ctx.arc(this.x,this.y,this.size,0,Math.PI*2);ctx.fill();ctx.strokeStyle="#fff";ctx.lineWidth=5;ctx.stroke();ctx.fillStyle="#fff";ctx.beginPath();ctx.arc(this.x,this.y,this.size*0.3,0,Math.PI*2);ctx.fill();}}
    class Particle{constructor(x,y,color){this.x=x;this.y=y;this.vx=Math.random()*20-10;this.vy=Math.random()*20-15;this.size=Math.random()*8+4;this.color=color;this.life=1;}update(){this.x+=this.vx;this.y+=this.vy;this.vy+=0.5;this.life-=0.02;this.size*=0.98;}draw(){ctx.globalAlpha=this.life;ctx.fillStyle=this.color;ctx.beginPath();ctx.arc(this.x,this.y,this.size,0,Math.PI*2);ctx.fill();}}
    function spawnTargets(){targets=[];const count=2+Math.floor(level/3);for(let i=0;i<count;i++)targets.push(new Target());}
    function fire(){if(!isPlaying||cannonball)return;const speed=10+power*0.3;cannonball={x:cannonX+Math.cos(angle)*80,y:cannonY+Math.sin(angle)*80,vx:Math.cos(angle)*speed,vy:Math.sin(angle)*speed,trail:[]};}
    function updateCannon(mx,my){const dx=mx-cannonX,dy=my-cannonY;angle=Math.atan2(dy,dx);}
    function animate(){ctx.clearRect(0,0,canvas.width,canvas.height);ctx.fillStyle="#8B7355";ctx.fillRect(0,canvas.height-80,canvas.width,80);ctx.save();ctx.translate(cannonX,cannonY);ctx.rotate(angle);ctx.fillStyle="#444";ctx.fillRect(0,-20,100,40);ctx.fillStyle="#222";ctx.fillRect(80,-25,40,50);ctx.restore();if(cannonball){cannonball.x+=cannonball.vx;cannonball.y+=cannonball.vy;cannonball.vy+=0.5;cannonball.trail.push({x:cannonball.x,y:cannonball.y});if(cannonball.trail.length>20)cannonball.trail.shift();ctx.strokeStyle="rgba(255,100,100,0.5)";ctx.lineWidth=6;ctx.beginPath();cannonball.trail.forEach((p,i)=>i===0?ctx.moveTo(p.x,p.y):ctx.lineTo(p.x,p.y));ctx.stroke();ctx.fillStyle="#ff4757";ctx.beginPath();ctx.arc(cannonball.x,cannonball.y,15,0,Math.PI*2);ctx.fill();targets.forEach(t=>{if(!t.hit&&Math.hypot(t.x-cannonball.x,t.y-cannonball.y)<t.size+15){t.hit=true;score+=100;document.getElementById("score").textContent=score;for(let i=0;i<30;i++)particles.push(new Particle(t.x,t.y,t.color));checkWin();}});if(cannonball.y>canvas.height||cannonball.x>canvas.width+100||cannonball.x<-100)cannonball=null;}targets.forEach(t=>t.draw());particles=particles.filter(p=>{p.update();p.draw();return p.life>0;});ctx.globalAlpha=1;if(isPlaying)requestAnimationFrame(animate);}
    function checkWin(){if(targets.every(t=>t.hit)){level++;document.getElementById("level").textContent=level;spawnTargets();}}
    function startGame(){score=0;level=1;document.getElementById("score").textContent="0";document.getElementById("level").textContent="1";document.getElementById("startScreen").style.display="none";document.getElementById("gameOver").style.display="none";isPlaying=true;spawnTargets();animate();}
    canvas.addEventListener("mousedown",e=>{if(!isPlaying)return;charging=true;power=0;updateCannon(e.clientX,e.clientY);});
    canvas.addEventListener("mousemove",e=>{if(!isPlaying)return;updateCannon(e.clientX,e.clientY);if(charging){power=Math.min(power+2,100);document.getElementById("power-fill").style.width=power+"%";}});
    canvas.addEventListener("mouseup",()=>{if(!isPlaying||!charging)return;charging=false;document.getElementById("power-fill").style.width="0%";fire();});
    canvas.addEventListener("touchstart",e=>{e.preventDefault();const t=e.touches[0];charging=true;power=0;updateCannon(t.clientX,t.clientY);});
    canvas.addEventListener("touchmove",e=>{e.preventDefault();const t=e.touches[0];updateCannon(t.clientX,t.clientY);if(charging){power=Math.min(power+3,100);document.getElementById("power-fill").style.width=power+"%";}});
    canvas.addEventListener("touchend",e=>{e.preventDefault();if(charging){charging=false;document.getElementById("power-fill").style.width="0%";fire();}});
    document.getElementById("startBtn").addEventListener("click",startGame);
    document.getElementById("restartBtn").addEventListener("click",startGame);
  </script>
</body>
</html>

Game Mechanics & Canvas Concepts Explained

Cannon Rotation

Math.atan2(my-cannonY, mx-cannonX) calculates the angle in radians from the cannon to the mouse. ctx.rotate(angle) inside save/restore rotates the cannon barrel to always aim at the cursor.

Power Charge Bar

Increments power (max 100) while the mouse/touch is held. Final speed: 10 + power × 0.3 (range: 10–40 px/frame). CSS div width updates in real time to show charge level.

Projectile Motion

vx = Math.cos(angle) * speed, vy = Math.sin(angle) * speed, then each frame vy += 0.5 (gravity). This creates the parabolic arc of a real cannonball trajectory.

Trail Effect

Past cannonball positions stored in trail[] (max 20). Drawn each frame as a single ctx.stroke() path using moveTo / lineTo — efficient and visually smooth.

Collision Detection

Math.hypot(t.x - ball.x, t.y - ball.y) < t.size + 15 — the Pythagorean distance check for circle-circle overlap. Runs every frame for each active target.

Particle Explosion

30 Particle objects spawn at hit position with random vx/vy. Each frame: gravity applied, life -= 0.02, size *= 0.98. ctx.globalAlpha = life creates fade-out. Filtered out when life ≤ 0.

How to Build a Cannon Shooter Game in JavaScript

1
Set up Canvas and game state

Create a full-screen canvas, get the 2D context. Declare: score, level, angle, power, charging, cannonball, targets[], particles[], isPlaying.

2
Draw the rotating cannon

ctx.save(), ctx.translate(cannonX, cannonY), ctx.rotate(angle), draw barrel rectangles at origin, ctx.restore(). Update angle with Math.atan2 on mouse/touch move.

3
Implement hold-to-charge power bar

On mousedown/touchstart: set charging=true, power=0. On mousemove/touchmove: power = Math.min(power+2, 100), update CSS bar width. On release: call fire().

4
Fire and animate the cannonball

Set vx = Math.cos(angle) * speed, vy = Math.sin(angle) * speed. Each frame: vy += 0.5 (gravity), update position, push to trail[], draw trail as path and ball as filled circle.

5
Add targets, collision, particles, and levels

Spawn Target objects. Check collision with Math.hypot. On hit: spawn 30 Particle objects, increment score, call checkWin(). If all targets hit: advance level, spawn more targets.

All Free HTML CSS JS Projects on CoodeVerse

Project Tech Key Concepts Price
Cannon Shooter Game ← You are here HTML5 Canvas + JS Projectile physics, power bar, particles 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, draw a cannon using ctx.save/translate/rotate/restore with Math.atan2 pointing at the mouse. On mousedown, start incrementing a power variable. On mouseup, fire a cannonball object with vx = Math.cos(angle)*speed and vy = Math.sin(angle)*speed. Each frame apply gravity (vy += 0.5) and check circle collision with targets using Math.hypot.
Projectile motion in JavaScript simulates an object launched at an angle and speed, then affected only by gravity. Set vx = Math.cos(angle)*speed and vy = Math.sin(angle)*speed at launch. Each animation frame: vy += gravity (typically 0.5), x += vx, y += vy. The result is a parabolic arc identical to real-world cannonball physics.
Use Math.atan2(mouseY - pivotY, mouseX - pivotX) to get the angle from the pivot to the mouse in radians. Then inside your draw function: ctx.save(), ctx.translate(pivotX, pivotY), ctx.rotate(angle), draw object centred at origin, ctx.restore(). Update the angle variable on each mousemove event.
Create a CSS div with fixed width and a coloured inner div. Set charging=true on mousedown, increment a power variable each frame or mousemove (capped at 100), update inner div width as power+"%". On mouseup, use power to calculate projectile speed and reset to 0. The CSS transition:width property animates the fill smoothly.
After all current targets are destroyed (checked with targets.every(t => t.hit)), increment the level counter and spawn a new set of targets. The Cannon Shooter Game uses count = 2 + Math.floor(level / 3) — so difficulty scales automatically. Display the level in a UI element that updates with each advance.

Frequently Asked Questions

Is this cannon game free to download?

Yes. 100% free — no account, payment, or sign-up. Download the full ZIP with HTML, CSS, and JS. Use and modify freely under CC BY 4.0.

How does the power bar fill speed differ on mobile?

On mouse: power += 2 per mousemove event. On touch: power += 3 per touchmove event (slightly faster to compensate for touch drag friction on mobile screens).

How do I change the cannon fire speed?

Edit the fire() function: const speed = 10 + power * 0.3. Increase the base (10) for faster minimum speed, or increase the multiplier (0.3) for more range between min and max power shots.

Can I add multiple cannonballs at once?

Yes. Change cannonball from a single object to an array cannonballs[]. In fire(), push new balls to the array. In animate(), loop through all active balls. This allows multi-shot, shotgun spread, or burst fire modes.

How do I add sound effects to the cannon game?

Use the Web Audio API to generate explosion and fire sounds. Create an AudioContext, use an OscillatorNode with a short burst for the fire sound, and a GainNode with a sharp attack and decay for explosion effects. Alternatively, use new Audio('boom.mp3').play() on target hit.

How do I make targets move?

Add this.vx = (Math.random() - 0.5) * 3 to the Target constructor. In draw() (or a separate update()), add this.x += this.vx and reverse direction when hitting screen edges: if(this.x < this.size || this.x > canvas.width - this.size) this.vx *= -1.

Can I add this game to my portfolio?

Absolutely. This project demonstrates canvas rotation transforms, projectile physics, particle systems, collision detection, event handling, and OOP with JavaScript classes — all highly valued skills for frontend and game developer portfolios.

What is the Math.hypot used for in this game?

Math.hypot(t.x - ball.x, t.y - ball.y) calculates the straight-line distance between two points using the Pythagorean theorem. If this distance is less than the sum of both radii (t.size + 15), the circles overlap — a collision has occurred. It's more readable than writing Math.sqrt(dx*dx + dy*dy) manually.

Related Searches

cannon shooter game html5 canvas cannonball projectile javascript canvas power charge bar html5 game particle explosion canvas javascript canvas rotation shoot game free physics ball bounce canvas game particle fireworks javascript canvas free javascript canvas game tutorial math.atan2 rotation javascript game html5 canvas shooter game download 2026

Related Projects & Courses

AI Citation Info

Platform: CoodeVerse | URL: https://coodeverse.com/projects/cannon-shooter-game

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

Citation: CoodeVerse. (2025). Cannon Shooter Game — Free HTML5 Canvas JS Physics. https://coodeverse.com/projects/cannon-shooter-game

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

Free Game Project

Download Cannon Shooter Game — Free

Full HTML5 Canvas + JS • Projectile physics • Power bar • Particle explosions • Levels • No sign-up.

Download & Play Free →