<commit_before>//////////////////// HMR BEGIN ////////////////////
if (module.hot) {
  (function(Elm) {
    "use strict";

    var programWithFlags = _elm_lang$virtual_dom$VirtualDom$programWithFlags;

    if (!programWithFlags) {
      console.warn('[elm-hot] Hot-swapping disabled because VirtualDom module was not found.')
      return;
    }

    var instances = module.hot.data
      ? module.hot.data.instances || {}
      : {};
    var uid = module.hot.data
      ? module.hot.uid || 0
      : 0;

    var cancellers = [];

    var initializingInstance = null, swappingInstance = null;

    module.hot.accept();
    module.hot.dispose(function(data) {
      data.instances = instances;
      data.uid = uid;
      if (cancellers.length) {
        console.log('[elm-hot] Killing ' + cancellers.length + ' running processes...');
        try {
          cancellers.forEach(function (cancel) {
            cancel();
          });
        } catch (e) {
          console.warn('[elm-hot] Kill process error: ' + e.message);
        }
      }
    });

    function getId() {
      return ++uid;
    }

    function findPublicModules(parent, path) {
      var modules = [];
      for (var key in parent) {
        var child = parent[key];
        var currentPath = path ? path + '.' + key : key;
        if ('fullscreen' in child) {
          modules.push({
            path: currentPath,
            module: child
          });
        } else {
          modules = modules.concat(findPublicModules(child, currentPath));
        }
      }
      return modules;
    }

    function getPublicModule(path) {
      var parts = path.split('.');
      var parent = Elm;
      for (var i = 0; i < parts.length; ++i) {
        var part = parts[i];
        if (part in parent) {
          parent = parent[part]
        }
        if (!parent) {
          return null;
        }
      }
      return parent
    }

    function registerInstance(domNode, flags, path, portSubscribes) {
      var id = getId();
      return instances[id] = {
        id: id,
        path: path,
        domNode: domNode,
        flags: flags,
        portSubscribes: portSubscribes,
        elmProxy: null
      };
    }

    function wrapPublicModule(path, module) {
      var embed = module.embed;
      var fullscreen = module.fullscreen;
      module.embed = function(domNode, flags) {
        var elm;
        var portSubscribes = {};
        initializingInstance = registerInstance(domNode, flags, path, portSubscribes)
        elm = embed(domNode, flags);
        wrapPorts(elm, portSubscribes)
        elm = initializingInstance.elmProxy = {
          ports: elm.ports
        };
        initializingInstance = null;
        return elm;
      };

      module.fullscreen = function (flags) {
        var elm
        var portSubscribes = {};
        initializingInstance = registerInstance(document.body, flags, path, portSubscribes)
        elm = fullscreen(flags);
        wrapPorts(elm, portSubscribes)
        elm = initializingInstance.elmProxy = {
          ports: elm.ports
        };
        initializingInstance = null;
        return elm;
      }
    }

    function swap(instance) {
      console.log('[elm-hot] Hot-swapping module: ' + instance.path)

      swappingInstance = instance;

      var domNode = instance.domNode;

      while (domNode.lastChild) {
        domNode.removeChild(domNode.lastChild);
      }

      var m = getPublicModule(instance.path)
      var elm;
      if (m) {
        if (instance.isFullscreen) {
          elm = m.fullscreen(instance.flags);
        } else {
          elm = m.embed(domNode, instance.flags);
        }

        instance.elmProxy.ports = elm.ports;

        Object.keys(instance.portSubscribes).forEach(function(portName) {
          if (portName in elm.ports && 'subscribe' in elm.ports[portName]) {
            var handlers = instance.portSubscribes[portName];
            if (!handlers.length) {
              return;
            }
            console.log('[elm-hot] Reconnect ' + handlers.length + ' handler(s) to port \'' + portName + '\' (' + instance.path + ').');
            handlers.forEach(function(handler) {
              elm.ports[portName].subscribe(handler);
            });
          } else {
            delete instance.portSubscribes[portName];
            console.log('[elm-hot] Port was removed: ' + portName);
          }
        });
      } else {
        console.log('[elm-hot] Module was removed: ' + instance.path);
      }

      swappingInstance = null;
    }

    function wrapPorts(elm, portSubscribes) {
      var portNames = Object.keys(elm.ports);
      //hook ports
      if (portNames.length) {
        portNames
          .filter(function(name) {
            return 'subscribe' in elm.ports[name];
          })
          .forEach(function(portName) {
            var port = elm.ports[portName];
            var subscribe = port.subscribe;
            var unsubscribe = port.unsubscribe;
            elm.ports[portName] = Object.assign(port, {
              subscribe: function(handler) {
                console.log('[elm-hot] ports.' + portName + '.subscribe called.');
                if (!portSubscribes[portName]) {
                  portSubscribes[portName] = [ handler ];
                } else {
                  //TODO handle subscribing to single handler more than once?
                  portSubscribes[portName].push(handler);
                }
                return subscribe.call(port, handler);
              },
              unsubscribe: function(handler) {
                console.log('[elm-hot] ports.' + portName + '.unsubscribe called.');
                var list = portSubscribes[portName];
                if (list && list.indexOf(handler) !== -1) {
                  list.splice(list.lastIndexOf(handler), 1);
                } else {
                  console.warn('[elm-hot] ports.' + portName + '.unsubscribe: handler not subscribed');
                }
                return unsubscribe.call(port, handler);
              }
            });
          });
      }
      return portSubscribes;
    }

    // hook program creation
    _elm_lang$virtual_dom$VirtualDom$programWithFlags = function () {
      var instance = initializingInstance;
      var swapping = swappingInstance;
      var tryFirstRender = !!swappingInstance;
      var isInitialRender = true;
      var program = programWithFlags.apply(this, arguments);

      //var makeRenderer = program.renderer;
      var init = program.init;
      var view = program.view;
      program.init = function () {
        var result = init.apply(this, arguments);
        if (swapping) {
          result._0 = swapping.lastState;
        }
        return result;
      };
      program.view = function(model) {
        var result;
        // first render may fail if shape of model changed too much
        if (tryFirstRender) {
          tryFirstRender = false;
          try {
            result = view(model);
          } catch (e) {
            throw new Error('[elm-hot] Hot-swapping is not possible, please reload page.');
          }
        } else {
          result = view(model);
        }
        if (instance) {
          instance.lastState = model;
        } else {
          instance = swapping;
        }
        isInitialRender = false;
        return result;
      };
      return program;
    }

    // hook process creation
    var nativeBinding = _elm_lang$core$Native_Scheduler.nativeBinding
    _elm_lang$core$Native_Scheduler.nativeBinding = function() {
      var def = nativeBinding.apply(this, arguments);
      var callback = def.callback
      def.callback = function() {
        var result = callback.apply(this, arguments)
        if (result) {
          cancellers.push(result);
          return function() {
            cancellers.splice(cancellers.indexOf(result), 1);
            return result();
          };
        }
        return result;
      };
      return def;
    };

    // swap instances
    var removedInstances = [];
    for (var id in instances) {
      var instance = instances[id]
      if (instance.domNode.parentNode) {
        swap(instance);
      } else {
        removedInstances.push(id);
      }
    }

    removedInstances.forEach(function (id) {
      delete instance[id];
    });

    // wrap all public modules
    var publicModules = findPublicModules(Elm);
    publicModules.forEach(function (m) {
      wrapPublicModule(m.path, m.module);
    });
  })(Elm);
}
//////////////////// HMR END ////////////////////<commit_msg>Don't error when there are no ports<commit_after>//////////////////// HMR BEGIN ////////////////////
if (module.hot) {
  (function(Elm) {
    "use strict";

    var programWithFlags = _elm_lang$virtual_dom$VirtualDom$programWithFlags;

    if (!programWithFlags) {
      console.warn('[elm-hot] Hot-swapping disabled because VirtualDom module was not found.')
      return;
    }

    var instances = module.hot.data
      ? module.hot.data.instances || {}
      : {};
    var uid = module.hot.data
      ? module.hot.uid || 0
      : 0;

    var cancellers = [];

    var initializingInstance = null, swappingInstance = null;

    module.hot.accept();
    module.hot.dispose(function(data) {
      data.instances = instances;
      data.uid = uid;
      if (cancellers.length) {
        console.log('[elm-hot] Killing ' + cancellers.length + ' running processes...');
        try {
          cancellers.forEach(function (cancel) {
            cancel();
          });
        } catch (e) {
          console.warn('[elm-hot] Kill process error: ' + e.message);
        }
      }
    });

    function getId() {
      return ++uid;
    }

    function findPublicModules(parent, path) {
      var modules = [];
      for (var key in parent) {
        var child = parent[key];
        var currentPath = path ? path + '.' + key : key;
        if ('fullscreen' in child) {
          modules.push({
            path: currentPath,
            module: child
          });
        } else {
          modules = modules.concat(findPublicModules(child, currentPath));
        }
      }
      return modules;
    }

    function getPublicModule(path) {
      var parts = path.split('.');
      var parent = Elm;
      for (var i = 0; i < parts.length; ++i) {
        var part = parts[i];
        if (part in parent) {
          parent = parent[part]
        }
        if (!parent) {
          return null;
        }
      }
      return parent
    }

    function registerInstance(domNode, flags, path, portSubscribes) {
      var id = getId();
      return instances[id] = {
        id: id,
        path: path,
        domNode: domNode,
        flags: flags,
        portSubscribes: portSubscribes,
        elmProxy: null
      };
    }

    function wrapPublicModule(path, module) {
      var embed = module.embed;
      var fullscreen = module.fullscreen;
      module.embed = function(domNode, flags) {
        var elm;
        var portSubscribes = {};
        initializingInstance = registerInstance(domNode, flags, path, portSubscribes)
        elm = embed(domNode, flags);
        wrapPorts(elm, portSubscribes)
        elm = initializingInstance.elmProxy = {
          ports: elm.ports
        };
        initializingInstance = null;
        return elm;
      };

      module.fullscreen = function (flags) {
        var elm
        var portSubscribes = {};
        initializingInstance = registerInstance(document.body, flags, path, portSubscribes)
        elm = fullscreen(flags);
        wrapPorts(elm, portSubscribes)
        elm = initializingInstance.elmProxy = {
          ports: elm.ports
        };
        initializingInstance = null;
        return elm;
      }
    }

    function swap(instance) {
      console.log('[elm-hot] Hot-swapping module: ' + instance.path)

      swappingInstance = instance;

      var domNode = instance.domNode;

      while (domNode.lastChild) {
        domNode.removeChild(domNode.lastChild);
      }

      var m = getPublicModule(instance.path)
      var elm;
      if (m) {
        if (instance.isFullscreen) {
          elm = m.fullscreen(instance.flags);
        } else {
          elm = m.embed(domNode, instance.flags);
        }

        instance.elmProxy.ports = elm.ports;

        Object.keys(instance.portSubscribes).forEach(function(portName) {
          if (portName in elm.ports && 'subscribe' in elm.ports[portName]) {
            var handlers = instance.portSubscribes[portName];
            if (!handlers.length) {
              return;
            }
            console.log('[elm-hot] Reconnect ' + handlers.length + ' handler(s) to port \'' + portName + '\' (' + instance.path + ').');
            handlers.forEach(function(handler) {
              elm.ports[portName].subscribe(handler);
            });
          } else {
            delete instance.portSubscribes[portName];
            console.log('[elm-hot] Port was removed: ' + portName);
          }
        });
      } else {
        console.log('[elm-hot] Module was removed: ' + instance.path);
      }

      swappingInstance = null;
    }

    function wrapPorts(elm, portSubscribes) {
      var portNames = Object.keys(elm.ports || {});
      //hook ports
      if (portNames.length) {
        portNames
          .filter(function(name) {
            return 'subscribe' in elm.ports[name];
          })
          .forEach(function(portName) {
            var port = elm.ports[portName];
            var subscribe = port.subscribe;
            var unsubscribe = port.unsubscribe;
            elm.ports[portName] = Object.assign(port, {
              subscribe: function(handler) {
                console.log('[elm-hot] ports.' + portName + '.subscribe called.');
                if (!portSubscribes[portName]) {
                  portSubscribes[portName] = [ handler ];
                } else {
                  //TODO handle subscribing to single handler more than once?
                  portSubscribes[portName].push(handler);
                }
                return subscribe.call(port, handler);
              },
              unsubscribe: function(handler) {
                console.log('[elm-hot] ports.' + portName + '.unsubscribe called.');
                var list = portSubscribes[portName];
                if (list && list.indexOf(handler) !== -1) {
                  list.splice(list.lastIndexOf(handler), 1);
                } else {
                  console.warn('[elm-hot] ports.' + portName + '.unsubscribe: handler not subscribed');
                }
                return unsubscribe.call(port, handler);
              }
            });
          });
      }
      return portSubscribes;
    }

    // hook program creation
    _elm_lang$virtual_dom$VirtualDom$programWithFlags = function () {
      var instance = initializingInstance;
      var swapping = swappingInstance;
      var tryFirstRender = !!swappingInstance;
      var isInitialRender = true;
      var program = programWithFlags.apply(this, arguments);

      //var makeRenderer = program.renderer;
      var init = program.init;
      var view = program.view;
      program.init = function () {
        var result = init.apply(this, arguments);
        if (swapping) {
          result._0 = swapping.lastState;
        }
        return result;
      };
      program.view = function(model) {
        var result;
        // first render may fail if shape of model changed too much
        if (tryFirstRender) {
          tryFirstRender = false;
          try {
            result = view(model);
          } catch (e) {
            throw new Error('[elm-hot] Hot-swapping is not possible, please reload page.');
          }
        } else {
          result = view(model);
        }
        if (instance) {
          instance.lastState = model;
        } else {
          instance = swapping;
        }
        isInitialRender = false;
        return result;
      };
      return program;
    }

    // hook process creation
    var nativeBinding = _elm_lang$core$Native_Scheduler.nativeBinding
    _elm_lang$core$Native_Scheduler.nativeBinding = function() {
      var def = nativeBinding.apply(this, arguments);
      var callback = def.callback
      def.callback = function() {
        var result = callback.apply(this, arguments)
        if (result) {
          cancellers.push(result);
          return function() {
            cancellers.splice(cancellers.indexOf(result), 1);
            return result();
          };
        }
        return result;
      };
      return def;
    };

    // swap instances
    var removedInstances = [];
    for (var id in instances) {
      var instance = instances[id]
      if (instance.domNode.parentNode) {
        swap(instance);
      } else {
        removedInstances.push(id);
      }
    }

    removedInstances.forEach(function (id) {
      delete instance[id];
    });

    // wrap all public modules
    var publicModules = findPublicModules(Elm);
    publicModules.forEach(function (m) {
      wrapPublicModule(m.path, m.module);
    });
  })(Elm);
}
//////////////////// HMR END ////////////////////
<|endoftext|>


