Site Search:

BlockBuster Game source code

you need to replace the .png urls, otherwise, your page will have image placeholders.

<style>
html
{
  -webkit-user-select: none;
}

body{
  margin:0;
}

#icon{
  float:left;
  margin:5px;
}

#titleBar{
  -webkit-app-region: drag;
  background-image:url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgP1fygCzk29l2Gdu2gd9UJwq8HMZrThQcFwwjLoiKsmePjkpY6e7T_LZdxCqQtkR-pZkjr7uyIPB1d1YHoJqMj25kBAXLt79uMyiI816d943jqXG7EtqZsD04BC8L2Ind3q1x9ONXYdVSH/s1600/menu.png);
  width:800px;
  height:30px;
}

#minimizeButton{
  float:left;
}

#closeButton{
  float:right;
}

#titleBarButtons{
    display:inline;
    float:right;
    -webkit-app-region: no-drag;
}
</style>


<canvas id="canvas" width="800" height="440"></canvas>
  <div id="titleBar">
   <img id="icon" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0nur3YD9KNtIG7WUAPYYpcnGB_iXsRcNojBTLUyz9omgDGE7HyUuFQ5qdpSIbmgZ0qtnyoMlXBw4wi9h4hKTVCfs-Dxxi4ntz8cwiHXxV4s6I1WBhRKXRi76bWLQycFnf1UsgVloEplJO/s1600/icon.png"></img>
   <div id="titleBarButtons">
    <img id="minimizeButton" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXMcRM1oGuZpu1FXXIl_5OpDn2YhPDt55zR_N-nCWKYtJHw-HpdlKH3w0aHKwDPu8edhx9biWjrIcK_hJOCxzvZvTrcyj-_ZrVLkQ6_mNXISh06-iuCqekFoG8pDpSR7NwtZslgSM_On70/s1600/minimize.png"></img>
    <img id="closeButton" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjElPKVqQlPRYQA1SCysdBPX2u8wokNJivtLjN8oKAf6lXkY7366Cp2h7N8KN6Wu0948jSD_YIoQlgMp-RpL1ncqEGom0Nx_QJY54x_ZVgytVopUHg039g6ZCxg5SL4zXhpLm-eZG-f5TpF/s1600/close.png"></img>
   </div>
  </div>

