Difference between revisions of "Team:Vilnius-Lithuania/HP/PheLossGame"

Line 14: Line 14:
 
     <canvas id='game' width='320' height='480'></canvas>
 
     <canvas id='game' width='320' height='480'></canvas>
 
   </div>
 
   </div>
   <script src='https://2016.igem.org/wiki/index.php?title=Team:Vilnius-Lithuania/HP/PheLossGame/engine.js'></script>
+
   <script >
   <script src='https://2016.igem.org/wiki/index.php?title=Team:Vilnius-Lithuania/HP/PheLossGame/game.js'></script>
+
(function() {
 +
    var lastTime = 0;
 +
    var vendors = ['ms', 'moz', 'webkit', 'o'];
 +
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
 +
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
 +
        window.cancelAnimationFrame =
 +
          window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
 +
    }
 +
 +
    if (!window.requestAnimationFrame)
 +
        window.requestAnimationFrame = function(callback, element) {
 +
            var currTime = new Date().getTime();
 +
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
 +
            var id = window.setTimeout(function() { callback(currTime + timeToCall); },
 +
              timeToCall);
 +
            lastTime = currTime + timeToCall;
 +
            return id;
 +
        };
 +
 +
    if (!window.cancelAnimationFrame)
 +
        window.cancelAnimationFrame = function(id) {
 +
            clearTimeout(id);
 +
        };
 +
}());
 +
 
 +
 
 +
var Game = new function() {                                                                 
 +
  var boards = [];
 +
 
 +
  // Game Initialization
 +
  this.initialize = function(canvasElementId,sprite_data,callback) {
 +
    this.canvas = document.getElementById(canvasElementId);
 +
 
 +
    this.playerOffset = 10;
 +
    this.canvasMultiplier= 1;
 +
    this.setupMobile();
 +
 
 +
    this.width = this.canvas.width;
 +
    this.height= this.canvas.height;
 +
 
 +
    this.ctx = this.canvas.getContext && this.canvas.getContext('2d');
 +
    if(!this.ctx) { return alert("Please upgrade your browser to play"); }
 +
 
 +
    this.setupInput();
 +
 
 +
    this.loop();
 +
 
 +
    if(this.mobile) {
 +
      this.setBoard(4,new TouchControls());
 +
    }
 +
 
 +
    SpriteSheet.load(sprite_data,callback);
 +
  };
 +
 
 +
 
 +
  // Handle Input
 +
  var KEY_CODES = { 37:'left', 39:'right', 32 :'fire' };
 +
  this.keys = {};
 +
 
 +
  this.setupInput = function() {
 +
    window.addEventListener('keydown',function(e) {
 +
      if(KEY_CODES[e.keyCode]) {
 +
      Game.keys[KEY_CODES[e.keyCode]] = true;
 +
      e.preventDefault();
 +
      }
 +
    },false);
 +
 
 +
    window.addEventListener('keyup',function(e) {
 +
      if(KEY_CODES[e.keyCode]) {
 +
      Game.keys[KEY_CODES[e.keyCode]] = false;
 +
      e.preventDefault();
 +
      }
 +
    },false);
 +
  };
 +
 
 +
 
 +
  var lastTime = new Date().getTime();
 +
  var maxTime = 1/30;
 +
  // Game Loop
 +
  this.loop = function() {
 +
    var curTime = new Date().getTime();
 +
    requestAnimationFrame(Game.loop);
 +
    var dt = (curTime - lastTime)/1000;
 +
    if(dt > maxTime) { dt = maxTime; }
 +
 
 +
    for(var i=0,len = boards.length;i<len;i++) {
 +
      if(boards[i]) {
 +
        boards[i].step(dt);
 +
        boards[i].draw(Game.ctx);
 +
      }
 +
    }
 +
    lastTime = curTime;
 +
  };
 +
 
 +
  // Change an active game board
 +
  this.setBoard = function(num,board) { boards[num] = board; };
 +
 
 +
 
 +
  this.setupMobile = function() {
 +
    var container = document.getElementById("container"),
 +
        hasTouch =  !!('ontouchstart' in window),
 +
        w = window.innerWidth, h = window.innerHeight;
 +
     
 +
    if(hasTouch) { this.mobile = true; }
 +
 
 +
    if(screen.width >= 1280 || !hasTouch) { return false; }
 +
 
 +
    if(w > h) {
 +
      alert("Please rotate the device and then click OK");
 +
      w = window.innerWidth; h = window.innerHeight;
 +
    }
 +
 
 +
    container.style.height = h*2 + "px";
 +
    window.scrollTo(0,1);
 +
 
 +
    h = window.innerHeight + 2;
 +
    container.style.height = h + "px";
 +
    container.style.width = w + "px";
 +
    container.style.padding = 0;
 +
 
 +
    if(h >= this.canvas.height * 1.75 || w >= this.canvas.height * 1.75) {
 +
      this.canvasMultiplier = 2;
 +
      this.canvas.width = w / 2;
 +
      this.canvas.height = h / 2;
 +
      this.canvas.style.width = w + "px";
 +
      this.canvas.style.height = h + "px";
 +
    } else {
 +
      this.canvas.width = w;
 +
      this.canvas.height = h;
 +
    }
 +
 
 +
    this.canvas.style.position='absolute';
 +
    this.canvas.style.left="0px";
 +
    this.canvas.style.top="0px";
 +
 
 +
  };
 +
 
 +
};
 +
 
 +
 
 +