<commit_before>function Game(currentLevel, maxLevels, movesMade, clickInterval, clickWidth, flashInterval, colorContainerClass, nextClass, colorsNumber,colorIDs){
	this.hasLost = false;
	this.currentLevel = currentLevel;
	this.maximumLevels = maxLevels;
	this.movesMade = movesMade;
	this.clickEffectInterval = clickInterval;
	this.clickEffectWidth = clickWidth;
	this.flashEffectInterval = flashInterval;
	this.colorContainerClass = colorContainerClass;
	this.nextClass = nextClass;
	this.colorsSequence = new Array();
	this.movesSequence = new Array();
	this.colorObjects = new Array();
	for(i=0; i<colorsNumber; i++){
		var temp = {'id': colorIDs[i]};
		this.colorObjects[i] = temp;
	}
}

Game.prototype.upgradeLevel = function(){
	this.currentLevel++;
	$('#star').html(this.currentLevel);
}

Game.prototype.resetMoves = function(){
	this.movesMade=0;
	$('#moves-value').html(this.currentLevel - this.movesMade);
	this.movesSequence = new Array();
}

Game.prototype.proceedToNextLevel = function(){
	this.upgradeLevel();
	this.resetMoves();
	var nextColor = this.getRandomColor();
	this.colorsSequence.push(nextColor);
	this.flashSequence(this.colorsSequence);
}

Game.prototype.handleNextMove = function(selectedColorNumber){
	this.movesMade++;
	console.log('moves : ' + this.movesMade);
	console.log('selected : ' + selectedColorNumber);
	console.log('right : ' + this.colorsSequence[this.movesMade-1]);
	if(selectedColorNumber != this.colorsSequence[this.movesMade-1]){
		alert('You lost');
		this.end();
	}
	else{
		if(this.movesMade == this.currentLevel){
			if(this.currentLevel == this.maximumLevels){
				alert("You won!");
				this.end();
			}
			else{
				var that = this;
				setTimeout(function(){that.proceedToNextLevel();}, that.clickEffectInterval*5);
			}
		}
		else{
			this.movesSequence[this.movesMade-1];
			$('#moves-value').html(this.currentLevel - this.movesMade);
		}
	}
}

Game.prototype.getRandomColor = function(){
	return Math.round(Math.random()*(this.colorObjects.length-1));
}

Game.prototype.flashPreviousElement = function(elementNumber){
	var that = this;
	var elementID = this.colorObjects[elementNumber].id;
	$('.' + this.colorContainerClass + ':not(#' + elementID + ')').fadeTo(this.flashEffectInterval, 0).delay(this.flashEffectInterval*4).fadeTo(this.flashEffectInterval, 1);
}

Game.prototype.flashElement = function(elementNumber){
	var elementID = this.colorObjects[elementNumber].id;
	$('#' + elementID).fadeTo(this.flashEffectInterval, 1).fadeTo(this.flashEffectInterval, 0);
}

Game.prototype.flashSequence = function(sequence){
	var that = this;
	$('.' + this.colorContainerClass).fadeTo(this.flashEffectInterval, 0);
	$('#' + this.nextClass).fadeTo(this.flashEffectInterval, 1);
	if(sequence != null){
		for(i=0; i<sequence.length; i++){
			var colourNumber = sequence[i];
			(function(number){
				setTimeout(function(){that.flashElement(number)},that.flashEffectInterval*4*(i+1));
			})(colourNumber);
		}
	}
	setTimeout(function(){$('.' + that.colorContainerClass).fadeTo(that.flashEffectInterval, 1)}, that.flashEffectInterval*4*(sequence.length+1));
	setTimeout(function(){$('#' + that.nextClass).fadeTo(that.flashEffectInterval, 0)}, that.flashEffectInterval*4*(sequence.length+1));
}

Game.prototype.end = function(){
	$('.colors').unbind('click');
	$('#play').show();
}<commit_msg>added Game metrics<commit_after>function Game(currentLevel, maxLevels, movesMade, clickInterval, clickWidth, flashInterval, colorContainerClass, nextClass, colorsNumber,colorIDs){
	this.hasLost = false;
	this.currentLevel = currentLevel;
	this.maximumLevels = maxLevels;
	this.movesMade = movesMade;
	this.clickEffectInterval = clickInterval;
	this.clickEffectWidth = clickWidth;
	this.flashEffectInterval = flashInterval;
	this.colorContainerClass = colorContainerClass;
	this.nextClass = nextClass;
	this.colorsSequence = new Array();
	this.movesSequence = new Array();
	this.colorObjects = new Array();
	for(i=0; i<colorsNumber; i++){
		var temp = {'id': colorIDs[i]};
		this.colorObjects[i] = temp;
	}
	this.startMoment = (new Date()).getTime();
}

Game.prototype.upgradeLevel = function(){
	this.currentLevel++;
	$('#star').html(this.currentLevel);
}

Game.prototype.resetMoves = function(){
	this.movesMade=0;
	$('#moves-value').html(this.currentLevel - this.movesMade);
	this.movesSequence = new Array();
}

Game.prototype.proceedToNextLevel = function(){
	this.upgradeLevel();
	this.resetMoves();
	var nextColor = this.getRandomColor();
	this.colorsSequence.push(nextColor);
	this.flashSequence(this.colorsSequence);
}

Game.prototype.handleNextMove = function(selectedColorNumber){
	this.movesMade++;
	console.log('moves : ' + this.movesMade);
	console.log('selected : ' + selectedColorNumber);
	console.log('right : ' + this.colorsSequence[this.movesMade-1]);
	if(selectedColorNumber != this.colorsSequence[this.movesMade-1]){
		this.end(0);
	}
	else{
		if(this.movesMade == this.currentLevel){
			if(this.currentLevel == this.maximumLevels){
				this.end(1);
			}
			else{
				var that = this;
				setTimeout(function(){that.proceedToNextLevel();}, that.clickEffectInterval*5);
			}
		}
		else{
			this.movesSequence[this.movesMade-1];
			$('#moves-value').html(this.currentLevel - this.movesMade);
		}
	}
}

Game.prototype.getRandomColor = function(){
	return Math.round(Math.random()*(this.colorObjects.length-1));
}

Game.prototype.flashPreviousElement = function(elementNumber){
	var that = this;
	var elementID = this.colorObjects[elementNumber].id;
	$('.' + this.colorContainerClass + ':not(#' + elementID + ')').fadeTo(this.flashEffectInterval, 0).delay(this.flashEffectInterval*4).fadeTo(this.flashEffectInterval, 1);
}

Game.prototype.flashElement = function(elementNumber){
	var elementID = this.colorObjects[elementNumber].id;
	$('#' + elementID).fadeTo(this.flashEffectInterval, 1).fadeTo(this.flashEffectInterval, 0);
}

Game.prototype.flashSequence = function(sequence){
	var that = this;
	$('.' + this.colorContainerClass).fadeTo(this.flashEffectInterval, 0);
	$('#' + this.nextClass).fadeTo(this.flashEffectInterval, 1);
	if(sequence != null){
		for(i=0; i<sequence.length; i++){
			var colourNumber = sequence[i];
			(function(number){
				setTimeout(function(){that.flashElement(number)},that.flashEffectInterval*4*(i+1));
			})(colourNumber);
		}
	}
	setTimeout(function(){$('.' + that.colorContainerClass).fadeTo(that.flashEffectInterval, 1)}, that.flashEffectInterval*4*(sequence.length+1));
	setTimeout(function(){$('#' + that.nextClass).fadeTo(that.flashEffectInterval, 0)}, that.flashEffectInterval*4*(sequence.length+1));
}

