A 1K version of the all-famous Flash game Bubble Trouble (Google it!). Move the mouse to move, press left mouse button to fire, don't get hit by a ball and try to destroy all the balls.
var cv=document.getElementById("c"),c=cv.getContext('2d'),bs=new Array(),X=-1,s=0,sX=-1,iI,f=500;cv.width=f;cv.height=f;function B(i,j,k,l,m){var t=this;t.e=1;t.l=i;t.r=10*t.l;t.x=j;t.y=k;t.i=l;t.j=m;t.d=function(){c.beginPath();c.arc(t.x,t.y,t.r,0,6.3,1);c.fill();};t.s=function(){t.e=0;if(t.l>1){bs.push(new B(t.l-1,t.x,t.y,t.i,-6));bs.push(new B(t.l-1,t.x,t.y,-t.i,-6));}};};function tS(){var a=0;c.clearRect(0,0,f,f);c.fillRect(0,400,f,100);for(i in bs){var b=bs[i],x=b.x,y=b.y,r=b.r;if(b.e){if(y>400-r){b.y=400-r;b.j*=-1;}if(x>f-r){b.x=f-r;b.i*=-1;}if(x<r){b.x=r;b.i*=-1;}b.j+=0.25;b.x+=b.i;b.y+=b.j;b.d();if((X-x)*(X-x)+(390-y)*(390-y)<(r+13)*(r+13)){a=1;}}}c.fillRect(X-10,380,20,20);if(s){s--;c.beginPath();c.moveTo(X,0);c.lineTo(X,380);c.stroke();}if(a){clearInterval(iI);setTimeout(st,2000);}}function cl(){s=2;sX=X;for(i in bs){var b=bs[i];if(b.e&&Math.abs(b.x-sX)<b.r){b.s();}}}function m(e){X=e.clientX-8;}function st(){bs=[new B(6,50,50,4,0)];iI=setInterval(tS,25);}cv.onclick=cl;cv.onmousemove=m;st();
dmFyIGN2PWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJjIiksYz1jdi5nZXRDb250ZXh0KCcyZCcpLGJzPW5ldyBBcnJheSgpLFg9LTEscz0wLHNYPS0xLGlJLGY9NTAwO2N2LndpZHRoPWY7Y3YuaGVpZ2h0PWY7ZnVuY3Rpb24gQihpLGosayxsLG0pe3ZhciB0PXRoaXM7dC5lPTE7dC5sPWk7dC5yPTEwKnQubDt0Lng9ajt0Lnk9azt0Lmk9bDt0Lmo9bTt0LmQ9ZnVuY3Rpb24oKXtjLmJlZ2luUGF0aCgpO2MuYXJjKHQueCx0LnksdC5yLDAsNi4zLDEpO2MuZmlsbCgpO307dC5zPWZ1bmN0aW9uKCl7dC5lPTA7aWYodC5sPjEpe2JzLnB1c2gobmV3IEIodC5sLTEsdC54LHQueSx0LmksLTYpKTticy5wdXNoKG5ldyBCKHQubC0xLHQueCx0LnksLXQuaSwtNikpO319O307ZnVuY3Rpb24gdFMoKXt2YXIgYT0wO2MuY2xlYXJSZWN0KDAsMCxmLGYpO2MuZmlsbFJlY3QoMCw0MDAsZiwxMDApO2ZvcihpIGluIGJzKXt2YXIgYj1ic1tpXSx4PWIueCx5PWIueSxyPWIucjtpZihiLmUpe2lmKHk+NDAwLXIpe2IueT00MDAtcjtiLmoqPS0xO31pZih4PmYtcil7Yi54PWYtcjtiLmkqPS0xO31pZih4PHIpe2IueD1yO2IuaSo9LTE7fWIuais9MC4yNTtiLngrPWIuaTtiLnkrPWIuajtiLmQoKTtpZigoWC14KSooWC14KSsoMzkwLXkpKigzOTAteSk8KHIrMTMpKihyKzEzKSl7YT0xO319fWMuZmlsbFJlY3QoWC0xMCwzODAsMjAsMjApO2lmKHMpe3MtLTtjLmJlZ2luUGF0aCgpO2MubW92ZVRvKFgsMCk7Yy5saW5lVG8oWCwzODApO2Muc3Ryb2tlKCk7fWlmKGEpe2NsZWFySW50ZXJ2YWwoaUkpO3NldFRpbWVvdXQoc3QsMjAwMCk7fX1mdW5jdGlvbiBjbCgpe3M9MjtzWD1YO2ZvcihpIGluIGJzKXt2YXIgYj1ic1tpXTtpZihiLmUmJk1hdGguYWJzKGIueC1zWCk8Yi5yKXtiLnMoKTt9fX1mdW5jdGlvbiBtKGUpe1g9ZS5jbGllbnRYLTg7fWZ1bmN0aW9uIHN0KCl7YnM9W25ldyBCKDYsNTAsNTAsNCwwKV07aUk9c2V0SW50ZXJ2YWwodFMsMjUpO31jdi5vbmNsaWNrPWNsO2N2Lm9ubW91c2Vtb3ZlPW07c3QoKTs=
var cv = document.getElementById("c");
cv.width = 500;
cv.height = 500;
var c = cv.getContext('2d');
var balls = new Array();
var mouseX = -1,
shot = 0,
shotX = -1,
intervalId;
function Ball(newLevel, newX, newY, newSpeedX, newSpeedY) {
var t = this;
t.enabled = 1;
t.level = newLevel;
t.radius = 10*t.level;
t.x = newX;
t.y = newY;
t.speedX = newSpeedX;
t.speedY = newSpeedY;
t.draw = function() {
c.beginPath();
c.arc(t.x,t.y,t.radius,0,6.3,1);
c.fill();
};
t.split = function() {
t.enabled = 0;
if(t.level > 1){
balls.push(new Ball(t.level-1,t.x,t.y,t.speedX,-6));
balls.push(new Ball(t.level-1,t.x,t.y,-t.speedX,-6));
}
};
};
function timeStep() {
var stop = 0;
c.clearRect(0,0,500,500);
c.fillRect(0,400,500,100);
var i;
for(i in balls) {
var ball = balls[i];
if(ball.enabled) {
if(ball.y > 400 - ball.radius) {
ball.y = 400 - ball.radius; // needed for the balls to keep going... (not perfect though)
ball.speedY *= -1;
}
if(ball.x > 500 - ball.radius) {
ball.x = 500 - ball.radius; // idem
ball.speedX *= -1;
}
if(ball.x < ball.radius) {
ball.x = ball.radius; // idem
ball.speedX *= -1;
}
ball.speedY += 0.25;
ball.x += ball.speedX;
ball.y += ball.speedY;
ball.draw();
if((mouseX - ball.x)*(mouseX - ball.x) + (390 - ball.y)*(390 - ball.y) < (ball.radius + 13)*(ball.radius + 13)) {
stop = 1;
}
}
}
c.fillRect(mouseX-10,380,20,20);
if(shot) {
shot--;
c.beginPath();
c.moveTo(mouseX,0);
c.lineTo(mouseX,380);
c.stroke();
}
if(stop) {
clearInterval(intervalId);
setTimeout(start,3000);
}
}
function clicked() {
shot = 1;
shotX = mouseX;
var i;
for(i in balls) {
var ball = balls[i];
if(ball.enabled && Math.abs(ball.x - shotX) < ball.radius) {
ball.split();
}
}
}
function mousemove(e) {
mouseX = e.clientX-8;
}
function start() {
balls = [new Ball(6,50,50,4,0)];
intervalId = setInterval(timeStep,25);
}
cv.onclick = clicked;
cv.onmousemove = mousemove;
start();