var SpriteSheet = new function() {
 +
  this.map = { };
 +
 
 +
  this.load = function(spriteData,callback) {
 +
    this.map = spriteData;
 +
    this.image = new Image();
 +
    this.image.onload = callback;
 +
    this.image.src = 'sprites.png';
 +
  };
 +
 
 +
  this.draw = function(ctx,sprite,x,y,frame) {
 +
    var s = this.map[sprite];
 +
    if(!frame) frame = 0;
 +
    ctx.drawImage(this.image,
 +
                    s.sx + frame * s.w,
 +
                    s.sy,
 +
                    s.w, s.h,
 +
                    Math.floor(x), Math.floor(y),
 +
                    s.w, s.h);
 +
  };
 +
 
 +
  return this;
 +
};
 +
 
 +
var TitleScreen = function TitleScreen(title,subtitle,callback) {
 +
  var up = false;
 +
  this.step = function(dt) {
 +
    if(!Game.keys['fire']) up = true;
 +
    if(up && Game.keys['fire'] && callback) callback();
 +
  };
 +
 
 +
  this.draw = function(ctx) {
 +
    ctx.fillStyle = "#FFFFFF";
 +
 
 +
    ctx.font = "bold 40px bangers";
 +
    var measure = ctx.measureText(title); 
 +
    ctx.fillText(title,Game.width/2 - measure.width/2,Game.height/2);
 +
 
 +
    ctx.font = "bold 20px bangers";
 +
    var measure2 = ctx.measureText(subtitle);
 +
    ctx.fillText(subtitle,Game.width/2 - measure2.width/2,Game.height/2 + 40);
 +
  };
 +
};
 +
 
 +
 
 +
var GameBoard = function() {
 +
  var board = this;
 +
 
 +
  // The current list of objects
 +
  this.objects = [];
 +
  this.cnt = {};
 +
 
 +
  // Add a new object to the object list
 +
  this.add = function(obj) {
 +
    obj.board=this;
 +
    this.objects.push(obj);
 +
    this.cnt[obj.type] = (this.cnt[obj.type] || 0) + 1;
 +
    return obj;
 +
  };
 +
 
 +
  // Mark an object for removal
 +
  this.remove = function(obj) {
 +
    var idx = this.removed.indexOf(obj);
 +
    if(idx == -1) {
 +
      this.removed.push(obj);
 +
      return true;
 +
    } else {
 +
      return false;
 +
    }
 +
  };
 +
 
 +
  // Reset the list of removed objects
 +
  this.resetRemoved = function() { this.removed = []; };
 +
 
 +
  // Removed an objects marked for removal from the list
 +
  this.finalizeRemoved = function() {
 +
    for(var i=0,len=this.removed.length;i<len;i++) {
 +
      var idx = this.objects.indexOf(this.removed[i]);
 +
      if(idx != -1) {
 +
        this.cnt[this.removed[i].type]--;
 +
        this.objects.splice(idx,1);
 +
      }
 +
    }
 +
  };
 +
 
 +
  // Call the same method on all current objects
 +
  this.iterate = function(funcName) {
 +
    var args = Array.prototype.slice.call(arguments,1);
 +
    for(var i=0,len=this.objects.length;i<len;i++) {
 +
      var obj = this.objects[i];
 +
      obj[funcName].apply(obj,args);
 +
    }
 +
  };
 +
 
 +
  // Find the first object for which func is true
 +
  this.detect = function(func) {
 +
    for(var i = 0,val=null, len=this.objects.length; i < len; i++) {
 +
      if(func.call(this.objects[i])) return this.objects[i];
 +
    }
 +
    return false;
 +
  };
 +
 
 +
  // Call step on all objects and them delete
 +
  // any object that have been marked for removal
 +
  this.step = function(dt) {
 +
    this.resetRemoved();
 +
    this.iterate('step',dt);
 +
    this.finalizeRemoved();
 +
  };
 +
 
 +
  // Draw all the objects
 +
  this.draw= function(ctx) {
 +
    this.iterate('draw',ctx);
 +
  };
 +
 
 +
  // Check for a collision between the
 +
  // bounding rects of two objects
 +
  this.overlap = function(o1,o2) {
 +
    return !((o1.y+o1.h-1<o2.y) || (o1.y>o2.y+o2.h-1) ||
 +
            (o1.x+o1.w-1<o2.x) || (o1.x>o2.x+o2.w-1));
 +
  };
 +
 
 +
  // Find the first object that collides with obj
 +
  // match against an optional type
 +
  this.collide = function(obj,type) {
 +
    return this.detect(function() {
 +
      if(obj != this) {
 +
      var col = (!type || this.type & type) && board.overlap(obj,this);
 +
      return col ? this : false;
 +
      }
 +
    });
 +
  };
 +
 
 +
 
 +
};
 +
 
 +