Game.prototype.end = function(gameResult){
	var end = (new Date()).getTime();
	var secondsPlayed = Math.floor((end-this.startMoment)/1000);
	if(gameResult == 0){
		alert("You lost ! Seconds played : " + secondsPlayed + ", Level reached: " + this.currentLevel);
	}
	else if(gameResult == 1){
		alert("You won ! Seconds played : " + secondsPlayed + ", Level reached: " + (this.maximumLevels + 1));
	}
	$('.colors').unbind('click');
	$('#play').show();
}<|endoftext|>


<commit_before><commit_msg>Remove critical from production<commit_after><|endoftext|>


<commit_before>// ALIENS;

    // Sets speed of missiles
var AlienFlock = function AlienFlock() {
  this.invulnrable = true;
  this.dx = 10; this.dy = 0;
  this.hit = 1; this.lastHit = 0;
  this.speed = 10;

  this.draw = function() {};

    // If there is a next level then load if, if not show the win screen.
  this.die = function() {
    if(Game.board.nextLevel()) {
      Game.loadBoard(new GameBoard(Game.board.nextLevel()));
    } else {
      Game.callbacks['win']();
    }
  }

//   ASK

  this.step = function(dt) {
    if(this.hit && this.hit != this.lastHit) {
      this.lastHit = this.hit;
      this.dy = this.speed;
    } else {
      this.dy=0;
    }
    this.dx = this.speed * this.hit;

    var max = {}, cnt = 0;
    this.board.iterate(function() {
      if(this instanceof Alien)  {
        if(!max[this.x] || this.y > max[this.x]) {
          max[this.x] = this.y;
        }
        cnt++;
      }
    });

    if(cnt == 0) { this.die(); }

    this.max_y = max;
    return true;
  };

}

// Sets position and information on each alien.

var Alien = function Alien(opts) {
  this.flock = opts['flock'];
  this.frame = 0;
  this.mx = 0;
}

    // Draws alien from sprite card
Alien.prototype.draw = function(canvas) {
  Sprites.draw(canvas,this.name,this.x,this.y,this.frame);
}

    // Play dying sound when alien is hit by user and remove specific alien from game
Alien.prototype.die = function() {
  GameAudio.play('die');
  this.flock.speed += 1;
  this.board.remove(this);
  playerScore++;

}

// ASK

Alien.prototype.step = function(dt) {
  this.mx += dt * this.flock.dx;
  this.y += this.flock.dy;
  if(Math.abs(this.mx) > 10) {
    if(this.y == this.flock.max_y[this.x]) {
      this.fireSometimes();
    }
    this.x += this.mx;
    this.mx = 0;
    this.frame = (this.frame+1) % 1;
    if(this.x > Game.width - Sprites.map.alien1.w * 2) this.flock.hit = -1;
    if(this.x < Sprites.map.alien1.w) this.flock.hit = 1;
  }

  return true;
}
    // Sets missile firing to random timing by aliens.
Alien.prototype.fireSometimes = function() {
      if(Math.random()*100 < 5) {
        this.board.addSprite('missile',this.x + this.w/2 - Sprites.map.missile.w/2,
                                      this.y + this.h,
                                     { dy: 100 });
      }
}

// PLAYER; Loads graphic from sprite card and sets position on game.
var Player = function Player(opts) {
  this.reloading = 0;
}

Player.prototype.draw = function(canvas) {
   Sprites.draw(canvas,'player',this.x,this.y);
}

// Sets what happens when the user dies
Player.prototype.die = function() {
  GameAudio.play('die');
  Game.callbacks['die']();
}

// PLAYER; Explains what happens when left and right arrow keys are pressed - moves player left and right.
Player.prototype.step = function(dt) {
  if(Game.keys['left']) { this.x -= 100 * dt; }
  if(Game.keys['right']) { this.x += 100 * dt; }

    // Stops moving when they get to the edge of the screen = 0.
  if(this.x < 0) this.x = 0;
  if(this.x > Game.width-this.w) this.x = Game.width-this.w;

    // Code below is set for player to move up and down
  if(Game.keys['up']) { this.y -= 100 * dt; }
  if(Game.keys['down']) { this.y += 100 * dt; }

  if(this.y < 0) this.y = 0;
  if(this.y > Game.height-this.h) this.y = Game.height-this.h;

  this.reloading--;

    // Sets how many missiles can be fired at once, also adds graphic and sound for missile. Also sets position of graphics on screen - follows user.
  if(Game.keys['fire'] && this.reloading <= 0 && this.board.missiles < 5) {
    GameAudio.play('fire');
    this.board.addSprite('missile',
                          this.x + this.w/2 - Sprites.map.missile.w/2,
                          this.y-this.h,
                          { dy: -100, player: true });
    this.board.missiles++;
    this.reloading = 10;
  }
  return true;
}

playerScore =0;
scorerInterval = setInterval(function() {
  document.getElementById("score").innerHTML = playerScore;

});

var Missile = function Missile(opts) {
   this.dy = opts.dy;
   this.player = opts.player;
}

// MISSILES; calls graphic from sprite card and tells game where and when to use missiles.

Missile.prototype.draw = function(canvas) {
   Sprites.draw(canvas,'missile',this.x,this.y);
}

Missile.prototype.step = function(dt) {
   this.y += this.dy * dt;

    // Tells missiles to dissapear if collided with alien
   var enemy = this.board.collide(this);
   if(enemy) {
     enemy.die();
     return false;
   }
   return (this.y < 0 || this.y > Game.height) ? false : true;
}

    // What happens if the missile collides with player?
Missile.prototype.die = function() {
  if(this.player) this.board.missiles--;
  if(this.board.missiles < 0) this.board.missiles=0;
   this.board.remove(this);
}

<commit_msg>Speed of user ammended<commit_after>// ALIENS;

    // Sets speed of missiles
var AlienFlock = function AlienFlock() {
  this.invulnrable = true;
  this.dx = 10; this.dy = 0;
  this.hit = 1; this.lastHit = 0;
  this.speed = 10;

  this.draw = function() {};

    // If there is a next level then load if, if not show the win screen.
  this.die = function() {
    if(Game.board.nextLevel()) {
      Game.loadBoard(new GameBoard(Game.board.nextLevel()));
    } else {
      Game.callbacks['win']();
    }
  }

//   ASK

  this.step = function(dt) {
    if(this.hit && this.hit != this.lastHit) {
      this.lastHit = this.hit;
      this.dy = this.speed;
    } else {
      this.dy=0;
    }
    this.dx = this.speed * this.hit;

    var max = {}, cnt = 0;
    this.board.iterate(function() {
      if(this instanceof Alien)  {
        if(!max[this.x] || this.y > max[this.x]) {
          max[this.x] = this.y;
        }
        cnt++;
      }
    });

    if(cnt == 0) { this.die(); }

    this.max_y = max;
    return true;
  };

}

// Sets position and information on each alien.

var Alien = function Alien(opts) {
  this.flock = opts['flock'];
  this.frame = 0;
  this.mx = 0;
}

    // Draws alien from sprite card
Alien.prototype.draw = function(canvas) {
  Sprites.draw(canvas,this.name,this.x,this.y,this.frame);
}

    // Play dying sound when alien is hit by user and remove specific alien from game
Alien.prototype.die = function() {
  GameAudio.play('die');
  this.flock.speed += 1;
  this.board.remove(this);
  playerScore++;

}

// ASK

Alien.prototype.step = function(dt) {
  this.mx += dt * this.flock.dx;
  this.y += this.flock.dy;
  if(Math.abs(this.mx) > 10) {
    if(this.y == this.flock.max_y[this.x]) {
      this.fireSometimes();
    }
    this.x += this.mx;
    this.mx = 0;
    this.frame = (this.frame+1) % 1;
    if(this.x > Game.width - Sprites.map.alien1.w * 2) this.flock.hit = -1;
    if(this.x < Sprites.map.alien1.w) this.flock.hit = 1;
  }

  return true;
}
    // Sets missile firing to random timing by aliens.
Alien.prototype.fireSometimes = function() {
      if(Math.random()*100 < 5) {
        this.board.addSprite('missile',this.x + this.w/2 - Sprites.map.missile.w/2,
                                      this.y + this.h,
                                     { dy: 100 });
      }
}

// PLAYER; Loads graphic from sprite card and sets position on game.
var Player = function Player(opts) {
  this.reloading = 0;
}

Player.prototype.draw = function(canvas) {
   Sprites.draw(canvas,'player',this.x,this.y);
}

// Sets what happens when the user dies
Player.prototype.die = function() {
  GameAudio.play('die');
  Game.callbacks['die']();
}

// PLAYER; Explains what happens when left and right arrow keys are pressed - moves player left and right.
     // 100 *dt = speed
Player.prototype.step = function(dt) {
  if(Game.keys['left']) { this.x -= 100 * dt; }
  if(Game.keys['right']) { this.x += 100 * dt; }

    // Stops moving when they get to the edge of the screen = 0.
  if(this.x < 0) this.x = 0;
  if(this.x > Game.width-this.w) this.x = Game.width-this.w;

        // 100 *dt = speed
    // Code below is set for player to move up and down
  if(Game.keys['up']) { this.y -= 100 * dt; }
  if(Game.keys['down']) { this.y += 100 * dt; }

  if(this.y < 0) this.y = 0;
  if(this.y > Game.height-this.h) this.y = Game.height-this.h;

  this.reloading--;

    // Sets how many missiles can be fired at once, also adds graphic and sound for missile. Also sets position of graphics on screen - follows user.
  if(Game.keys['fire'] && this.reloading <= 0 && this.board.missiles < 5) {
    GameAudio.play('fire');
    this.board.addSprite('missile',
                          this.x + this.w/2 - Sprites.map.missile.w/2,
                          this.y-this.h,
                          { dy: -100, player: true });
    this.board.missiles++;
    this.reloading = 10;
  }
  return true;
}

playerScore =0;
scorerInterval = setInterval(function() {
  document.getElementById("score").innerHTML = playerScore;

});

var Missile = function Missile(opts) {
   this.dy = opts.dy;
   this.player = opts.player;
}

// MISSILES; calls graphic from sprite card and tells game where and when to use missiles.

Missile.prototype.draw = function(canvas) {
   Sprites.draw(canvas,'missile',this.x,this.y);
}

Missile.prototype.step = function(dt) {
   this.y += this.dy * dt;

    // Tells missiles to dissapear if collided with alien
   var enemy = this.board.collide(this);
   if(enemy) {
     enemy.die();
     return false;
   }
   return (this.y < 0 || this.y > Game.height) ? false : true;
}

    // What happens if the missile collides with player?
Missile.prototype.die = function() {
  if(this.player) this.board.missiles--;
  if(this.board.missiles < 0) this.board.missiles=0;
   this.board.remove(this);
}

<|endoftext|>


<commit_before>var global = {
    network: {
        socket: undefined,
        host: "localhost",
        port: 3000
    }
}