<script>
// based on https://github.com/Deftwun/BlockBlaster
//license: https://opensource.org/licenses/MIT
//Create canvas
// document.body.innerHTML += '<canvas id="canvas" width="800" height="600"></canvas>';

 //Globals Variables
 //-----------------
 var fps = 30;
 var canvas = document.getElementById('canvas');
 var ctx = canvas.getContext("2d");
 var bgColor = "rgb(40,40,40)"
 var ready;
 var enemyScore;
 var renderTimer = setInterval(render,1/fps*100);
 var difficultyTimer;
 var spawnTimer;
 var spawntime;
 var gameTime;
 var difficulty;
 var score;
 var highScore=0;
 var gameOver;
 var entities = [];
 var entitiesToRemove = []
 var player;
 var fader;
 var tripleShotActive = false;
 var tripleShotTimer;
 var flash = false;
 var bonusPointsMessage = false;
 var tripleShotMessage = false;



 //Global Functions
 //----------------

 //Reset app back to 'Ready?' Screen
 function reset(){
  if (score > highScore) highScore = score;
  ready = true;
  enemyScore = 0;
  gameTime = 0;
  difficulty = 1;
  score = 0;
  spawntime = 1500;
  gameOver = false;
  fader = 0;
  entities = [];
  entitiesToRemove = [];
  player = null;
  tripleShotActive = false;
  flash = false;
  clearTimers();
 }

 //Clear all timers
 function clearTimers(){
  clearInterval(difficultyTimer);
  clearInterval(spawnTimer);
  clearInterval(tripleShotTimer);
 }

 //Initialize all timers
 function initializeTimers(){
  difficultyTimer = setInterval(increaseDifficulty,2000);
  spawnTimer = setInterval(spawnEnemy,spawntime);
 }

 //Initialize / Start game
 function init(){
  ready = false;
  clearTimers();
  initializeTimers();

  //Spawn player
  player = new Player();
  player.position.set(canvas.width/2,canvas.height-player.size);
  player.render();
  entities.push(player);

 }

 //Update Entities
 function updateEntities(){
  entities.forEach(function(e){
   if (e.position.y > canvas.height + 20){
    if (e.name == "Enemy"){
     enemyScore += 1;
    }
    removeEntity(e);
   }
   e.update(1/fps);
  })
 }

 //Draw background
 function drawBG(){
  ctx.fillStyle = bgColor;
  ctx.fillRect(0,0,canvas.width,canvas.height);
 }

 //Draw Score / HUD
 function drawScore(){
  ctx.fillStyle = "#CCFF99";
  ctx.font = "24px sans-serif";
  ctx.fillText("Score: " + score,10,24);
  ctx.font = "16px sans-serif";
  ctx.fillText("High Score: " + highScore,10,48);
  var enemyScoreString = "";
  for (var i = 0; i < enemyScore; i++){
   enemyScoreString += "X";
  }
  ctx.font = "24px sans-serif";
  ctx.fillStyle = "#FF6666";
  ctx.fillText(enemyScoreString,canvas.width - 75,24);
  ctx.font = "16px sans-serif";
  ctx.fillText("Difficulty: " + difficulty,canvas.width/2 - 50,24);
 }

 //Draws some static.
 //@param alpha transparency
 function drawStatic(alpha){
  var s = 15 ;
  for (var x = 0; x < canvas.width; x+=s){
   for (var y = 0; y < canvas.width; y+=s){
    var n = Math.floor(Math.random() * 60);
    ctx.fillStyle = "rgba(" + n + "," + n + "," + n + "," + (Math.random() * alpha) + ")";
    ctx.fillRect(x,y,s,s);
   }
  }
 }

 //Draws 'Ready?' screen
 function drawReadyScreen(){
  drawBG();
  //drawStatic(.25);
  drawScore();
  fader += .1 * 1/fps;
  ctx.fillStyle = "rgba(255,255,255," + fader + ")";
  ctx.font = "72px sans-serif";
  ctx.fillText("READY?",canvas.width/2 - 140,canvas.height/2);
  drawScore();
 }

 //Draw all entities
 function drawEntities(){
  entities.forEach(function(e){e.render();});
 }

 //Draw 'Game Over' screen
 function drawGameOver(){
  ctx.fillStyle = "rgba(0,0,0,"+fader +")";
  ctx.fillRect(0,0,canvas.width,canvas.height);
  drawStatic(fader/2);
  drawScore();
  fader += .1 * 1/fps
  ctx.fillStyle = "rgba(255,255,255," + fader + ")";
  ctx.font = "72px sans-serif";
  ctx.fillText("GAME OVER",canvas.width/2 - 220,canvas.height/2);
 }

 //Render everything
 function render(){
  drawBG();
  drawEntities();
  drawScore();
  if (flash){drawFlash();}
  if (bonusPointsMessage){drawBonusPointsMessage();}
  if (tripleShotMessage){drawTripleShotMessage();}
  if (gameOver){drawGameOver(); return;}
  else if (ready){drawReadyScreen(); return;}

  updateEntities();
  entitiesToRemove.forEach(function(e){
   var idx = entities.indexOf(e);
   if (idx > -1) entities.splice(idx,1);
  })
  gameTime += 1/fps;
  if (enemyScore >= 3) {
   clearTimers();
   gameOver = true;
   fader = 0;
  }
 }

 //Return mouse position relative to canvas
 function getMousePos(canvas, evt) {
  var rect = canvas.getBoundingClientRect();
  return new Vector2(evt.clientX - rect.left,
       evt.clientY - rect.top)
 }

 //Click Event
 function canvasClick(){
  if (gameOver){ if (fader > .5) reset();return;}
  if (ready)  {init(); return;}

  //Fire Bullets
  fireBullet({x:0,y:-player.size},30);
  if (tripleShotActive){
   fireBullet({x:-player.size,y:-player.size},25);
   fireBullet({x:player.size,y:-player.size},25);
  }
  if (score > 0) score -= 1;
 }

 //Fire bullet from player
 function fireBullet(offset,speed){
  var bullet = new Bullet();
  bullet.position.set(player.position.x + player.size/2 - bullet.size/2 + offset.x,
            player.position.y + player.size/2 - bullet.size/2 + offset.y);
  bullet.velocity.y = -speed;
  entities.push(bullet);
 }

 //Screen Flash
 function drawFlash(){
  fader -= (.1 * 1/fps);
  ctx.fillStyle = "rgba(255,255,255," + fader + ")";
  ctx.fillRect(0,0,canvas.width,canvas.height)
  if (fader <= 0) {
   flash = false;
  }
 }

 //Draw Bonus points message
 function drawBonusPointsMessage(){
  fader -= (.1 * 1/fps);
  ctx.fillStyle = "rgba(255,255,255," + fader + ")";
  ctx.font = "72px sans-serif";
  ctx.fillText("+250 POINTS!",canvas.width/2 - 220,canvas.height/2);
  if (fader <= 0) {
   bonusPointsMessage = false;
  }
 }

 //Draw Triple shot message
 function drawTripleShotMessage(){
  fader -= (.1 * 1/fps);
  ctx.fillStyle = "rgba(255,255,255," + fader + ")";
  ctx.font = "72px sans-serif";
  ctx.fillText("TRIPLE SHOT!",canvas.width/2 - 220,canvas.height/2);
  if (fader <= 0) {
   tripleShotMessage = false;
  }
 }

 //Activate power up effect
 function activateEffect(type){
  if (type == "scoreBoost"){
   console.log("+250");
   fader = 1;
   bonusPointsMessage=true;
   score += 250;
  }
  else if (type == "tripleShot"){
   console.log("TRIPLE SHOT");
   fader = 1;
   tripleShotActive = true;
   tripleShotMessage = true;
   tripleShotTimer = setInterval(function(){
    tripleShotActive=false;
    clearInterval(tripleShotTimer);
   },10000);
  }
  else if (type == "bomb"){
   console.log("BOMB");
   flash = true;
   fader = 1;
   entities.forEach(function(e){
    if (e.name == "Enemy"){
     death(e);
    }
   })
  }
 }

 //Increment difficulty
 function increaseDifficulty(){
  difficulty += 1;
  if (spawntime > 20) spawntime -= 20;
  if (difficulty % 5 == 0 && Math.random() > .5) spawnPowerUp();
  clearInterval(spawnTimer);
  spawnTimer = setInterval(spawnEnemy,spawntime);
 }

 //Change alpha of color
 function setAlpha(color,alpha){
  if (color.indexOf('a') == -1){
   return color.replace(")",","+alpha+")").replace("rgb","rgba");
  }
 }



 //Entity death
 function death(entity){
  if (entity.name == "Enemy") {
   var particleCount = Math.floor((Math.random() * 6) + 3);
   for (var i = 0; i < particleCount; i++){
    var p = new Particle();
    p.color = entity.color;
    p.size = Math.floor((Math.random() * entity.size/2) + 5);
    //p.position.set(entity.position.x+entity.size/2,entity.position.y+entity.size/2);
    var modx = (Math.random() * entity.size/2);
    var mody = (Math.random() * entity.size/2);
    p.position.x = entity.position.x + modx;
    p.position.y = entity.position.y + mody;
    entities.push(p);
   }
   score += 25;
  }
  else if (entity.name == "PowerUp"){
   var particleCount = Math.floor((Math.random() * 6) + 3);
   for (var i = 0; i < particleCount; i++){
    var p = new Particle();
    p.color = randomColor(100,255); //Rainbow colored particles
    p.size = Math.floor((Math.random() * entity.size/2) + 5);
    //p.position.set(entity.position.x+entity.size/2,entity.position.y+entity.size/2);
    var modx = (Math.random() * entity.size/2);
    var mody = (Math.random() * entity.size/2);
    p.position.x = entity.position.x + modx;
    p.position.y = entity.position.y + mody;
    entities.push(p);
   }
   activateEffect(entity.effect);
  }

  removeEntity(entity);
 }

 //Remove Entity
 function removeEntity(entity){
  entitiesToRemove.push(entity);
  /*
  var idx = entities.indexOf(entity);
  if (idx > -1) entities.splice(idx,1);
  */
 }

 //Check if two entities overlap
 function overlaps(entityA,entityB){

  var sa = entityA.size;
  var x1a = entityA.position.x;
  var x2a = entityA.position.x + sa;
  var y1a = entityA.position.y;
  var y2a = entityA.position.y + sa;
  var sb = entityB.size;
  var x1b = entityB.position.x;
  var x2b = entityB.position.x + sb;
  var y1b = entityB.position.y;
  var y2b = entityB.position.y + sb;

  return (x1a < x2b && x2a > x1b && y1a < y2b && y2a > y1b);
 }

 //Spawns new powerup
 function spawnPowerUp(){
  var e = new PowerUp();
  var px = Math.floor((Math.random() * canvas.width));
  var py = -e.size;
  var v = (Math.random() * difficulty) + difficulty / 2;
  var a = Math.floor((Math.random() * (v + 15)) + v) / 2;
  var f = Math.floor((Math.random() * (v + 15)) + v) / 2;
  e.position.set(px,py);
  var r = Math.random();
  if (r > .5){
   straightDownMotion(e,v);
  }
  else if (r > .3){
   sineMotion(e,a,f,v);
  }
  else if (r > .1){
   triangularMotion(e,a,f,v);
  }
  else{
   sawtoothMotion(e,a,f,v);
  }
  entities.push(e);
 }

 //Spawns new enemy
 function spawnEnemy(){
  var e = new Enemy();
  var px = Math.floor((Math.random() * canvas.width));
  var py = -e.size;
  //var v = difficulty;
  var v = (Math.random() * difficulty) + difficulty / 2;
  var a = Math.floor((Math.random() * (v + 15)) + v);
  var f = Math.floor((Math.random() * (v + 15)) + v);
  e.position.set(px,py);
  var r = Math.random();
  if (r > .5){
   straightDownMotion(e,v);
  }
  else if (r > .3){
   sineMotion(e,a,f,v);
  }
  else if (r > .1){
   triangularMotion(e,a,f,v);
  }
  else{
   sawtoothMotion(e,a,f,v);
  }
  entities.push(e);
 }

 //Straight down motion
 function straightDownMotion(entity,speed){
  entity.update = function(deltatime){
   this.velocity.x = 0;
   this.velocity.y = speed;
   Entity.prototype.update.call(this,deltatime);
  }
 }

 //Define sin wave motion
 function sineMotion(entity,amplitude,freq,speed){
  entity.update = function(deltatime){
   this.velocity.x = amplitude * Math.cos(this.position.y/freq);
   this.velocity.y = speed;
   Entity.prototype.update.call(this,deltatime);
  }
 }

 //Define saw tooth motion
 function sawtoothMotion(entity, amplitude,freq,speed){
  var modifier = 1;
  if (Math.random() > .5) modifier = -1;
  entity.update = function(deltatime){
   this.velocity.x = modifier * ((-2*amplitude)/Math.PI)*Math.atan(1/Math.tan(this.position.y / freq));
   this.velocity.y = speed;
   Entity.prototype.update.call(this,deltatime);
  }
 }

 //Define triangular motion (sorta. More of a sine wave in the end really)
 function triangularMotion(entity, amplitude,freq,speed){
  entity.update = function(deltatime){
   this.velocity.x = ((2*amplitude)/Math.PI)*Math.asin(Math.sin(this.position.y / freq));
   this.velocity.y = speed;
   Entity.prototype.update.call(this,deltatime);
  }
 }

 //Generate random rgba color string
 function randomColor(min,max){
  var r = Math.floor((Math.random() * max) + min);
  var g = Math.floor((Math.random() * max) + min);
  var b = Math.floor((Math.random() * max) + min);
  var col = "rgb(" + r + "," + g + "," + b + ")";
  return col;
 }

 // Classes
 //----------

 //Vector2
 var Vector2 = function(x1,y1){
  this.x = x1;
  this.y = y1;
 }
 Vector2.prototype.set = function(a,b){
  this.x = a;
  this.y = b;
 }

 //Entity (Base class)
 var Entity = function(){
  this.name = "Entity";
  this.size = 25;
  this.position = new Vector2(0,0);
  this.velocity = new Vector2(0,0);
  this.color = "#FFFFFF";
 }
 Entity.prototype.sayName = function(){
  console.log(this.name);
 }
 Entity.prototype.update = function(deltaTime){
  this.position.x += this.velocity.x * deltaTime;
  this.position.y += this.velocity.y * deltaTime;
  //Keep in bounds
  if (this.position.x < 0) {this.position.x = this.size;}
  if (this.position.x + this.size > canvas.width) {this.position.x = canvas.width - this.size;}
 }
 Entity.prototype.render = function(){
  ctx.fillStyle = this.color;
  ctx.fillRect(this.position.x,this.position.y,this.size,this.size);
 }

 //Enemy Entity
 var Enemy = function(){
  Entity.call(this);
  this.name = "Enemy";
  this.size = Math.floor((Math.random() * 50)+20);
  this.color = randomColor(90,150);
 }
 Enemy.prototype = Object.create(Entity.prototype);
 Enemy.prototype.constructor = Entity;
 //Player Entity
 var Player = function(){
  Entity.call(this);
  this.name = "Player";
  this.color = "#4747FF"
 }
 Player.prototype = Object.create(Entity.prototype);
 Player.prototype.constructor = Entity;

 //Particle Entity
 var Particle = function(){
  Entity.call(this);
  this.name = "Particle";
  this.size = 10;
  this.time = 0;
  this.maxTime = Math.floor((Math.random() * 10) + 3);
  this.velocity.x = Math.floor((Math.random() * 20) - 10);
  this.velocity.y = Math.floor((Math.random() * 20) - 10);
 }
 Particle.prototype = Object.create(Entity.prototype);
 Particle.prototype.constructor = Entity;
 Particle.prototype.update = function(deltatime){
  Entity.prototype.update.call(this,deltatime);
  this.time += deltatime;
  if (this.time >= this.maxTime) removeEntity(this);
 }

 //Bullet Entity
 var Bullet = function(){
  Entity.call(this);
  this.name = "Bullet";
  this.size = 10;
  this.time = 0;
  this.color = "rgba(200,200,200,1)";
  this.particlesDelay = .7;
 }
 Bullet.prototype = Object.create(Entity.prototype);
 Bullet.prototype.constructor = Entity;
 Bullet.prototype.update = function(deltatime){
  Entity.prototype.update.call(this,deltatime);

  //Check for collisions
  var me = this;
  entities.forEach(function(e){
   if (e !== me && e.name != "Particle"){
    if (overlaps(me,e)){
     death(e);
     removeEntity(me);
    }
   }
  })
  //Remove from game if outside bounds
  if (this.position.y < 0) removeEntity(this);

  //Create particles
  this.time += deltatime;
  if (this.time >= this.particlesDelay){
   this.time = 0;
   var p = new Particle();
   p.size = Math.floor((Math.random() * 5)+2);
   p.color = setAlpha("rgb(125,125,125)",Math.random());
   //p.color = setAlpha(randomColor(100,255),Math.random()); //Rainbow colored particles
   p.velocity.x /=2;
   p.position.x = this.position.x + this.size /2 - p.size/2;
   p.position.y = this.position.y - p.size/2;
   entities.push(p);
  }
 }

 //PowerUp Entity
 var PowerUp = function(){
  Entity.call(this);
  this.name = "PowerUp";
  this.size = 20;
  this.time = 0;
  this.particlesDelay = .25;
  var r = Math.random();
  if (r < .5){this.effect = "scoreBoost";}
  else if (r < .75){this.effect = "tripleShot";}
  else {this.effect = "bomb";}

 }
 PowerUp.prototype = Object.create(Entity.prototype);
 PowerUp.prototype.constructor = Entity;
 PowerUp.prototype.update = function(deltatime){
  Entity.prototype.update.call(this,deltatime);

  //Remove from game if outside bounds
  if (this.position.y < 0 || this.position.y+this.size > canvas.height) removeEntity(this);

  //Create particles
  this.time += deltatime;
  if (this.time >= this.particlesDelay){
   this.time = 0;
   var p = new Particle();
   p.size = Math.floor((Math.random() * 5)+2);
   p.color = setAlpha(randomColor(100,255),Math.random()); //Rainbow colored particles
   p.velocity.x /=2;
   p.position.x = this.position.x + this.size /2 - p.size/2;
   p.position.y = this.position.y - p.size/2;
   entities.push(p);
  }
 }
 PowerUp.prototype.render = function(){
   ctx.fillStyle = randomColor(100,255);
   ctx.fillRect(this.position.x,this.position.y,this.size,this.size);
 }


 // These must remain at the bottom of this file & in this order //
 // ============================================================ //

 //HTML load event
 document.addEventListener('DOMContentLoaded', reset());

 //Close
 document.getElementById("closeButton").onclick=function(){
  self.close()
 }
 //Minimize
 document.getElementById("minimizeButton").onclick=function(){
  minimize();
 }

 canvas.addEventListener("click",canvasClick);

 //Mouse move event
 canvas.addEventListener('mousemove', function(evt) {
   var mousePos = getMousePos(canvas, evt);
   if (player && !gameOver) player.position.x = mousePos.x;
 }, false);
</script>