var Sprite = function() { };
 +
 
 +
Sprite.prototype.setup = function(sprite,props) {
 +
  this.sprite = sprite;
 +
  this.merge(props);
 +
  this.frame = this.frame || 0;
 +
  this.w =  SpriteSheet.map[sprite].w;
 +
  this.h =  SpriteSheet.map[sprite].h;
 +
};
 +
 
 +
Sprite.prototype.merge = function(props) {
 +
  if(props) {
 +
    for (var prop in props) {
 +
      this[prop] = props[prop];
 +
    }
 +
  }
 +
};
 +
 
 +
Sprite.prototype.draw = function(ctx) {
 +
  SpriteSheet.draw(ctx,this.sprite,this.x,this.y,this.frame);
 +
};
 +
 
 +
Sprite.prototype.hit = function(damage) {
 +
  this.board.remove(this);
 +
};
 +
 
 +
 
 +
var Level = function(levelData,callback) {
 +
  this.levelData = [];
 +
  for(var i =0; i<levelData.length; i++) {
 +
    this.levelData.push(Object.create(levelData[i]));
 +
  }
 +
  this.t = 0;
 +
  this.callback = callback;
 +
};
 +
 
 +
Level.prototype.step = function(dt) {
 +
  var idx = 0, remove = [], curShip = null;
 +
 
 +
  // Update the current time offset
 +
  this.t += dt * 1000;
 +
 
 +
  //  Start, End,  Gap, Type,  Override
 +
  // [ 0,    4000, 500, 'step', { x: 100 } ]
 +
  while((curShip = this.levelData[idx]) &&
 +
        (curShip[0] < this.t + 2000)) {
 +
    // Check if we've passed the end time
 +
    if(this.t > curShip[1]) {
 +
      remove.push(curShip);
 +
    } else if(curShip[0] < this.t) {
 +
      // Get the enemy definition blueprint
 +
      var enemy = enemies[curShip[3]],
 +
          override = curShip[4];
 +
 
 +
      // Add a new enemy with the blueprint and override
 +
      this.board.add(new Enemy(enemy,override));
 +
 
 +
      // Increment the start time by the gap
 +
      curShip[0] += curShip[2];
 +
    }
 +
    idx++;
 +
  }
 +
 
 +
  // Remove any objects from the levelData that have passed
 +
  for(var i=0,len=remove.length;i<len;i++) {
 +
    var remIdx = this.levelData.indexOf(remove[i]);
 +
    if(remIdx != -1) this.levelData.splice(remIdx,1);
 +
  }
 +
 
 +
  // If there are no more enemies on the board or in
 +
  // levelData, this level is done
 +
  if(this.levelData.length === 0 && this.board.cnt[OBJECT_ENEMY] === 0) {
 +
    if(this.callback) this.callback();
 +
  }
 +
 
 +
};
 +
 
 +
Level.prototype.draw = function(ctx) { };
 +
 
 +
 
 +