/* Game namespace */
var game = {

    data: {
        players: {},

        localPlayer : null,

        playersDirty: true,

        // score
        score: 0,

        time: 100,

        localSpy: false,

        rituel: {
            gaugeStartValue: 50,
            gaugeCurrentValue: 50,
            gaugeMaxValue: 100,
            goodRitualInc: +1,
            badRitualInc: -2,
        }
    },
    functions: {
        playerById: function (id) {
            return game.data.players[id];
        }
    },

    // Run on page load.
    "onload": function () {

        // Initialize the video.
        if (!me.video.init(640, 480, {wrapper: "screen", scale: "auto"})) {
            alert("Your browser does not support HTML5 canvas.");
            return;
        }

        // add "#debug" to the URL to enable the debug Panel
        if (me.game.HASH.debug === true) {
            window.onReady(function () {
                me.plugin.register.defer(this, me.debug.Panel, "debug", me.input.KEY.V);
            });
        }

        // Initialize the audio.
        me.audio.init("mp3,ogg");
        me.audio.disable();

        // Set a callback to run when loading is complete.
        me.loader.onload = this.loaded.bind(this);

        // Load the resources.
        me.loader.preload(game.resources);

        // Initialize melonJS and display a loading screen.
        me.state.change(me.state.LOADING);
    },

    // Run on game resources loaded.

    "loaded": function () {
        //   me.state.set(me.state.MENU, new game.TitleScreen());
        me.state.set(me.state.READY, new game.MainScreen());

        // set the "Play/Ingame" Screen Object
        me.state.set(me.state.MENU, new game.TitleScreen());
        me.state.set(me.state.PLAY, new game.PlayScreen());

        // set a global fading transition for the screen
        me.state.transition("fade", "#FFFFFF", 250);

        // register our player entity in the object pool
        me.pool.register("mainPlayer", game.PlayerEntity);
        me.pool.register("networkPlayer", game.NetworkPlayer);

        // me.pool.register("ingredientEntity", game.IngredientEntity);
        //me.pool.register("opponentEntity", game.OpponentEntity); // TODO use a playerEntity

        // enable the keyboard
        me.input.bindKey(me.input.KEY.LEFT, "left");
        me.input.bindKey(me.input.KEY.RIGHT, "right");
        me.input.bindKey(me.input.KEY.UP, "up");
        me.input.bindKey(me.input.KEY.DOWN, "down");
        me.input.bindKey(me.input.KEY.X, "dance");
        me.input.bindKey(me.input.KEY.SPACE, "carry", true);

        // start the game
        me.state.change(me.state.MENU);
    }
};
<commit_msg>start in game state<commit_after>var global = {
    network: {
        socket: undefined,
        host: "localhost",
        port: 3000
    }
}

/* Game namespace */
var game = {

    data: {
        players: {},

        localPlayer : null,

        playersDirty: true,

        // score
        score: 0,

        time: 100,

        localSpy: false,

        rituel: {
            gaugeStartValue: 50,
            gaugeCurrentValue: 50,
            gaugeMaxValue: 100,
            goodRitualInc: +1,
            badRitualInc: -2,
        }
    },
    functions: {
        playerById: function (id) {
            return game.data.players[id];
        }
    },

    // Run on page load.
    "onload": function () {

        // Initialize the video.
        if (!me.video.init(640, 480, {wrapper: "screen", scale: "auto"})) {
            alert("Your browser does not support HTML5 canvas.");
            return;
        }

        // add "#debug" to the URL to enable the debug Panel
        if (me.game.HASH.debug === true) {
            window.onReady(function () {
                me.plugin.register.defer(this, me.debug.Panel, "debug", me.input.KEY.V);
            });
        }

        // Initialize the audio.
        me.audio.init("mp3,ogg");
        me.audio.disable();

        // Set a callback to run when loading is complete.
        me.loader.onload = this.loaded.bind(this);

        // Load the resources.
        me.loader.preload(game.resources);

        // Initialize melonJS and display a loading screen.
        me.state.change(me.state.LOADING);
    },

    // Run on game resources loaded.

    "loaded": function () {
        //   me.state.set(me.state.MENU, new game.TitleScreen());
        me.state.set(me.state.READY, new game.MainScreen());

        // set the "Play/Ingame" Screen Object
        me.state.set(me.state.MENU, new game.TitleScreen());
        me.state.set(me.state.PLAY, new game.PlayScreen());

        // set a global fading transition for the screen
        me.state.transition("fade", "#FFFFFF", 250);

        // register our player entity in the object pool
        me.pool.register("mainPlayer", game.PlayerEntity);
        me.pool.register("networkPlayer", game.NetworkPlayer);

        // me.pool.register("ingredientEntity", game.IngredientEntity);
        //me.pool.register("opponentEntity", game.OpponentEntity); // TODO use a playerEntity

        // enable the keyboard
        me.input.bindKey(me.input.KEY.LEFT, "left");
        me.input.bindKey(me.input.KEY.RIGHT, "right");
        me.input.bindKey(me.input.KEY.UP, "up");
        me.input.bindKey(me.input.KEY.DOWN, "down");
        me.input.bindKey(me.input.KEY.X, "dance");
        me.input.bindKey(me.input.KEY.SPACE, "carry", true);

        // start the game
        me.state.change(me.state.READY);
    }
};
<|endoftext|>


<commit_before>define(['app'], function() {

    return {

        app: null,
        ctx: null,
        ROW_COUNT: 5,
        MAX_ROW_COUNT: 7,
        COL_COUNT: 27,
        BRICKWIDTH: 0,
        BRICKHEIGHT: 18,
        PADDING: 1,
        bricks: [],
        drawIntervalId: null,
        addRowIntervalId: null,
        ballRadius: 9,
        rowcolors: ["#f2665e", "#fcb040", "#6ac071", "#57cbf5", "#f2665e"],
        paddlecolor: "#656565",
        ballcolor: "#f2665e",
        backcolor: "#f4f0ed",
        paddlePosition: {
            x: 0,
            y: 0
        },
        ballPosition: {
            x: 25,
            y: 250,
        },
        ballSpeed: {
            x: 1.5,
            y: -4,
        },
        // Used to calculate where the ball is going/what it's hitting
        tempBallPosition: {
            x: 0,
            y: 0,
        },

        init: function(app) {
            this.app = app;
            this.app.init();
            this.ctx = this.app.ctx;
            drawIntervalId = setInterval($.proxy(function() {
                this.draw();
            }, this), 10);
            this.BRICKWIDTH = (this.app.WIDTH / this.COL_COUNT) - 1;
            this.initBricks();
            this.startAddRowInterval();
            this.addListeners();
        },

        addListeners: function() {
            $(window).on('game.over', function() {
                console.log('Game over man, game over');
                clearInterval(drawIntervalId);
            });
        },

        draw: function() {
            this.ctx.fillStyle = this.backcolor;
            this.clear();
            this.ctx.fillStyle = this.ballcolor;
            this.circle(this.ballPosition.x, this.ballPosition.y, this.ballRadius);

            this.paddlePosition = {
                x: this.app.paddlex + this.app.PADDLE_POSITION_OFFSET.x,
                y: this.app.HEIGHT - this.app.paddleh + this.app.PADDLE_POSITION_OFFSET.y
            };

            this.tempBallPosition = {
                x: this.ballPosition.x + this.ballSpeed.x,
                y: this.ballPosition.y + this.ballSpeed.y
            };

            this.drawPaddle();
            this.drawBricks();
            this.updateBricks();

            if (this.isBallOutOfBounds()) {
                $(window).trigger('player.died');
                return this.restart();
            }

            // If the ball has hit the wall
            if (this.hasBallHitWall()) {
                this.ballSpeed.x *= -1;
            }

            if (this.isBallNearPaddle()) {
                // Ball has hit paddle
                if (this.hasBallHitPaddle()) {
                    //move the ball differently based on where it hit the paddle
                    this.ballSpeed.x = 8 * ((this.ballPosition.x - (this.app.paddlex + this.app.paddlew / 2)) / this.app.paddlew);
                    this.ballSpeed.y *= -1;
                }
            } else if (this.hasBallHitTop()) {
                this.ballSpeed.y *= -1;
            }

            this.ballPosition = this.tempBallPosition;
        },

        restart: function() {
            this.ballPosition = {
                x: 25,
                y: 250,
            };
            this.ballSpeed = {
                x: 1.5,
                y: -4,
            };
        },

        initBricks: function() {
            for(var i=0; i < this.ROW_COUNT; i++) {
                this.addRow();
            }
        },

        addRow: function() {
            // Prepend row
            this.bricks.unshift(this.createRow());
        },

        createRow: function() {
            var row = [];
            for(var i=0; i < this.COL_COUNT; i++) {
                row[i] = 1;
            }
            return row;
        },

        startAddRowInterval: function() {
            this.addRowIntervalId = setInterval($.proxy(function() {
                if (this.bricks.length < this.MAX_ROW_COUNT) {
                    this.addRow();
                }
            }, this), 5000);
        },

        drawBricks: function() {
            var rowCount = this.bricks.length;
            for(var i=0; i < rowCount; i++) {
                var row = this.bricks[i];

                this.ctx.fillStyle = this.rowcolors[i];

                var colCount = row.length;
                for(var j=0; j < colCount; j++) {
                    if (row[j] == 1) {
                        this.rect((j * (this.BRICKWIDTH + this.PADDING)) + this.PADDING,
                                (i * (this.BRICKHEIGHT + this.PADDING)) + this.PADDING,
                                this.BRICKWIDTH, this.BRICKHEIGHT);
                    }
                }
            }
        },

        updateBricks: function() {
            //want to learn about real collision detection? go read
            // http://www.harveycartel.org/metanet/tutorials/tutorialA.html
            var rowheight = this.BRICKHEIGHT + this.PADDING;
            var colwidth = this.BRICKWIDTH + this.PADDING;
            var row = Math.floor(this.ballPosition.y / rowheight);
            var col = Math.floor(this.ballPosition.x / colwidth);
            var rowCount = this.bricks.length
            //reverse the ball and mark the brick as broken
            if (this.ballPosition.y < rowCount * rowheight && row >= 0 && col >= 0 && this.bricks[row][col] == 1) {
                this.ballSpeed.y *= -1;
                this.bricks[row][col] = 0;
                if (!this.isRowActive(this.bricks[row])) {
                    this.bricks.splice(row, 1);
                }
                $(window).trigger('brick.destroyed');
            }
        },

        isRowActive: function(row) {
            var isRowActive = false;
            var rowLength = row.length;
            for (var i=0; i < rowLength; i++) {
                var col = row[i];
                if (col == 1) {
                    isRowActive = true;
                    break;
                }
            };

            return isRowActive;
        },

        drawPaddle: function() {

            // Move paddle
            if (this.app.rightDown && this.canPaddleMoveRight()) {
                this.app.paddlex += 5;
            } else if (this.app.leftDown && this.canPaddleMoveLeft()) {
                this.app.paddlex -= 5;
            }
            this.ctx.fillStyle = this.paddlecolor;

            // Draw paddle
            this.rect(this.paddlePosition.x, this.paddlePosition.y, this.app.paddlew, this.app.paddleh);
        },

        canPaddleMoveLeft: function() {
            return (this.paddlePosition.x > 0);
        },

        canPaddleMoveRight: function() {
            return (this.paddlePosition.x + this.app.paddlew < this.app.WIDTH);
        },

        hasBallHitWall: function() {
            return (this.tempBallPosition.x + this.ballRadius > this.app.WIDTH
                    || this.tempBallPosition.x - this.ballRadius < 0);
        },

        hasBallHitTop: function() {
            return (this.ballPosition.y + this.ballSpeed.y - this.ballRadius < 0);
        },

        /**
         * Is the ball about to hit the paddle. Check whether the ball is currently hittable
         * or whether it's too late/early
         */
        isBallNearPaddle: function() {
            return (this.tempBallPosition.y + this.ballRadius >= this.app.HEIGHT - this.app.paddleh + this.app.PADDLE_POSITION_OFFSET.y);
        },

        hasBallHitPaddle: function() {
            return (this.ballPosition.x > this.paddlePosition.x && this.ballPosition.x < this.paddlePosition.x + this.app.paddlew);
        },

        isBallOutOfBounds: function() {
            return (this.tempBallPosition.y + this.ballRadius >= this.app.HEIGHT);
        },

        circle: function(x,y,r) {
            this.ctx.beginPath();
            this.ctx.arc(x, y, r, 0, Math.PI*2, true);
            this.ctx.closePath();
            this.ctx.fill();
        },

        rect: function(x,y,w,h) {
            this.ctx.beginPath();
            this.ctx.rect(x, y, w, h);
            this.ctx.closePath();
            this.ctx.fill();
        },

        clear: function() {
            this.ctx.clearRect(0, 0, this.app.WIDTH, this.app.HEIGHT);
            this.rect(0, 0, this.app.WIDTH, this.app.HEIGHT);
        }
    }
});
<commit_msg>Moved brick drawing logic to its own method<commit_after>define(['app'], function() {

    return {

        app: null,
        ctx: null,
        ROW_COUNT: 5,
        MAX_ROW_COUNT: 7,
        COL_COUNT: 27,
        BRICKWIDTH: 0,
        BRICKHEIGHT: 18,
        PADDING: 1,
        bricks: [],
        drawIntervalId: null,
        addRowIntervalId: null,
        ballRadius: 9,
        rowcolors: ["#f2665e", "#fcb040", "#6ac071", "#57cbf5", "#f2665e"],
        paddlecolor: "#656565",
        ballcolor: "#f2665e",
        backcolor: "#f4f0ed",
        paddlePosition: {
            x: 0,
            y: 0
        },
        ballPosition: {
            x: 25,
            y: 250,
        },
        ballSpeed: {
            x: 1.5,
            y: -4,
        },
        // Used to calculate where the ball is going/what it's hitting
        tempBallPosition: {
            x: 0,
            y: 0,
        },

        init: function(app) {
            this.app = app;
            this.app.init();
            this.ctx = this.app.ctx;
            drawIntervalId = setInterval($.proxy(function() {
                this.draw();
            }, this), 10);
            this.BRICKWIDTH = (this.app.WIDTH / this.COL_COUNT) - 1;
            this.initBricks();
            this.startAddRowInterval();
            this.addListeners();
        },

        addListeners: function() {
            $(window).on('game.over', function() {
                console.log('Game over man, game over');
                clearInterval(drawIntervalId);
            });
        },

        draw: function() {
            this.ctx.fillStyle = this.backcolor;
            this.clear();
            this.ctx.fillStyle = this.ballcolor;
            this.circle(this.ballPosition.x, this.ballPosition.y, this.ballRadius);

            this.paddlePosition = {
                x: this.app.paddlex + this.app.PADDLE_POSITION_OFFSET.x,
                y: this.app.HEIGHT - this.app.paddleh + this.app.PADDLE_POSITION_OFFSET.y
            };

            this.tempBallPosition = {
                x: this.ballPosition.x + this.ballSpeed.x,
                y: this.ballPosition.y + this.ballSpeed.y
            };

            this.drawPaddle();
            this.drawBricks();
            this.updateBricks();

            if (this.isBallOutOfBounds()) {
                $(window).trigger('player.died');
                return this.restart();
            }

            // If the ball has hit the wall
            if (this.hasBallHitWall()) {
                this.ballSpeed.x *= -1;
            }

            if (this.isBallNearPaddle()) {
                // Ball has hit paddle
                if (this.hasBallHitPaddle()) {
                    //move the ball differently based on where it hit the paddle
                    this.ballSpeed.x = 8 * ((this.ballPosition.x - (this.app.paddlex + this.app.paddlew / 2)) / this.app.paddlew);
                    this.ballSpeed.y *= -1;
                }
            } else if (this.hasBallHitTop()) {
                this.ballSpeed.y *= -1;
            }

            this.ballPosition = this.tempBallPosition;
        },

        restart: function() {
            this.ballPosition = {
                x: 25,
                y: 250,
            };
            this.ballSpeed = {
                x: 1.5,
                y: -4,
            };
        },

        initBricks: function() {
            for(var i=0; i < this.ROW_COUNT; i++) {
                this.addRow();
            }
        },

        addRow: function() {
            // Prepend row
            this.bricks.unshift(this.createRow());
        },

        createRow: function() {
            var row = [];
            for(var i=0; i < this.COL_COUNT; i++) {
                row[i] = 1;
            }
            return row;
        },

        startAddRowInterval: function() {
            this.addRowIntervalId = setInterval($.proxy(function() {
                if (this.bricks.length < this.MAX_ROW_COUNT) {
                    this.addRow();
                }
            }, this), 5000);
        },

        drawBricks: function() {
            var rowCount = this.bricks.length;
            for(var i=0; i < rowCount; i++) {
                var row = this.bricks[i];

                this.ctx.fillStyle = this.rowcolors[i];

                var colCount = row.length;
                for(var j=0; j < colCount; j++) {
                    if (row[j] == 1) {
                        this.drawBrickForRowAndColumn(i, j);
                    }
                }
            }
        },

        drawBrickForRowAndColumn: function(row, column) {
            var x = (column * (this.BRICKWIDTH + this.PADDING)) + this.PADDING;
            var y = (row * (this.BRICKHEIGHT + this.PADDING)) + this.PADDING;
            this.rect(x, y, this.BRICKWIDTH, this.BRICKHEIGHT);
        },

        updateBricks: function() {
            //want to learn about real collision detection? go read
            // http://www.harveycartel.org/metanet/tutorials/tutorialA.html
            var rowheight = this.BRICKHEIGHT + this.PADDING;
            var colwidth = this.BRICKWIDTH + this.PADDING;
            var row = Math.floor(this.ballPosition.y / rowheight);
            var col = Math.floor(this.ballPosition.x / colwidth);
            var rowCount = this.bricks.length
            //reverse the ball and mark the brick as broken
            if (this.ballPosition.y < rowCount * rowheight && row >= 0 && col >= 0 && this.bricks[row][col] == 1) {
                this.ballSpeed.y *= -1;
                this.bricks[row][col] = 0;
                if (!this.isRowActive(this.bricks[row])) {
                    this.bricks.splice(row, 1);
                }
                $(window).trigger('brick.destroyed');
            }
        },

        isRowActive: function(row) {
            var isRowActive = false;
            var rowLength = row.length;
            for (var i=0; i < rowLength; i++) {
                var col = row[i];
                if (col == 1) {
                    isRowActive = true;
                    break;
                }
            };

            return isRowActive;
        },

        drawPaddle: function() {

            // Move paddle
            if (this.app.rightDown && this.canPaddleMoveRight()) {
                this.app.paddlex += 5;
            } else if (this.app.leftDown && this.canPaddleMoveLeft()) {
                this.app.paddlex -= 5;
            }
            this.ctx.fillStyle = this.paddlecolor;

            // Draw paddle
            this.rect(this.paddlePosition.x, this.paddlePosition.y, this.app.paddlew, this.app.paddleh);
        },

        canPaddleMoveLeft: function() {
            return (this.paddlePosition.x > 0);
        },

        canPaddleMoveRight: function() {
            return (this.paddlePosition.x + this.app.paddlew < this.app.WIDTH);
        },

        hasBallHitWall: function() {
            return (this.tempBallPosition.x + this.ballRadius > this.app.WIDTH
                    || this.tempBallPosition.x - this.ballRadius < 0);
        },

        hasBallHitTop: function() {
            return (this.ballPosition.y + this.ballSpeed.y - this.ballRadius < 0);
        },

        /**
         * Is the ball about to hit the paddle. Check whether the ball is currently hittable
         * or whether it's too late/early
         */
        isBallNearPaddle: function() {
            return (this.tempBallPosition.y + this.ballRadius >= this.app.HEIGHT - this.app.paddleh + this.app.PADDLE_POSITION_OFFSET.y);
        },

        hasBallHitPaddle: function() {
            return (this.ballPosition.x > this.paddlePosition.x && this.ballPosition.x < this.paddlePosition.x + this.app.paddlew);
        },

        isBallOutOfBounds: function() {
            return (this.tempBallPosition.y + this.ballRadius >= this.app.HEIGHT);
        },

        circle: function(x,y,r) {
            this.ctx.beginPath();
            this.ctx.arc(x, y, r, 0, Math.PI * 2, true);
            this.ctx.closePath();
            this.ctx.fill();
        },

        rect: function(x,y,w,h) {
            this.ctx.beginPath();
            this.ctx.rect(x, y, w, h);
            this.ctx.closePath();
            this.ctx.fill();
        },

        clear: function() {
            this.ctx.clearRect(0, 0, this.app.WIDTH, this.app.HEIGHT);
            this.rect(0, 0, this.app.WIDTH, this.app.HEIGHT);
        }
    }
});
<|endoftext|>


<commit_before>import React, { Text, TextInput, View, Animated } from 'react-native'
import t from 'tcomb-form-native'

const Textbox = t.form.Textbox

class FloatingLabel extends Textbox {
  constructor (props) {
    super(props)
    this.state = {
      fieldFocused: (props.value) ? true : false,
      value: (props.value) ? String(props.value) : undefined,
      fadeAnim: (props.value) ? new Animated.Value(1) : new Animated.Value(0),
      placeholderString: undefined,
    }
  }