var TouchControls = function() {
 +
 
 +
  var gutterWidth = 10;
 +
  var unitWidth = Game.width/5;
 +
  var blockWidth = unitWidth-gutterWidth;
 +
 
 +
  this.drawSquare = function(ctx,x,y,txt,on) {
 +
    ctx.globalAlpha = on ? 0.9 : 0.6;
 +
    ctx.fillStyle =  "#CCC";
 +
    ctx.fillRect(x,y,blockWidth,blockWidth);
 +
 
 +
    ctx.fillStyle = "#FFF";
 +
    ctx.globalAlpha = 1.0;
 +
    ctx.font = "bold " + (3*unitWidth/4) + "px arial";
 +
 
 +
    var txtSize = ctx.measureText(txt);
 +
 
 +
    ctx.fillText(txt,
 +
                x+blockWidth/2-txtSize.width/2,
 +
                y+3*blockWidth/4+5);
 +
  };
 +
 
 +
  this.draw = function(ctx) {
 +
    ctx.save();
 +
 
 +
    var yLoc = Game.height - unitWidth;
 +
    this.drawSquare(ctx,gutterWidth,yLoc,"\u25C0", Game.keys['left']);
 +
    this.drawSquare(ctx,unitWidth + gutterWidth,yLoc,"\u25B6", Game.keys['right']);
 +
    this.drawSquare(ctx,4*unitWidth,yLoc,"A",Game.keys['fire']);
 +
 
 +
    ctx.restore();
 +
  };
 +
 
 +
  this.step = function(dt) { };
 +
 
 +
  this.trackTouch = function(e) {
 +
    var touch, x;
 +
 
 +
    e.preventDefault();
 +
    Game.keys['left'] = false;
 +
    Game.keys['right'] = false;
 +
    for(var i=0;i<e.targetTouches.length;i++) {
 +
      touch = e.targetTouches[i];
 +
      x = touch.pageX / Game.canvasMultiplier - Game.canvas.offsetLeft;
 +
      if(x < unitWidth) {
 +
        Game.keys['left'] = true;
 +
      }
 +
      if(x > unitWidth && x < 2*unitWidth) {
 +
        Game.keys['right'] = true;
 +
      }
 +
    }
 +
 
 +
    if(e.type == 'touchstart' || e.type == 'touchend') {
 +
      for(i=0;i<e.changedTouches.length;i++) {
 +
        touch = e.changedTouches[i];
 +
        x = touch.pageX / Game.canvasMultiplier - Game.canvas.offsetLeft;
 +
        if(x > 4 * unitWidth) {
 +
          Game.keys['fire'] = (e.type == 'touchstart');
 +
        }
 +
      }
 +
    }
 +
  };
 +
 
 +
  Game.canvas.addEventListener('touchstart',this.trackTouch,true);
 +
  Game.canvas.addEventListener('touchmove',this.trackTouch,true);
 +
  Game.canvas.addEventListener('touchend',this.trackTouch,true);
 +
 
 +
  // For Android
 +
  Game.canvas.addEventListener('dblclick',function(e) { e.preventDefault(); },true);
 +
  Game.canvas.addEventListener('click',function(e) { e.preventDefault(); },true);
 +
 
 +
  Game.playerOffset = unitWidth + 20;
 +
};
 +
 
 +
 
 +
var GamePoints = function() {
 +
  Game.points = 0;
 +
 
 +
  var pointsLength = 8;
 +
 
 +
  this.draw = function(ctx) {
 +
    ctx.save();
 +
    ctx.font = "bold 18px arial";
 +
    ctx.fillStyle= "#FFFFFF";
 +
 
 +
    var txt = "" + Game.points;
 +
    var i = pointsLength - txt.length, zeros = "";
 +
    while(i-- > 0) { zeros += "0"; }
 +
 
 +
    ctx.fillText(zeros + txt,10,20);
 +
    ctx.restore();
 +
 
 +
  };
 +
 
 +
  this.step = function(dt) { };
 +
};
 +
 
 +
</script>
 +
   <script'>
 +
var sprites = {
 +
ship: { sx: 0, sy: 0, w: 37, h: 42, frames: 1 },
 +
//missile: { sx: 0, sy: 30, w: 2, h: 10, frames: 1 },
 +
enemy_purple: { sx: 37, sy: 0, w: 42, h: 43, frames: 1 },
 +
enemy_bee: { sx: 79, sy: 0, w: 37, h: 43, frames: 1 },
 +
enemy_ship: { sx: 116, sy: 0, w: 42, h: 43, frames: 1 },
 +
enemy_circle: { sx: 158, sy: 0, w: 32, h: 33, frames: 1 },
 +
explosion: { sx: 0, sy: 64, w: 64, h: 64, frames: 12 }
 +
//enemy_missile: { sx: 9, sy: 42, w: 3, h: 20, frame: 1, }
 +
};
 +
 
 +
var enemies = {
 +
  straight: { x: 0,  y: -50, sprite: 'enemy_ship', health: 10,
 +
              E: 100 },
 +
  ltr:      { x: 0,  y: -100, sprite: 'enemy_purple', health: 10,
 +
              B: 75, C: 1, E: 100},
 +
  circle:  { x: 250,  y: -50, sprite: 'enemy_circle', health: 10,
 +
              A: 0,  B: -100, C: 1, E: 20, F: 100, G: 1, H: Math.PI/2 },
 +
  wiggle:  { x: 100, y: -50, sprite: 'enemy_bee', health: 20,
 +
              B: 50, C: 4, E: 100, firePercentage: 0.001 },
 +
  step:    { x: 0,  y: -50, sprite: 'enemy_circle', health: 10,
 +
              B: 150, C: 1.2, E: 75 }
 +
};
 +
 
 +
var OBJECT_PLAYER = 1,
 +
    OBJECT_PLAYER_PROJECTILE = 2,
 +
    OBJECT_ENEMY = 4,
 +
    OBJECT_ENEMY_PROJECTILE = 8,
 +
    OBJECT_POWERUP = 16;
 +
 
 +
var startGame = function() {
 +
  var ua = navigator.userAgent.toLowerCase();
 +
 
 +
  // Only 1 row of stars
 +
  if(ua.match(/android/)) {
 +
    Game.setBoard(0,new Starfield(50,0.6,100,true));
 +
  } else {
 +
    Game.setBoard(0,new Starfield(20,0.4,100,true));
 +
    Game.setBoard(1,new Starfield(50,0.6,100));
 +
    Game.setBoard(2,new Starfield(100,1.0,50));
 +
  } 
 +
  Game.setBoard(3,new TitleScreen("Alien Invasion",
 +
                                  "Press fire to start playing",
 +
                                  playGame));
 +
};
 +
 
 +
var level1 = [
 +
// Start,  End, Gap,  Type,  Override
 +
  [ 0,      4000,  500, 'step' ],
 +
  [ 6000,  13000, 800, 'ltr' ],
 +
  [ 10000,  16000, 400, 'circle' ],
 +
  [ 17800,  20000, 500, 'straight', { x: 50 } ],
 +
  [ 18200,  20000, 500, 'straight', { x: 90 } ],
 +
  [ 18200,  20000, 500, 'straight', { x: 10 } ],
 +
  [ 22000,  25000, 400, 'wiggle', { x: 150 }],
 +
  [ 22000,  25000, 400, 'wiggle', { x: 100 }]
 +
];
 +
 
 +
 
 +
 
 +
var playGame = function() {
 +
  var board = new GameBoard();
 +
  board.add(new PlayerShip());
 +
  board.add(new Level(level1,winGame));
 +
  Game.setBoard(3,board);
 +
  Game.setBoard(5,new GamePoints(0));
 +
};
 +
 
 +
var winGame = function() {
 +
  Game.setBoard(3,new TitleScreen("You win!",
 +
                                  "Press fire to play again",
 +
                                  playGame));
 +
};
 +
 
 +
var loseGame = function() {
 +
  Game.setBoard(3,new TitleScreen("You lose!",
 +
                                  "Press fire to play again",
 +
                                  playGame));
 +
};
 +
 
 +
var Starfield = function(speed,opacity,numStars,clear) {
 +
 
 +
  // Set up the offscreen canvas
 +
  var stars = document.createElement("canvas");
 +
  stars.width = Game.width;
 +
  stars.height = Game.height;
 +
  var starCtx = stars.getContext("2d");
 +
 
 +
  var offset = 0;
 +
 
 +
  // If the clear option is set,
 +
  // make the background black instead of transparent
 +
  if(clear) {
 +
    starCtx.fillStyle = "#000";
 +
    starCtx.fillRect(0,0,stars.width,stars.height);
 +
  }
 +
 
 +
  // Now draw a bunch of random 2 pixel
 +
  // rectangles onto the offscreen canvas
 +
  starCtx.fillStyle = "#FFF";
 +
  starCtx.globalAlpha = opacity;
 +
  for(var i=0;i<numStars;i++) {
 +
    starCtx.fillRect(Math.floor(Math.random()*stars.width),
 +
                    Math.floor(Math.random()*stars.height),
 +
                    2,
 +
                    2);
 +
  }
 +
 
 +
  // This method is called every frame
 +
  // to draw the starfield onto the canvas
 +
  this.draw = function(ctx) {
 +
    var intOffset = Math.floor(offset);
 +
    var remaining = stars.height - intOffset;
 +
 
 +
    // Draw the top half of the starfield
 +
    if(intOffset > 0) {
 +
      ctx.drawImage(stars,
 +
                0, remaining,
 +
                stars.width, intOffset,
 +
                0, 0,
 +
                stars.width, intOffset);
 +
    }
 +
 
 +
    // Draw the bottom half of the starfield
 +
    if(remaining > 0) {
 +
      ctx.drawImage(stars,
 +
              0, 0,
 +
              stars.width, remaining,
 +
              0, intOffset,
 +
              stars.width, remaining);
 +
    }
 +
  };
 +
 
 +
  // This method is called to update
 +
  // the starfield
 +
  this.step = function(dt) {
 +
    offset += dt * speed;
 +
    offset = offset % stars.height;
 +
  };
 +
};
 +
 
 +
var PlayerShip = function() {
 +
  this.setup('ship', { vx: 0, reloadTime: 0.25, maxVel: 200 });
 +
 
 +
  this.reload = this.reloadTime;
 +
  this.x = Game.width/2 - this.w / 2;
 +
  this.y = Game.height - Game.playerOffset - this.h;
 +
 
 +
  this.step = function(dt) {
 +
    if(Game.keys['left']) { this.vx = -this.maxVel; }
 +
    else if(Game.keys['right']) { this.vx = this.maxVel; }
 +
    else { this.vx = 0; }
 +
 
 +
    this.x += this.vx * dt;
 +
 
 +
    if(this.x < 0) { this.x = 0; }
 +
    else if(this.x > Game.width - this.w) {
 +
      this.x = Game.width - this.w;
 +
    }
 +
 
 +
    this.reload-=dt;
 +
    if(Game.keys['left'] && this.reload < 0) {
 +
      Game.keys['left'] = false;
 +
      this.reload = this.reloadTime;
 +
 
 +
    // this.board.add(new PlayerMissile(this.x,this.y+this.h/2));
 +
      //this.board.add(new PlayerMissile(this.x+this.w,this.y+this.h/2));
 +
    }
 +
 
 +
 
 +
  };
 +
};
 +
 
 +