  getTemplate () {
    let self = this
    return function (locals) {
      const stylesheet = locals.stylesheet;
      let formGroupStyle = stylesheet.formGroup.normal;
      let controlLabelStyle = stylesheet.controlLabel.normal;
      let textboxStyle = stylesheet.textbox.normal;
      let helpBlockStyle = stylesheet.helpBlock.normal;
      let errorBlockStyle = stylesheet.errorBlock;

      if (locals.hasError) {
        controlLabelStyle = stylesheet.controlLabel.error;
        formGroupStyle = stylesheet.formGroup.error;
        textboxStyle = stylesheet.textbox.error;
        helpBlockStyle = stylesheet.helpBlock.error;
      }

      if (locals.editable === false) {
        textboxStyle = stylesheet.textbox.notEditable;
      }

      const help = locals.help ? <Text style={helpBlockStyle}>{locals.help}</Text> : null;
      const error = locals.hasError && locals.error ? <Text style={errorBlockStyle}>{locals.error}</Text> : null;
      const label =
        <Animated.Text style={[controlLabelStyle, {
          opacity: self.state.fadeAnim,
          transform: [{
            translateY: self.state.fadeAnim.interpolate({
              inputRange: [0, 1],
              outputRange: [10, 0]
            }),
          }]}]}>
          {locals.label}
        </Animated.Text>

      const placeholderString = (self.state.placeholderString !== undefined) ? self.state.placeholderString : locals.label
      return (
        <View style={formGroupStyle}>
          {label}
          <TextInput
            ref='input'
            autoCapitalize={locals.autoCapitalize}
            autoCorrect={locals.autoCorrect}
            autoFocus={locals.autoFocus}
            bufferDelay={locals.bufferDelay}
            clearButtonMode={locals.clearButtonMode}
            editable={locals.editable}
            enablesReturnKeyAutomatically={locals.enablesReturnKeyAutomatically}
            keyboardType={locals.keyboardType}
            multiline={locals.multiline}
            onBlur={self._onBlur.bind(self, locals)}
            onEndEditing={locals.onEndEditing}
            onFocus={self._onFocus.bind(self, locals)}
            onSubmitEditing={locals.onSubmitEditing}
            password={locals.password}
            placeholderTextColor={locals.placeholderTextColor}
            returnKeyType={locals.returnKeyType}
            selectTextOnFocus={locals.selectTextOnFocus}
            secureTextEntry={locals.secureTextEntry}
            selectionState={locals.selectionState}
            onChangeText={(value) => {
              locals.onChange(value)
              self._onChangeText.bind(self, value, locals)
            }}
            placeholder={placeholderString}
            maxLength={locals.maxLength}
            numberOfLines={locals.numberOfLines}
            textAlign={locals.textAlign}
            textAlignVertical={locals.textAlignVertical}
            underlineColorAndroid={locals.underlineColorAndroid}
            style={[styles.textInput, textboxStyle]}
            value={locals.value}
          />
          {help}
          {error}
        </View>
      )
    }
  }

  _onChangeText (text, locals) {
    this.setState({value: text})
  }

  _onFocus (locals) {
    Animated.spring(
      this.state.fadeAnim,
      {toValue: 1, friction: 5},
    ).start()
    this.setState({
      fieldFocused: true,
      placeholderString: '',
    })
    if (locals.onFocus) {
      locals.onFocus()
    }
  }

  _onBlur (locals) {
    if (!this.state.value) {
      Animated.timing(
        this.state.fadeAnim,
        {toValue: 0},
      ).start()
    }
    this.setState({
      fieldFocused: false,
      placeholderString: locals.label
    })
    if (locals.onBlur) {
      locals.onBlur()
    }
  }

  shouldComponentUpdate (nextProps, nextState) {
    return true
  }
}

const styles = React.StyleSheet.create({
  textInput: {
    height: 40,
  }
})

export default FloatingLabel
<commit_msg>Added focus when tapping the label<commit_after>import React, {
  Text,
  TextInput,
  View,
  Animated,
  TouchableWithoutFeedback,
} from 'react-native'
import t from 'tcomb-form-native'

const Textbox = t.form.Textbox

class FloatingLabel extends Textbox {
  constructor (props) {
    super(props)
    this.state = {
      fieldFocused: (props.value) ? true : false,
      value: (props.value) ? String(props.value) : undefined,
      fadeAnim: (props.value) ? new Animated.Value(1) : new Animated.Value(0),
      placeholderString: undefined,
    }
  }

  getTemplate () {
    let self = this
    return function (locals) {
      const stylesheet = locals.stylesheet;
      let formGroupStyle = stylesheet.formGroup.normal;
      let controlLabelStyle = stylesheet.controlLabel.normal;
      let textboxStyle = stylesheet.textbox.normal;
      let helpBlockStyle = stylesheet.helpBlock.normal;
      let errorBlockStyle = stylesheet.errorBlock;

      if (locals.hasError) {
        controlLabelStyle = stylesheet.controlLabel.error;
        formGroupStyle = stylesheet.formGroup.error;
        textboxStyle = stylesheet.textbox.error;
        helpBlockStyle = stylesheet.helpBlock.error;
      }

      if (locals.editable === false) {
        textboxStyle = stylesheet.textbox.notEditable;
      }
      const help = locals.help ? <Text style={helpBlockStyle}>{locals.help}</Text> : null;
      const error = locals.hasError && locals.error ? <Text style={errorBlockStyle}>{locals.error}</Text> : null;
      const label =
        <Animated.Text style={[controlLabelStyle, {
          opacity: self.state.fadeAnim,
          transform: [{
            translateY: self.state.fadeAnim.interpolate({
              inputRange: [0, 1],
              outputRange: [10, 0]
            }),
          }]}]}>
          {locals.label}
        </Animated.Text>

      const placeholderString = (self.state.placeholderString !== undefined) ? self.state.placeholderString : locals.label
      return (
        <TouchableWithoutFeedback onPress={() => self.refs.input.focus()}>
          <View style={formGroupStyle}>
            {label}
            <TextInput
              ref='input'
              autoCapitalize={locals.autoCapitalize}
              autoCorrect={locals.autoCorrect}
              autoFocus={locals.autoFocus}
              bufferDelay={locals.bufferDelay}
              clearButtonMode={locals.clearButtonMode}
              editable={locals.editable}
              enablesReturnKeyAutomatically={locals.enablesReturnKeyAutomatically}
              keyboardType={locals.keyboardType}
              multiline={locals.multiline}
              onBlur={self._onBlur.bind(self, locals)}
              onEndEditing={locals.onEndEditing}
              onFocus={self._onFocus.bind(self, locals)}
              onSubmitEditing={locals.onSubmitEditing}
              password={locals.password}
              placeholderTextColor={locals.placeholderTextColor}
              returnKeyType={locals.returnKeyType}
              selectTextOnFocus={locals.selectTextOnFocus}
              secureTextEntry={locals.secureTextEntry}
              selectionState={locals.selectionState}
              onChangeText={(value) => {
                locals.onChange(value)
                self._onChangeText.bind(self, value, locals)
              }}
              placeholder={placeholderString}
              maxLength={locals.maxLength}
              numberOfLines={locals.numberOfLines}
              textAlign={locals.textAlign}
              textAlignVertical={locals.textAlignVertical}
              underlineColorAndroid={locals.underlineColorAndroid}
              style={[styles.textInput, textboxStyle]}
              value={locals.value}
            />
            {help}
            {error}
          </View>
        </TouchableWithoutFeedback>
      )
    }
  }

  _onChangeText (text, locals) {
    this.setState({value: text})
  }

  _onFocus (locals) {
    Animated.spring(
      this.state.fadeAnim,
      {toValue: 1, friction: 5},
    ).start()
    this.setState({
      fieldFocused: true,
      placeholderString: '',
    })
    if (locals.onFocus) {
      locals.onFocus()
    }
  }

  _onBlur (locals) {
    if (!this.state.value) {
      Animated.timing(
        this.state.fadeAnim,
        {toValue: 0},
      ).start()
    }
    this.setState({
      fieldFocused: false,
      placeholderString: locals.label
    })
    if (locals.onBlur) {
      locals.onBlur()
    }
  }

  shouldComponentUpdate (nextProps, nextState) {
    return true
  }
}

const styles = React.StyleSheet.create({
  textInput: {
    height: 40,
  }
})

export default FloatingLabel
<|endoftext|>


<commit_before>function Game(startBoard) = {
  this.completed = false;
  this.board = makeBoard(startBoard);
};

Game.prototype.makeBoard = function(stringBoard){
  if (stringBoard.length !== 16){
    alert("Starting boards must be 16 digits long, you silly hobbit!");
    return false
  } else {
    var board = [];
    for (var i = 0; i < stringBoard.length; i+=4) {
      var array = [];
      for (var j = i; j < i+4; j++) {
      array.push(parseInt(stringBoard[j]));
      }
    board.push(array);
    }
  }
  return board;
};

// Game.prototype.toString = function(){

// };
<commit_msg>Creates to String method for Game objects with new lines<commit_after>var Game = function(startBoard) {
  this.completed = false;
  this.startBoard = startBoard;
  this.board = this.makeBoard(startBoard);
};

Game.prototype.makeBoard = function(stringBoard){
  if (stringBoard.length !== 16){
    alert("Starting boards must be 16 digits long, you silly hobbit!");
    return false
  } else {
    var board = [];
    for (var i = 0; i < stringBoard.length; i+=4) {
      var array = [];
      for (var j = i; j < i+4; j++) {
      array.push(parseInt(stringBoard[j]));
      }
    board.push(array);
    }
  }
  return board;
};

Game.prototype.toString = function(){
  // var boardString = this.board.toString().replace(/,/g, "");
  var boardString = this.board;
  for (var i = 0; i < boardString.length; i++) {
    boardString[i].push("\n");
  };
  console.log(boardString.join("").replace(/,/g, ""));
};
<|endoftext|>


<commit_before>
//BONUS LEVEL
//ENORME TODO
function loadBonusLevel(lvl) {
   music.stop();
   if(!mute && !in_bonus_level) {
      music_bonus.play();
   }
   in_bonus_level = true;

   text_middle.text = "Niveau bonus !";
   text_level.text = "YAY ! (il est en travaux btw)";
   //text_level.text = level_names_en[lvl];
   text_middle.alpha = 0;
   text_level.alpha = 0;

   game.add.tween(text_middle).to( { alpha: 1 }, 1000, Phaser.Easing.Quadratic.In, true);
   game.add.tween(text_level).to( { alpha: 1 }, 1000, Phaser.Easing.Quadratic.In, true);

   speed = START_SPEED;
   speedup = SPEEDUP_INIT;
   accel = SPEEDUP_ACCEL;
   /*timer = new Phaser.Timer(game, false);
   timer.add(Phaser.Timer.SECOND*2, createEnemies(levels[lvl]), this);
   timer.start(2000);
   */
   window.setTimeout(function(){
      game.add.tween(text_middle).to( { alpha: 0 }, 1000, Phaser.Easing.Quadratic.Out, true);
      game.add.tween(text_level) .to( { alpha: 0 }, 1000, Phaser.Easing.Quadratic.Out, true);
      //createEnemies(levels[lvl]);
   }, 3000);
   createEnemies(bonus_levels[lvl]);
}
<commit_msg>delete this shit<commit_after><|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2020 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'com.foamdev.demos.maze',
  name: 'Question1',
  properties: [
    {
      name: 'question',
      label: 'Who was the best Star Wars robot?',
      view: {
        class: 'foam.u2.view.RadioView',
        placeholder: 'Please select',
        choices: [
          'C3-PO',
          'R2-D2',
          'BB-8',
          'K-2SO'
        ]
      }
    },
    {
      name: 'answer',
      hidden: true,
      value: 'R2-D2'
    }
  ]
});

foam.CLASS({
  package: 'com.foamdev.demos.maze',
  name: 'Question2',
  properties: [
    {
      name: 'question',
      label: 'Which of the following do robots make',
      view: {
        class: 'foam.u2.view.RadioView',
        placeholder: 'Please select',
        choices: [
          'Cars',
          'Washing Machines',
          'Computers',
          'Robots',
          'All of the Above'

        ]
      }
    },
    {
      name: 'answer',
      hidden: true,
      value: 'All of the Above'
    }
  ]
});

foam.CLASS({
  package: 'com.foamdev.demos.maze',
  name: 'Door',
  extends: 'foam.graphics.Box',
  properties: [
    [ 'color', 'red' ],
    [ 'isClosed', true ]
  ],
  methods: [
    function open() {
      this.isClosed = false;
      this.rotation = Math.PI / 4;
//      this.width = this.height = 0;
    }
  ]
});