PlayerShip.prototype = new Sprite();
 +
PlayerShip.prototype.type = OBJECT_PLAYER;
 +
 
 +
PlayerShip.prototype.hit = function(damage) {
 +
  if(this.board.remove(this)) {
 +
    loseGame();
 +
  }
 +
};
 +
 
 +
/*
 +
var PlayerMissile = function(x,y) {
 +
  this.setup('missile',{ vy: -700, damage: 10 });
 +
  this.x = x - this.w/2;
 +
  this.y = y - this.h;
 +
};
 +
 
 +
PlayerMissile.prototype = new Sprite();
 +
PlayerMissile.prototype.type = OBJECT_PLAYER_PROJECTILE;
 +
 
 +
PlayerMissile.prototype.step = function(dt)  {
 +
  this.y += this.vy * dt;
 +
  var collision = this.board.collide(this,OBJECT_ENEMY);
 +
  if(collision) {
 +
    collision.hit(this.damage);
 +
    this.board.remove(this);
 +
  } else if(this.y < -this.h) {
 +
      this.board.remove(this);
 +
  }
 +
};
 +
*/
 +
 
 +
var Enemy = function(blueprint,override) {
 +
  this.merge(this.baseParameters);
 +
  this.setup(blueprint.sprite,blueprint);
 +
  this.merge(override);
 +
};
 +
 
 +
Enemy.prototype = new Sprite();
 +
Enemy.prototype.type = OBJECT_ENEMY;
 +
 
 +
Enemy.prototype.baseParameters = { A: 0, B: 0, C: 0, D: 0,
 +
                                  E: 0, F: 0, G: 0, H: 0,
 +
                                  t: 0, reloadTime: 0.75,
 +
                                  reload: 0 };
 +
 
 +
Enemy.prototype.step = function(dt) {
 +
  this.t += dt;
 +
 
 +
  this.vx = this.A + this.B * Math.sin(this.C * this.t + this.D);
 +
  this.vy = this.E + this.F * Math.sin(this.G * this.t + this.H);
 +
 
 +
  this.x += this.vx * dt;
 +
  this.y += this.vy * dt;
 +
 
 +
if (this.sprite == "enemy_purple"){
 +
var collision = this.board.collide( this, OBJECT_PLAYER );
 +
if(collision) {
 +
collision.hit(this.damage);
 +
this.board.remove(this);
 +
}
 +
}
 +
else{
 +
var collision = this.board.collide( this, OBJECT_PLAYER );
 +
if(collision) {
 +
    Game.points += this.points || 100;
 +
      this.board.add(new Explosion(this.x + this.w/2,
 +
                                  this.y + this.h/2));
 +
}
 +
}
 +
 
 +
/*
 +
  if(Math.random() < 0.01 && this.reload <= 0) {
 +
    this.reload = this.reloadTime;
 +
    if(this.missiles == 2) {
 +
      this.board.add(new EnemyMissile(this.x+this.w-2,this.y+this.h));
 +
      this.board.add(new EnemyMissile(this.x+2,this.y+this.h));
 +
    } else {
 +
      this.board.add(new EnemyMissile(this.x+this.w/2,this.y+this.h));
 +
    }
 +
 
 +
*/ 
 +
  this.reload-=dt;
 +
 
 +
  if(this.y > Game.height ||
 +
    this.x < -this.w ||
 +
    this.x > Game.width) {
 +
      this.board.remove(this);
 +
if (this.sprite == "enemy_purple")
 +
  console.log(this)
 +
  }
 +
};
 +
/*
 +
Enemy.prototype.hit = function(damage) {
 +
  this.health -= damage;
 +
  if(this.health <=0) {
 +
    if(this.board.remove(this)) {
 +
      Game.points += this.points || 100;
 +
      this.board.add(new Explosion(this.x + this.w/2,
 +
                                  this.y + this.h/2));
 +
    }
 +
  }
 +
};
 +
 
 +
var EnemyMissile = function(x,y) {
 +
  this.setup('enemy_missile',{ vy: 200, damage: 10 });
 +
  this.x = x - this.w/2;
 +
  this.y = y;
 +
};
 +
 
 +
EnemyMissile.prototype = new Sprite();
 +
EnemyMissile.prototype.type = OBJECT_ENEMY_PROJECTILE;
 +
 
 +
EnemyMissile.prototype.step = function(dt)  {
 +
  this.y += this.vy * dt;
 +
  var collision = this.board.collide(this,OBJECT_PLAYER)
 +
  if(collision) {
 +
    collision.hit(this.damage);
 +
    this.board.remove(this);
 +
  } else if(this.y > Game.height) {
 +
      this.board.remove(this);
 +
  }
 +
};
 +
 
 +
*/
 +
 
 +
var Explosion = function(centerX,centerY) {
 +
  this.setup('explosion', { frame: 0 });
 +
  this.x = centerX - this.w/2;
 +
  this.y = centerY - this.h/2;
 +
};
 +
 
 +
Explosion.prototype = new Sprite();
 +
 
 +
Explosion.prototype.step = function(dt) {
 +
  this.frame++;
 +
  if(this.frame >= 12) {
 +
    this.board.remove(this);
 +
  }
 +
};
 +
 
 +
window.addEventListener("load", function() {
 +
  Game.initialize("game",sprites,startGame);
 +
});
 +
 
 +
 
 +
 
 +
</script>
 
</body>
 
</body>
 
</html>
 
</html>

Revision as of 06:27, 11 September 2016

<!DOCTYPE HTML> Alien Invasion

var sprites = { ship: { sx: 0, sy: 0, w: 37, h: 42, frames: 1 }, //missile: { sx: 0, sy: 30, w: 2, h: 10, frames: 1 }, enemy_purple: { sx: 37, sy: 0, w: 42, h: 43, frames: 1 }, enemy_bee: { sx: 79, sy: 0, w: 37, h: 43, frames: 1 }, enemy_ship: { sx: 116, sy: 0, w: 42, h: 43, frames: 1 }, enemy_circle: { sx: 158, sy: 0, w: 32, h: 33, frames: 1 }, explosion: { sx: 0, sy: 64, w: 64, h: 64, frames: 12 } //enemy_missile: { sx: 9, sy: 42, w: 3, h: 20, frame: 1, } }; var enemies = { straight: { x: 0, y: -50, sprite: 'enemy_ship', health: 10, E: 100 }, ltr: { x: 0, y: -100, sprite: 'enemy_purple', health: 10, B: 75, C: 1, E: 100}, circle: { x: 250, y: -50, sprite: 'enemy_circle', health: 10, A: 0, B: -100, C: 1, E: 20, F: 100, G: 1, H: Math.PI/2 }, wiggle: { x: 100, y: -50, sprite: 'enemy_bee', health: 20, B: 50, C: 4, E: 100, firePercentage: 0.001 }, step: { x: 0, y: -50, sprite: 'enemy_circle', health: 10, B: 150, C: 1.2, E: 75 } }; var OBJECT_PLAYER = 1, OBJECT_PLAYER_PROJECTILE = 2, OBJECT_ENEMY = 4, OBJECT_ENEMY_PROJECTILE = 8, OBJECT_POWERUP = 16; var startGame = function() { var ua = navigator.userAgent.toLowerCase(); // Only 1 row of stars if(ua.match(/android/)) { Game.setBoard(0,new Starfield(50,0.6,100,true)); } else { Game.setBoard(0,new Starfield(20,0.4,100,true)); Game.setBoard(1,new Starfield(50,0.6,100)); Game.setBoard(2,new Starfield(100,1.0,50)); } Game.setBoard(3,new TitleScreen("Alien Invasion", "Press fire to start playing", playGame)); }; var level1 = [ // Start, End, Gap, Type, Override [ 0, 4000, 500, 'step' ], [ 6000, 13000, 800, 'ltr' ], [ 10000, 16000, 400, 'circle' ], [ 17800, 20000, 500, 'straight', { x: 50 } ], [ 18200, 20000, 500, 'straight', { x: 90 } ], [ 18200, 20000, 500, 'straight', { x: 10 } ], [ 22000, 25000, 400, 'wiggle', { x: 150 }], [ 22000, 25000, 400, 'wiggle', { x: 100 }] ]; var playGame = function() { var board = new GameBoard(); board.add(new PlayerShip()); board.add(new Level(level1,winGame)); Game.setBoard(3,board); Game.setBoard(5,new GamePoints(0)); }; var winGame = function() { Game.setBoard(3,new TitleScreen("You win!", "Press fire to play again", playGame)); }; var loseGame = function() { Game.setBoard(3,new TitleScreen("You lose!", "Press fire to play again", playGame)); }; var Starfield = function(speed,opacity,numStars,clear) { // Set up the offscreen canvas var stars = document.createElement("canvas"); stars.width = Game.width; stars.height = Game.height; var starCtx = stars.getContext("2d"); var offset = 0; // If the clear option is set, // make the background black instead of transparent if(clear) { starCtx.fillStyle = "#000"; starCtx.fillRect(0,0,stars.width,stars.height); } // Now draw a bunch of random 2 pixel // rectangles onto the offscreen canvas starCtx.fillStyle = "#FFF"; starCtx.globalAlpha = opacity; for(var i=0;i 0) { ctx.drawImage(stars, 0, remaining, stars.width, intOffset, 0, 0, stars.width, intOffset); } // Draw the bottom half of the starfield if(remaining > 0) { ctx.drawImage(stars, 0, 0, stars.width, remaining, 0, intOffset, stars.width, remaining); } }; // This method is called to update // the starfield this.step = function(dt) { offset += dt * speed; offset = offset % stars.height; }; }; var PlayerShip = function() { this.setup('ship', { vx: 0, reloadTime: 0.25, maxVel: 200 }); this.reload = this.reloadTime; this.x = Game.width/2 - this.w / 2; this.y = Game.height - Game.playerOffset - this.h; this.step = function(dt) { if(Game.keys['left']) { this.vx = -this.maxVel; } else if(Game.keys['right']) { this.vx = this.maxVel; } else { this.vx = 0; } this.x += this.vx * dt; if(this.x < 0) { this.x = 0; } else if(this.x > Game.width - this.w) { this.x = Game.width - this.w; } this.reload-=dt; if(Game.keys['left'] && this.reload < 0) { Game.keys['left'] = false; this.reload = this.reloadTime; // this.board.add(new PlayerMissile(this.x,this.y+this.h/2)); //this.board.add(new PlayerMissile(this.x+this.w,this.y+this.h/2)); } }; }; PlayerShip.prototype = new Sprite(); PlayerShip.prototype.type = OBJECT_PLAYER; PlayerShip.prototype.hit = function(damage) { if(this.board.remove(this)) { loseGame(); } }; /* var PlayerMissile = function(x,y) { this.setup('missile',{ vy: -700, damage: 10 }); this.x = x - this.w/2; this.y = y - this.h; }; PlayerMissile.prototype = new Sprite(); PlayerMissile.prototype.type = OBJECT_PLAYER_PROJECTILE; PlayerMissile.prototype.step = function(dt) { this.y += this.vy * dt; var collision = this.board.collide(this,OBJECT_ENEMY); if(collision) { collision.hit(this.damage); this.board.remove(this); } else if(this.y < -this.h) { this.board.remove(this); } }; */ var Enemy = function(blueprint,override) { this.merge(this.baseParameters); this.setup(blueprint.sprite,blueprint); this.merge(override); }; Enemy.prototype = new Sprite(); Enemy.prototype.type = OBJECT_ENEMY; Enemy.prototype.baseParameters = { A: 0, B: 0, C: 0, D: 0, E: 0, F: 0, G: 0, H: 0, t: 0, reloadTime: 0.75, reload: 0 }; Enemy.prototype.step = function(dt) { this.t += dt; this.vx = this.A + this.B * Math.sin(this.C * this.t + this.D); this.vy = this.E + this.F * Math.sin(this.G * this.t + this.H); this.x += this.vx * dt; this.y += this.vy * dt; if (this.sprite == "enemy_purple"){ var collision = this.board.collide( this, OBJECT_PLAYER ); if(collision) { collision.hit(this.damage); this.board.remove(this); } } else{ var collision = this.board.collide( this, OBJECT_PLAYER ); if(collision) { Game.points += this.points || 100; this.board.add(new Explosion(this.x + this.w/2, this.y + this.h/2)); } } /* if(Math.random() < 0.01 && this.reload <= 0) { this.reload = this.reloadTime; if(this.missiles == 2) { this.board.add(new EnemyMissile(this.x+this.w-2,this.y+this.h)); this.board.add(new EnemyMissile(this.x+2,this.y+this.h)); } else { this.board.add(new EnemyMissile(this.x+this.w/2,this.y+this.h)); } */ this.reload-=dt; if(this.y > Game.height || this.x < -this.w || this.x > Game.width) { this.board.remove(this); if (this.sprite == "enemy_purple") console.log(this) } }; /* Enemy.prototype.hit = function(damage) { this.health -= damage; if(this.health <=0) { if(this.board.remove(this)) { Game.points += this.points || 100; this.board.add(new Explosion(this.x + this.w/2, this.y + this.h/2)); } } }; var EnemyMissile = function(x,y) { this.setup('enemy_missile',{ vy: 200, damage: 10 }); this.x = x - this.w/2; this.y = y; }; EnemyMissile.prototype = new Sprite(); EnemyMissile.prototype.type = OBJECT_ENEMY_PROJECTILE; EnemyMissile.prototype.step = function(dt) { this.y += this.vy * dt; var collision = this.board.collide(this,OBJECT_PLAYER) if(collision) { collision.hit(this.damage); this.board.remove(this); } else if(this.y > Game.height) { this.board.remove(this); } }; */ var Explosion = function(centerX,centerY) { this.setup('explosion', { frame: 0 }); this.x = centerX - this.w/2; this.y = centerY - this.h/2; }; Explosion.prototype = new Sprite(); Explosion.prototype.step = function(dt) { this.frame++; if(this.frame >= 12) { this.board.remove(this); } }; window.addEventListener("load", function() { Game.initialize("game",sprites,startGame); });