foam.CLASS({
  package: 'com.foamdev.demos.maze',
  name: 'Wall',
  extends: 'foam.graphics.Box',
  properties: [
    [ 'color', 'gray' ]
  ]
});

foam.CLASS({
  package: 'com.foamdev.demos.maze',
  name: 'Exit',
  extends: 'foam.graphics.Box',
  properties: [
    [ 'color', 'blue' ]
  ]
});

foam.CLASS({
  package: 'com.foamdev.demos.maze',
  name: 'Laser',
  extends: 'foam.graphics.Circle',

  requires: [ 'foam.animation.Animation' ],
  imports: [ 'game'],

  properties: [
    [ 'color', 'yellow' ],
    [ 'radius', 8 ],
    'vx',
    'vy'
  ],

  methods: [
    function init() {
      this.SUPER();

      this.game.addChild(this);
      this.Animation.create({
        duration: 5000,
        f: () => {
          this.x += 2000 * this.vx;
          this.y += 2000 * this.vy;
        },
        onEnd: () => this.game.removeChild(this),
        objs: [ this ]
      }).start();
    }
  ]
});

foam.CLASS({
  package: 'com.foamdev.demos.maze',
  name: 'Game',
  extends: 'foam.u2.Element',

  requires: [
    'com.foamdev.demos.maze.Door',
    'com.foamdev.demos.maze.Exit',
    'com.foamdev.demos.maze.Laser',
    'com.foamdev.demos.maze.Question1',
    'com.foamdev.demos.maze.Question2',
    'com.foamdev.demos.maze.Wall',
    'com.google.foam.demos.robot.Robot',
    'foam.animation.Animation',
    'foam.audio.Speak',
    'foam.graphics.Box as Rectangle',
    'foam.graphics.CView',
    'foam.graphics.Label',
    'foam.input.Gamepad',
    'foam.physics.Collider',
    'foam.util.Timer'
  ],

  exports: [
    'timer',
    'as game'
  ],

  constants: {
    BRICK_SIZE: 40,
    MAZE_HORIZ: [
      ['Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall'],
      ['Wall', null, null, 'Wall', null, 'Wall', null, null, 'Wall'],
      [null, 'Door', null, null, null, null, null, 'Wall', null, 'Wall', 'Wall'],
      [null, 'Wall', 'Wall', null, 'Wall', 'Wall', 'Wall', null, 'Wall', 'Wall', null],
      [null, null, 'Wall', 'Wall', 'Wall', null, 'Wall', 'Wall', null, 'Wall', 'Wall'],
      [null, null, 'Door', 'Wall', null, 'Door', null, null, null, 'Wall'],
      ['Wall', 'Door', null, 'Wall', null, null, null, null, 'Wall', null, 'Wall'],
      ['Wall', 'Wall', null, 'Wall', 'Wall', null, null, 'Door', null, 'Wall'],
      ['Wall', null, 'Wall', 'Wall', null, 'Wall', null, null, 'Wall', null, 'Wall'],
      [null, null, 'Wall', null, 'Wall', null, 'Wall', null, null, 'Wall', 'Wall'],
      [null, 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', null, 'Wall', null, 'Wall'],
      ['Door', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall']
    ],
    MAZE_VERT: [
      ['Wall', null, 'Wall', null, null, 'Wall', 'Wall', 'Wall', null, null, 'Wall', 'Exit'],
      ['Wall', 'Wall', 'Wall', 'Wall', 'Wall', null, 'Wall', 'Wall', null, 'Wall', null, 'Wall'],
      ['Wall', null, null, 'Wall', null, 'Wall', null, null, 'Wall', null, null, 'Wall'],
      ['Wall', 'Wall', null, null, null, null, null, 'Wall', null, null, null, 'Wall'],
      ['Wall', 'Wall', 'Wall', null, null, 'Wall', null, null, 'Wall', 'Wall', null, 'Wall'],
      ['Wall', 'Wall', null, null, 'Wall', null, 'Wall', 'Wall', 'Wall', null, 'Wall', 'Wall'],
      ['Wall', null, null, 'Wall', null, 'Door', 'Wall', 'Wall', null, 'Wall', null, 'Wall'],
      ['Wall', null, 'Wall', null, null, null, 'Wall', 'Wall', 'Wall', null, 'Wall', 'Wall'],
      ['Wall', 'Wall', null, null, 'Wall', 'Wall', null, 'Wall', 'Wall', null, null, 'Wall'],
      ['Wall', 'Wall', null, 'Wall', null, null, null, 'Wall', null, 'Wall', null, 'Wall'],
      ['Wall', null, null, null, null, null, null, null, 'Wall', null, false, 'Wall']
    ]
   },

  properties: [
    [ 'isGameOver', false ],
    [ 'width', 1600 ],
    [ 'height', 800 ],
    {
      name: 'gamepad',
      factory: function() { return this.Gamepad.create(); }
    },
    {
      name: 'timer',
      factory: function() { return this.Timer.create(); }
    },
    {
      name: 'table',
      factory: function() {
        return this.Rectangle.create({
          color: 'black',
          scaleX: 1.8,
          scaleY: 1.8,
          width: 500, // window.innerWidth,
          height: 500 // window.innerHeight
        });
      }
    },
    {
      name: 'robot',
      factory: function() {
        return this.Robot.create({x:37.5, y:435, scaleX: 0.5, scaleY: 0.5, width: 3, height: 3});
      }
    },
    {
      name: 'collider',
      factory: function() { return this.Collider.create(); }
    },
    'lastX', 'lastY', 'hittingWall',
    'questionArea'
  ],

  methods: [
    function init() {
      this.SUPER();

      this.buildMaze();
      this.addChild(this.robot);

      this.gamepad.pressed.sub('button4', () => this.fire());
      this.gamepad.pressed.sub('button5', () => this.fire());

      // Setup Physics
      this.collider.collide = function(o1, o2) {
        if ( o2 == this.robot ) {
          o2 = o1;
          o1 = this.robot;
        }
        if ( o1 == this.robot ) {
          if ( this.Door.isInstance(o2) ) {
            if ( ! o2.isClosed ) return;
            console.log('*************************** Door');
            o2.open();
            this.hittingWall = true;
            this.questionArea.removeAllChildren();
            this.questionArea.add(this.Question1.create());
          } else if ( this.Wall.isInstance(o2) ) {
            console.log('*************************** Wall');
            this.hittingWall = true;
          } else if ( this.Exit.isInstance(o2) ) {
            this.gameOver();
          }
        }
      }.bind(this);
      this.collider.start();
      this.timer.i$.sub(this.tick);
      this.timer.start();
    },

    function buildMaze() {
      var m = this.MAZE_HORIZ;

      // draw horizontal lines
      for ( var row = 0 ; row < m.length ; row++ ) {
        var rowdata = m[row];
        for ( var col = 0 ; col < rowdata.length ; col++ ) {
          if ( rowdata[col] ) {
            var blockType = this[rowdata[col]];
            this.addChild(blockType.create({
              x: this.BRICK_SIZE/2 + col*this.BRICK_SIZE,
              y: this.BRICK_SIZE/2 + row*this.BRICK_SIZE,
              width: this.BRICK_SIZE,
              height: 5
            }));
          }
        }
      }

      // draw vertical lines
      m = this.MAZE_VERT;
      for ( var row = 0 ; row < m.length ; row++ ) {
        var rowdata = m[row];
        for ( var col = 0 ; col < rowdata.length ; col++ ) {
          if ( rowdata[col] ) {
            var blockType = this[rowdata[col]];
            this.addChild(blockType.create({
              x: this.BRICK_SIZE/2 + col*this.BRICK_SIZE,
              y: this.BRICK_SIZE/2 + row*this.BRICK_SIZE,
              width: 5,
              height: this.BRICK_SIZE
            }));
          }
        }
      }

    },

    function initE() {
      this.SUPER();
      this.focus();
      this.style({display:'flex'}).add(this.table).add(' ').tag(null, null, this.questionArea$);
    },

    function gameOver() {
      if ( this.isGameOver ) return;
      this.isGameOver = true;

      this.table.color = 'white';

      var label = this.Label.create({
        text: 'You Win!',
        align: 'center',
        color: 'red',
        x: this.table.width/2,
        y: 180
      });
      this.addChild(label);

      this.Animation.create({
        duration: 2000,
        f: ()=> { label.scaleX = label.scaleY = 10; label.rotation = 2 * Math.PI; },
        objs: [label]
      }).start();

      this.Speak.create({text: "You Win! You're so smart! You're a JavaScript master!"}).play();
    },

    function addChild(c) {
      this.table.add(c);
      if ( c.intersects ) this.collider.add(c);
    },

    function removeChild(c) {
      this.table.remove(c);
      if ( c.intersects ) this.collider.remove(c);
    }
  ],

  listeners: [
    {
      name: 'tick',
      code: function() {
        if ( this.hittingWall ) {
          this.robot.x = this.lastX;
          this.robot.y = this.lastY;
          this.hittingWall = false;
        } else {
          this.lastX = this.robot.x;
          this.lastY = this.robot.y;
        }

        if ( this.gamepad.button0 ) this.up();
        if ( this.gamepad.button1 ) this.right();
        if ( this.gamepad.button2 ) this.down();
        if ( this.gamepad.button3 ) this.left();
      }
    }
  ],

  actions: [
    {
      name: 'up',
      keyboardShortcuts: [ 38 /* up arrow */, 'w' ],
      code: function() { this.robot.y -= 3; }
    },
    {
      name: 'down',
      keyboardShortcuts: [ 40 /* down arrow */, 's' ],
      code: function() { this.robot.y += 3; }
    },
    {
      name: 'left',
      keyboardShortcuts: [ 37 /* left arrow */, 'a' ],
      code: function() { this.robot.x -= 3; }
    },
    {
      name: 'right',
      keyboardShortcuts: [ 39 /* right arrow */, 'd' ],
      code: function() { this.robot.x += 3; }
    },
    {
      name: 'fire',
      keyboardShortcuts: [ ' ', 'x' ],
      code: function() {
        this.Laser.create({x: this.robot.x, y: this.robot.y, vx: 1, vy: 0});
        this.Laser.create({x: this.robot.x, y: this.robot.y, vx: 0, vy: 1});
        this.Laser.create({x: this.robot.x, y: this.robot.y, vx: -1, vy: 0});
        this.Laser.create({x: this.robot.x, y: this.robot.y, vx: 0, vy: -1});
      }
    }
  ]
});
<commit_msg>Animate opening of doors in Maze game.<commit_after>/**
 * @license
 * Copyright 2020 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'com.foamdev.demos.maze',
  name: 'Question1',
  properties: [
    {
      name: 'question',
      label: 'Who was the best Star Wars robot?',
      view: {
        class: 'foam.u2.view.RadioView',
        placeholder: 'Please select',
        choices: [
          'C3-PO',
          'R2-D2',
          'BB-8',
          'K-2SO'
        ]
      }
    },
    {
      name: 'answer',
      hidden: true,
      value: 'R2-D2'
    }
  ]
});

foam.CLASS({
  package: 'com.foamdev.demos.maze',
  name: 'Question2',
  properties: [
    {
      name: 'question',
      label: 'Which of the following do robots make',
      view: {
        class: 'foam.u2.view.RadioView',
        placeholder: 'Please select',
        choices: [
          'Cars',
          'Washing Machines',
          'Computers',
          'Robots',
          'All of the Above'

        ]
      }
    },
    {
      name: 'answer',
      hidden: true,
      value: 'All of the Above'
    }
  ]
});

foam.CLASS({
  package: 'com.foamdev.demos.maze',
  name: 'Door',
  extends: 'foam.graphics.Box',

  requires: [ 'foam.animation.Animation' ],

  properties: [
    [ 'color', 'red' ],
    [ 'isClosed', true ]
  ],

  methods: [
    function open() {
      this.isClosed = false;
      this.Animation.create({
        duration: 300,
        f: () => this.rotation = Math.PI /4,
        objs: [ this ]
      }).start();
    }
  ]
});

foam.CLASS({
  package: 'com.foamdev.demos.maze',
  name: 'Wall',
  extends: 'foam.graphics.Box',
  properties: [
    [ 'color', 'gray' ]
  ]
});

foam.CLASS({
  package: 'com.foamdev.demos.maze',
  name: 'Exit',
  extends: 'foam.graphics.Box',
  properties: [
    [ 'color', 'blue' ]
  ]
});

foam.CLASS({
  package: 'com.foamdev.demos.maze',
  name: 'Laser',
  extends: 'foam.graphics.Circle',

  requires: [ 'foam.animation.Animation' ],
  imports: [ 'game'],

  properties: [
    [ 'color', 'yellow' ],
    [ 'radius', 8 ],
    'vx',
    'vy'
  ],

  methods: [
    function init() {
      this.SUPER();

      this.game.addChild(this);
      this.Animation.create({
        duration: 5000,
        f: () => {
          this.x += 2000 * this.vx;
          this.y += 2000 * this.vy;
        },
        onEnd: () => this.game.removeChild(this),
        objs: [ this ]
      }).start();
    }
  ]
});

foam.CLASS({
  package: 'com.foamdev.demos.maze',
  name: 'Game',
  extends: 'foam.u2.Element',

  requires: [
    'com.foamdev.demos.maze.Door',
    'com.foamdev.demos.maze.Exit',
    'com.foamdev.demos.maze.Laser',
    'com.foamdev.demos.maze.Question1',
    'com.foamdev.demos.maze.Question2',
    'com.foamdev.demos.maze.Wall',
    'com.google.foam.demos.robot.Robot',
    'foam.animation.Animation',
    'foam.audio.Speak',
    'foam.graphics.Box as Rectangle',
    'foam.graphics.CView',
    'foam.graphics.Label',
    'foam.input.Gamepad',
    'foam.physics.Collider',
    'foam.util.Timer'
  ],

  exports: [
    'timer',
    'as game'
  ],

  constants: {
    BRICK_SIZE: 40,
    MAZE_HORIZ: [
      ['Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall'],
      ['Wall', null, null, 'Wall', null, 'Wall', null, null, 'Wall'],
      [null, 'Door', null, null, null, null, null, 'Wall', null, 'Wall', 'Wall'],
      [null, 'Wall', 'Wall', null, 'Wall', 'Wall', 'Wall', null, 'Wall', 'Wall', null],
      [null, null, 'Wall', 'Wall', 'Wall', null, 'Wall', 'Wall', null, 'Wall', 'Wall'],
      [null, null, 'Door', 'Wall', null, 'Door', null, null, null, 'Wall'],
      ['Wall', 'Door', null, 'Wall', null, null, null, null, 'Wall', null, 'Wall'],
      ['Wall', 'Wall', null, 'Wall', 'Wall', null, null, 'Door', null, 'Wall'],
      ['Wall', null, 'Wall', 'Wall', null, 'Wall', null, null, 'Wall', null, 'Wall'],
      [null, null, 'Wall', null, 'Wall', null, 'Wall', null, null, 'Wall', 'Wall'],
      [null, 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', null, 'Wall', null, 'Wall'],
      ['Door', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall', 'Wall']
    ],
    MAZE_VERT: [
      ['Wall', null, 'Wall', null, null, 'Wall', 'Wall', 'Wall', null, null, 'Wall', 'Exit'],
      ['Wall', 'Wall', 'Wall', 'Wall', 'Wall', null, 'Wall', 'Wall', null, 'Wall', null, 'Wall'],
      ['Wall', null, null, 'Wall', null, 'Wall', null, null, 'Wall', null, null, 'Wall'],
      ['Wall', 'Wall', null, null, null, null, null, 'Wall', null, null, null, 'Wall'],
      ['Wall', 'Wall', 'Wall', null, null, 'Wall', null, null, 'Wall', 'Wall', null, 'Wall'],
      ['Wall', 'Wall', null, null, 'Wall', null, 'Wall', 'Wall', 'Wall', null, 'Wall', 'Wall'],
      ['Wall', null, null, 'Wall', null, 'Door', 'Wall', 'Wall', null, 'Wall', null, 'Wall'],
      ['Wall', null, 'Wall', null, null, null, 'Wall', 'Wall', 'Wall', null, 'Wall', 'Wall'],
      ['Wall', 'Wall', null, null, 'Wall', 'Wall', null, 'Wall', 'Wall', null, null, 'Wall'],
      ['Wall', 'Wall', null, 'Wall', null, null, null, 'Wall', null, 'Wall', null, 'Wall'],
      ['Wall', null, null, null, null, null, null, null, 'Wall', null, false, 'Wall']
    ]
   },

  properties: [
    [ 'isGameOver', false ],
    [ 'width', 1600 ],
    [ 'height', 800 ],
    {
      name: 'gamepad',
      factory: function() { return this.Gamepad.create(); }
    },
    {
      name: 'timer',
      factory: function() { return this.Timer.create(); }
    },
    {
      name: 'table',
      factory: function() {
        return this.Rectangle.create({
          color: 'black',
          scaleX: 1.8,
          scaleY: 1.8,
          width: 500, // window.innerWidth,
          height: 500 // window.innerHeight
        });
      }
    },
    {
      name: 'robot',
      factory: function() {
        return this.Robot.create({x:37.5, y:435, scaleX: 0.5, scaleY: 0.5, width: 3, height: 3});
      }
    },
    {
      name: 'collider',
      factory: function() { return this.Collider.create(); }
    },
    'lastX', 'lastY', 'hittingWall',
    'questionArea'
  ],

  methods: [
    function init() {
      this.SUPER();

      this.buildMaze();
      this.addChild(this.robot);

      this.gamepad.pressed.sub('button4', () => this.fire());
      this.gamepad.pressed.sub('button5', () => this.fire());

      // Setup Physics
      this.collider.collide = function(o1, o2) {
        if ( o2 == this.robot ) {
          o2 = o1;
          o1 = this.robot;
        }
        if ( o1 == this.robot ) {
          if ( this.Door.isInstance(o2) ) {
            if ( ! o2.isClosed ) return;
            console.log('*************************** Door');
            o2.open();
            this.hittingWall = true;
            this.questionArea.removeAllChildren();
            this.questionArea.add(this.Question1.create());
          } else if ( this.Wall.isInstance(o2) ) {
            console.log('*************************** Wall');
            this.hittingWall = true;
          } else if ( this.Exit.isInstance(o2) ) {
            this.gameOver();
          }
        }
      }.bind(this);
      this.collider.start();
      this.timer.i$.sub(this.tick);
      this.timer.start();
    },

    function buildMaze() {
      var m = this.MAZE_HORIZ;

      // draw horizontal lines
      for ( var row = 0 ; row < m.length ; row++ ) {
        var rowdata = m[row];
        for ( var col = 0 ; col < rowdata.length ; col++ ) {
          if ( rowdata[col] ) {
            var blockType = this[rowdata[col]];
            this.addChild(blockType.create({
              x: this.BRICK_SIZE/2 + col*this.BRICK_SIZE,
              y: this.BRICK_SIZE/2 + row*this.BRICK_SIZE,
              width: this.BRICK_SIZE,
              height: 5
            }));
          }
        }
      }

      // draw vertical lines
      m = this.MAZE_VERT;
      for ( var row = 0 ; row < m.length ; row++ ) {
        var rowdata = m[row];
        for ( var col = 0 ; col < rowdata.length ; col++ ) {
          if ( rowdata[col] ) {
            var blockType = this[rowdata[col]];
            this.addChild(blockType.create({
              x: this.BRICK_SIZE/2 + col*this.BRICK_SIZE,
              y: this.BRICK_SIZE/2 + row*this.BRICK_SIZE,
              width: 5,
              height: this.BRICK_SIZE
            }));
          }
        }
      }

    },

    function initE() {
      this.SUPER();
      this.focus();
      this.style({display:'flex'}).add(this.table).add(' ').tag(null, null, this.questionArea$);
    },

    function gameOver() {
      if ( this.isGameOver ) return;
      this.isGameOver = true;

      this.table.color = 'white';

      var label = this.Label.create({
        text: 'You Win!',
        align: 'center',
        color: 'red',
        x: this.table.width/2,
        y: 180
      });
      this.addChild(label);

      this.Animation.create({
        duration: 2000,
        f: ()=> { label.scaleX = label.scaleY = 10; label.rotation = 2 * Math.PI; },
        objs: [label]
      }).start();

      this.Speak.create({text: "You Win! You're so smart! You're a JavaScript master!"}).play();
    },

    function addChild(c) {
      this.table.add(c);
      if ( c.intersects ) this.collider.add(c);
    },

    function removeChild(c) {
      this.table.remove(c);
      if ( c.intersects ) this.collider.remove(c);
    }
  ],

  listeners: [
    {
      name: 'tick',
      code: function() {
        if ( this.hittingWall ) {
          this.robot.x = this.lastX;
          this.robot.y = this.lastY;
          this.hittingWall = false;
        } else {
          this.lastX = this.robot.x;
          this.lastY = this.robot.y;
        }

        if ( this.gamepad.button0 ) this.up();
        if ( this.gamepad.button1 ) this.right();
        if ( this.gamepad.button2 ) this.down();
        if ( this.gamepad.button3 ) this.left();
      }
    }
  ],

  actions: [
    {
      name: 'up',
      keyboardShortcuts: [ 38 /* up arrow */, 'w' ],
      code: function() { this.robot.y -= 3; }
    },
    {
      name: 'down',
      keyboardShortcuts: [ 40 /* down arrow */, 's' ],
      code: function() { this.robot.y += 3; }
    },
    {
      name: 'left',
      keyboardShortcuts: [ 37 /* left arrow */, 'a' ],
      code: function() { this.robot.x -= 3; }
    },
    {
      name: 'right',
      keyboardShortcuts: [ 39 /* right arrow */, 'd' ],
      code: function() { this.robot.x += 3; }
    },
    {
      name: 'fire',
      keyboardShortcuts: [ ' ', 'x' ],
      code: function() {
        this.Laser.create({x: this.robot.x, y: this.robot.y, vx: 1, vy: 0});
        this.Laser.create({x: this.robot.x, y: this.robot.y, vx: 0, vy: 1});
        this.Laser.create({x: this.robot.x, y: this.robot.y, vx: -1, vy: 0});
        this.Laser.create({x: this.robot.x, y: this.robot.y, vx: 0, vy: -1});
      }
    }
  ]
});
<|endoftext|>