<commit_before>define(["require", "js/html/HtmlElement", "js/ui/ContentPlaceHolder", "js/core/Module", "underscore", "js/conf/ModuleConfiguration", "flow"],
    function (require, HtmlElement, ContentPlaceHolder, Module, _, ModuleConfiguration, flow) {
        var ModuleLoader = HtmlElement.inherit("js.core.ModuleLoader", {

            $classAttributes: ['router', 'currentModuleName', 'state'],
            defaults: {
                /**
                 * The current module name
                 */
                currentModuleName: null,
                /**
                 * The current module
                 */
                $currentModule: null,

                tagName: 'div',
                /**
                 * The css class of the component
                 */
                componentClass: "module-loader",
                /**
                 * The current state - is set to "loading" or "loading unloading"
                 * Is rendered to css className
                 */
                state: null,
                /***
                 * the router used for automatically registering routes from {@link js.conf.ModuleConfiguration}
                 *
                 * @type js.core.Router
                 * @required
                 */
                router: null
            },

            ctor: function (attributes) {
                this.callBase();
                this.$modules = {};
                this.$moduleCache = {};
            },

            _initializationComplete: function () {
                this.callBase();

                for (var i = 0; i < this.$configurations.length; i++) {
                    var config = this.$configurations[i];

                    if (config instanceof ModuleConfiguration) {
                        this.addModule(config.$);
                    }
                }
            },

            /***
             * adds a module to the list of known modules
             *
             * @param {js.conf.ModuleConfiguration} module
             */
            addModule: function (module) {
                _.defaults(module, {
                    name: null,
                    moduleClass: null,
                    route: null,
                    attributes: null
                });

                if (!module.name) {
                    throw "module cannot be added: module name is required";
                }

                if (!module.moduleClass) {
                    throw "no moduleClass defined for module";
                }

                if (this.$modules.hasOwnProperty(module.name)) {
                    throw "module with name '" + module.name + "' already registered";
                }

                this.$modules[module.name] = module;

                if (module.route) {
                    if (!this.$.router) {
                        throw "defining modules with routes requires a router instance to be set";
                    }

                    var self = this;
                    this.$.router.addRoute({
                        name: module.name,
                        route: module.route,
                        fn: function (routeContext) {

                            // route triggered -> load module
                            self.loadModule(module, routeContext.callback, routeContext);
                        }.async()
                    });
                }

            },
            /**
             * Starts the module with the given name
             * @param {String} moduleName - The name of the module
             * @param {js.core.Module} moduleInstance - the module instance
             * @param {Function} callback - the callback function
             * @param {Object} routeContext - the route context
             * @param {Object} [cachedInstance]
             * @private
             */
            _startModule: function (moduleName, moduleInstance, callback, routeContext, cachedInstance) {

                var self = this;

                flow()
                    .seq(function (cb) {

                        var currentModule = self.$.$currentModule;
                        if (currentModule) {
                            currentModule._unload(cb);
                        } else {
                            cb();
                        }
                    })
                    .seq(function(cb) {

                        // start module
                        moduleInstance.start(function (err) {

                            if (err || cachedInstance) {
                                cb(err);
                            } else {
                                if (routeContext) {
                                    // fresh instance with maybe new routers -> exec routes for new router
                                    var routeExecutionStack = [];

                                    for (var i = 0; i < moduleInstance.$routers.length; i++) {
                                        routeExecutionStack = routeExecutionStack.concat(moduleInstance.$routers[i].generateRoutingStack(routeContext.fragment));
                                    }

                                    flow()
                                        .seqEach(routeExecutionStack, function (routingFunction, cb) {
                                            routingFunction(cb);
                                        })
                                        .exec(cb);

                                } else {
                                    cb();
                                }

                            }
                        }, routeContext);
                    })
                    .seq(function () {
                        self._clearContentPlaceHolders();

                        self.set('currentModuleName', moduleName);
                        var contentPlaceHolders = self.getContentPlaceHolders();

                        // set content
                        for (var i = 0; i < contentPlaceHolders.length; i++) {
                            var contentPlaceHolder = contentPlaceHolders[i];
                            contentPlaceHolder.set("content", moduleInstance.findContent(contentPlaceHolder.$.name));
                        }

                    })
                    .exec(function (err) {
                        self.set({
                            state: err ? 'error' : null,
                            $currentModule: moduleInstance
                        });

                        if (callback) {
                            callback(err, moduleInstance);
                        }
                    });

            },

            /***
             * loads an module instance into the module loader and starts the module
             *
             * @param {js.conf.ModuleConfiguration} module - the module to load
             * @param {Function} [callback] - a callback function which gets invoked after the module is loaded or an error occurred
             * @param {js.core.Router.RouteContext} [routeContext]
             */
            loadModule: function (module, callback, routeContext) {

                var self = this;
                callback = callback || function () {
                };

                if (!module.hasOwnProperty("name")) {
                    // load by name
                    module = this.$modules[module];
                }

                if (!module) {
                    callback("module not found");
                }

                if (module.name === this.$.currentModuleName) {
                    // module already shown
                    if (callback) {
                        callback();
                    }
                } else {

                    flow()
                        .seq(function () {
                            self.set('currentModuleName', null);
                            self.set('state', 'unloading loading');
                        })
                        .seq(function (cb) {

                            self.set('state', 'loading');

                            self._clearContentPlaceHolders();
                            self.$lastModuleName = self.$.currentModuleName;

                            if (self.$moduleCache.hasOwnProperty(module.name)) {
                                self._startModule(module.name, self.$moduleCache[module.name], cb, routeContext, true);
                            } else {

                                // load module

                                require([self.$stage.$applicationContext.getFqClassName(module.moduleClass)], function (moduleBaseClass) {
                                    var moduleInstance = new moduleBaseClass(module.attributes, false, self.$stage, null, null);

                                    if (moduleInstance instanceof Module) {
                                        if (typeof(CollectGarbage) == "function") {
                                            CollectGarbage();
                                        }

                                        moduleInstance._initialize("auto");

                                        // cache instance
                                        self.$moduleCache[module.name] = moduleInstance;

                                        self._startModule(module.name, moduleInstance, cb, routeContext, false);

                                    } else {
                                        cb(new Error("Module '" + module.moduleClass + "' isn't an instance of js.core.Module"));
                                    }

                                }, function (err) {
                                    cb(err);
                                });
                            }

                        })
                        .exec(function (err) {

                            if (err) {
                                self.set('state', 'error');
                                self.log(err, "warn");
                            }

                            callback(err);
                        });

                }

            },
            /**
             * Returns true if module with name is active
             *
             * @param {String} moduleName
             */
            isModuleActive: function (moduleName) {
                return this.$.currentModuleName == moduleName;
            }.onChange('currentModuleName'),

            _clearContentPlaceHolders: function () {

                var contentPlaceHolders = this.getContentPlaceHolders();

                // set content
                for (var i = 0; i < contentPlaceHolders.length; i++) {
                    var contentPlaceHolder = contentPlaceHolders[i];
                    contentPlaceHolder.set("content", null);
                }

            },

            // TODO: remove this method and make the modules bindable

            /***
             * @deprecated will be removed soon
             * @return {Array}
             */
            moduleNames: function () {
                var modules = [], conf;
                for (var i = 0; i < this.$configurations.length; i++) {
                    conf = this.$configurations[i];
                    if (conf instanceof ModuleConfiguration) {
                        modules.push(conf.$.name);
                    }
                }
                return modules;
            },

            _renderState: function (state, oldState) {
                oldState && this.removeClass(oldState);
                state && this.addClass(state);
            }
        });

        ModuleLoader.findContentPlaceHolders = function (component) {
            var ret = [];

            for (var i = 0; i < component.$children.length; i++) {
                var child = component.$children[i];
                if (child instanceof ContentPlaceHolder) {
                    ret.push(child);
                } else {
                    ret.concat(ModuleLoader.findContentPlaceHolders(child));
                }
            }

            return ret;

        };

        return ModuleLoader;
    });<commit_msg>removed unused method findContentPlaceHolders<commit_after>define(["require", "js/html/HtmlElement", "js/ui/ContentPlaceHolder", "js/core/Module", "underscore", "js/conf/ModuleConfiguration", "flow"],
    function (require, HtmlElement, ContentPlaceHolder, Module, _, ModuleConfiguration, flow) {
        var ModuleLoader = HtmlElement.inherit("js.core.ModuleLoader", {

            $classAttributes: ['router', 'currentModuleName', 'state'],
            defaults: {
                /**
                 * The current module name
                 */
                currentModuleName: null,
                /**
                 * The current module
                 */
                $currentModule: null,

                tagName: 'div',
                /**
                 * The css class of the component
                 */
                componentClass: "module-loader",
                /**
                 * The current state - is set to "loading" or "loading unloading"
                 * Is rendered to css className
                 */
                state: null,
                /***
                 * the router used for automatically registering routes from {@link js.conf.ModuleConfiguration}
                 *
                 * @type js.core.Router
                 * @required
                 */
                router: null
            },

            ctor: function (attributes) {
                this.callBase();
                this.$modules = {};
                this.$moduleCache = {};
            },

            _initializationComplete: function () {
                this.callBase();

                for (var i = 0; i < this.$configurations.length; i++) {
                    var config = this.$configurations[i];

                    if (config instanceof ModuleConfiguration) {
                        this.addModule(config.$);
                    }
                }
            },

            /***
             * adds a module to the list of known modules
             *
             * @param {js.conf.ModuleConfiguration} module
             */
            addModule: function (module) {
                _.defaults(module, {
                    name: null,
                    moduleClass: null,
                    route: null,
                    attributes: null
                });

                if (!module.name) {
                    throw "module cannot be added: module name is required";
                }

                if (!module.moduleClass) {
                    throw "no moduleClass defined for module";
                }

                if (this.$modules.hasOwnProperty(module.name)) {
                    throw "module with name '" + module.name + "' already registered";
                }

                this.$modules[module.name] = module;

                if (module.route) {
                    if (!this.$.router) {
                        throw "defining modules with routes requires a router instance to be set";
                    }

                    var self = this;
                    this.$.router.addRoute({
                        name: module.name,
                        route: module.route,
                        fn: function (routeContext) {

                            // route triggered -> load module
                            self.loadModule(module, routeContext.callback, routeContext);
                        }.async()
                    });
                }

            },
            /**
             * Starts the module with the given name
             * @param {String} moduleName - The name of the module
             * @param {js.core.Module} moduleInstance - the module instance
             * @param {Function} callback - the callback function
             * @param {Object} routeContext - the route context
             * @param {Object} [cachedInstance]
             * @private
             */
            _startModule: function (moduleName, moduleInstance, callback, routeContext, cachedInstance) {

                var self = this;

                flow()
                    .seq(function (cb) {

                        var currentModule = self.$.$currentModule;
                        if (currentModule) {
                            currentModule._unload(cb);
                        } else {
                            cb();
                        }
                    })
                    .seq(function(cb) {

                        // start module
                        moduleInstance.start(function (err) {

                            if (err || cachedInstance) {
                                cb(err);
                            } else {
                                if (routeContext) {
                                    // fresh instance with maybe new routers -> exec routes for new router
                                    var routeExecutionStack = [];

                                    for (var i = 0; i < moduleInstance.$routers.length; i++) {
                                        routeExecutionStack = routeExecutionStack.concat(moduleInstance.$routers[i].generateRoutingStack(routeContext.fragment));
                                    }

                                    flow()
                                        .seqEach(routeExecutionStack, function (routingFunction, cb) {
                                            routingFunction(cb);
                                        })
                                        .exec(cb);

                                } else {
                                    cb();
                                }

                            }
                        }, routeContext);
                    })
                    .seq(function () {
                        self._clearContentPlaceHolders();

                        self.set('currentModuleName', moduleName);
                        var contentPlaceHolders = self.getContentPlaceHolders();

                        // set content
                        for (var i = 0; i < contentPlaceHolders.length; i++) {
                            var contentPlaceHolder = contentPlaceHolders[i];
                            contentPlaceHolder.set("content", moduleInstance.findContent(contentPlaceHolder.$.name));
                        }

                    })
                    .exec(function (err) {
                        self.set({
                            state: err ? 'error' : null,
                            $currentModule: moduleInstance
                        });

                        if (callback) {
                            callback(err, moduleInstance);
                        }
                    });

            },

            /***
             * loads an module instance into the module loader and starts the module
             *
             * @param {js.conf.ModuleConfiguration} module - the module to load
             * @param {Function} [callback] - a callback function which gets invoked after the module is loaded or an error occurred
             * @param {js.core.Router.RouteContext} [routeContext]
             */
            loadModule: function (module, callback, routeContext) {

                var self = this;
                callback = callback || function () {
                };

                if (!module.hasOwnProperty("name")) {
                    // load by name
                    module = this.$modules[module];
                }

                if (!module) {
                    callback("module not found");
                }

                if (module.name === this.$.currentModuleName) {
                    // module already shown
                    if (callback) {
                        callback();
                    }
                } else {

                    flow()
                        .seq(function () {
                            self.set('currentModuleName', null);
                            self.set('state', 'unloading loading');
                        })
                        .seq(function (cb) {

                            self.set('state', 'loading');

                            self._clearContentPlaceHolders();
                            self.$lastModuleName = self.$.currentModuleName;

                            if (self.$moduleCache.hasOwnProperty(module.name)) {
                                self._startModule(module.name, self.$moduleCache[module.name], cb, routeContext, true);
                            } else {

                                // load module

                                require([self.$stage.$applicationContext.getFqClassName(module.moduleClass)], function (moduleBaseClass) {
                                    var moduleInstance = new moduleBaseClass(module.attributes, false, self.$stage, null, null);

                                    if (moduleInstance instanceof Module) {
                                        if (typeof(CollectGarbage) == "function") {
                                            CollectGarbage();
                                        }

                                        moduleInstance._initialize("auto");

                                        // cache instance
                                        self.$moduleCache[module.name] = moduleInstance;

                                        self._startModule(module.name, moduleInstance, cb, routeContext, false);

                                    } else {
                                        cb(new Error("Module '" + module.moduleClass + "' isn't an instance of js.core.Module"));
                                    }

                                }, function (err) {
                                    cb(err);
                                });
                            }

                        })
                        .exec(function (err) {

                            if (err) {
                                self.set('state', 'error');
                                self.log(err, "warn");
                            }

                            callback(err);
                        });

                }

            },
            /**
             * Returns true if module with name is active
             *
             * @param {String} moduleName
             */
            isModuleActive: function (moduleName) {
                return this.$.currentModuleName == moduleName;
            }.onChange('currentModuleName'),

            _clearContentPlaceHolders: function () {

                var contentPlaceHolders = this.getContentPlaceHolders();

                // set content
                for (var i = 0; i < contentPlaceHolders.length; i++) {
                    var contentPlaceHolder = contentPlaceHolders[i];
                    contentPlaceHolder.set("content", null);
                }

            },

            // TODO: remove this method and make the modules bindable

            /***
             * @deprecated will be removed soon
             * @return {Array}
             */
            moduleNames: function () {
                var modules = [], conf;
                for (var i = 0; i < this.$configurations.length; i++) {
                    conf = this.$configurations[i];
                    if (conf instanceof ModuleConfiguration) {
                        modules.push(conf.$.name);
                    }
                }
                return modules;
            },

            _renderState: function (state, oldState) {
                oldState && this.removeClass(oldState);
                state && this.addClass(state);
            }
        });

        return ModuleLoader;
    });<|endoftext|>


<commit_before>// Copyright 2002-2014, University of Colorado Boulder

/**
 * Handles a visual WebGL layer of drawables.  The WebGL system is designed to be modular, so that testing can
 * easily be done without scenery.  Hence WebGLBlock delegates most of its work to WebGLRenderer.
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Sharfudeen Ashraf (For Ghent University)
 */
define( function( require ) {
  'use strict';

  // modules
  var inherit = require( 'PHET_CORE/inherit' );
  var PoolableMixin = require( 'PHET_CORE/PoolableMixin' );
  var cleanArray = require( 'PHET_CORE/cleanArray' );
  var scenery = require( 'SCENERY/scenery' );
  var FittedBlock = require( 'SCENERY/display/FittedBlock' );
  var Util = require( 'SCENERY/util/Util' );
  var Color = require( 'SCENERY/util/Color' );

  scenery.PixiBlock = function PixiBlock( display, renderer, transformRootInstance, filterRootInstance ) {
    this.initialize( display, renderer, transformRootInstance, filterRootInstance );
  };
  var PixiBlock = scenery.PixiBlock;

  inherit( FittedBlock, PixiBlock, {
    initialize: function( display, renderer, transformRootInstance, filterRootInstance ) {

      this.initializeFittedBlock( display, renderer, transformRootInstance );

      // PixiBlocks are hard-coded to take the full display size (as opposed to svg and canvas)
      // Since we saw some jitter on iPad, see #318 and generally expect WebGL layers to span the entire display
      // In the future, it would be good to understand what was causing the problem and make webgl consistent
      // with svg and canvas again.
      this.fit = FittedBlock.FULL_DISPLAY;

      this.filterRootInstance = filterRootInstance;

      this.dirtyDrawables = cleanArray( this.dirtyDrawables );

      // TODO: Maybe reuse the WebGLRenderer and use an initialize pattern()?

      // TODO: Maybe pass through Renderer.bitmaskWebGLLowResolution ) ?
      // Each WebGL block needs its own canvas, and this is created by the WebGLRenderer.
      this.webglRenderer = PIXI.autoDetectRenderer( 400, 300, { transparent: true } );
      this.domElement = this.webglRenderer.view;

      this.stage = new PIXI.Stage();

      // reset any fit transforms that were applied
      // TODO: What is force acceleration?
      Util.prepareForTransform( this.webglRenderer.view, this.forceAcceleration );
      Util.unsetTransform( this.webglRenderer.view ); // clear out any transforms that could have been previously applied

      // store our backing scale so we don't have to look it up while fitting
//      this.backingScale = ( renderer & Renderer.bitmaskWebGLLowResolution ) ? 1 : scenery.Util.backingScale( this.gl );

      this.initializeWebGLState();

      sceneryLog && sceneryLog.PixiBlock && sceneryLog.PixiBlock( 'initialized #' + this.id );
      // TODO: dirty list of nodes (each should go dirty only once, easier than scanning all?)

      return this;
    },

    initializeWebGLState: function() {

      // TODO: Maybe initialize the webglRenderer, if it is reused during pooling?
//      this.webglRenderer.initialize();
    },

    setSizeFullDisplay: function() {

      // TODO: Allow scenery to change the size of the WebGLRenderer.view
      var size = this.display.getSize();

      // TODO: Set size
      //this.webglRenderer.setCanvasSize( size.width, size.height );
    },

    setSizeFitBounds: function() {
      // TODO: Allow scenery to change the size of the WebGLRenderer.view

      var x = this.fitBounds.minX;
      var y = this.fitBounds.minY;
      //OHTWO TODO PERFORMANCE: see if we can get a speedup by putting the backing scale in our transform instead of with CSS?
      Util.setTransform( 'matrix(1,0,0,1,' + x + ',' + y + ')', this.webglRenderer.view, this.forceAcceleration ); // reapply the translation as a CSS transform

      // TODO: Set size
      //this.webglRenderer.setCanvasSize( this.fitBounds.width, this.fitBounds.height );

      //TODO: How to handle this in WebGLRenderer?
//      this.updateWebGLDimension( -x, -y, this.fitBounds.width, this.fitBounds.height );
    },

    update: function() {
      sceneryLog && sceneryLog.PixiBlock && sceneryLog.PixiBlock( 'update #' + this.id );
      sceneryLog && sceneryLog.PixiBlock && sceneryLog.push();

      if ( this.dirty && !this.disposed ) {
        this.dirty = false;

        while ( this.dirtyDrawables.length ) {
          this.dirtyDrawables.pop().update();
        }

        // udpate the fit BEFORE drawing, since it may change our offset
        this.updateFit();

        this.webglRenderer.render( this.stage );
      }

      sceneryLog && sceneryLog.PixiBlock && sceneryLog.pop();
    },

    dispose: function() {
      sceneryLog && sceneryLog.PixiBlock && sceneryLog.PixiBlock( 'dispose #' + this.id );

      this.webglRenderer.dispose();

      // clear references
      cleanArray( this.dirtyDrawables );

      FittedBlock.prototype.dispose.call( this );
    },

    markDirtyDrawable: function( drawable ) {
      sceneryLog && sceneryLog.dirty && sceneryLog.dirty( 'markDirtyDrawable on PixiBlock#' + this.id + ' with ' + drawable.toString() );

      assert && assert( drawable );

      // TODO: instance check to see if it is a canvas cache (usually we don't need to call update on our drawables)
      this.dirtyDrawables.push( drawable );
      this.markDirty();
    },

    addDrawable: function( drawable ) {
      sceneryLog && sceneryLog.PixiBlock && sceneryLog.PixiBlock( '#' + this.id + '.addDrawable ' + drawable.toString() );

      FittedBlock.prototype.addDrawable.call( this, drawable );

      drawable.initializeContext( this );
    },

    removeDrawable: function( drawable ) {
      sceneryLog && sceneryLog.PixiBlock && sceneryLog.PixiBlock( '#' + this.id + '.removeDrawable ' + drawable.toString() );

      FittedBlock.prototype.removeDrawable.call( this, drawable );
    },

    onIntervalChange: function( firstDrawable, lastDrawable ) {
      sceneryLog && sceneryLog.PixiBlock && sceneryLog.PixiBlock( '#' + this.id + '.onIntervalChange ' + firstDrawable.toString() + ' to ' + lastDrawable.toString() );

      FittedBlock.prototype.onIntervalChange.call( this, firstDrawable, lastDrawable );
    },

    onPotentiallyMovedDrawable: function( drawable ) {
      sceneryLog && sceneryLog.PixiBlock && sceneryLog.PixiBlock( '#' + this.id + '.onPotentiallyMovedDrawable ' + drawable.toString() );
      sceneryLog && sceneryLog.PixiBlock && sceneryLog.push();

      assert && assert( drawable.parentDrawable === this );

      // For now, mark it as dirty so that we redraw anything containing it. In the future, we could have more advanced
      // behavior that figures out the intersection-region for what was moved and what it was moved past, but that's
      // a harder problem.
      drawable.markDirty();

      sceneryLog && sceneryLog.PixiBlock && sceneryLog.pop();
    },

    // This method can be called to simulate context loss using the khronos webgl-debug context loss simulator, see #279
    simulateWebGLContextLoss: function() {
      console.log( 'simulating webgl context loss in PixiBlock' );
      assert && assert( this.scene.webglMakeLostContextSimulatingCanvas );
      this.webglRenderer.view.loseContextInNCalls( 5 );
    },

    toString: function() {
      return 'PixiBlock#' + this.id + '-' + FittedBlock.fitString[ this.fit ];
    }
  }, {
    // Statics
    fragmentTypeFill: 0,
    fragmentTypeTexture: 1
  } );

  /* jshint -W064 */
  PoolableMixin( PixiBlock, {
    constructorDuplicateFactory: function( pool ) {
      return function( display, renderer, transformRootInstance, filterRootInstance ) {
        if ( pool.length ) {
          sceneryLog && sceneryLog.PixiBlock && sceneryLog.PixiBlock( 'new from pool' );
          return pool.pop().initialize( display, renderer, transformRootInstance, filterRootInstance );
        }
        else {
          sceneryLog && sceneryLog.PixiBlock && sceneryLog.PixiBlock( 'new from constructor' );
          return new PixiBlock( display, renderer, transformRootInstance, filterRootInstance );
        }
      };
    }
  } );

  return PixiBlock;
} );
<commit_msg>Renamed renderer to pixiRenderer<commit_after>// Copyright 2002-2014, University of Colorado Boulder

/**
 * Handles a visual WebGL layer of drawables.  The WebGL system is designed to be modular, so that testing can
 * easily be done without scenery.  Hence WebGLBlock delegates most of its work to WebGLRenderer.
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Sharfudeen Ashraf (For Ghent University)
 */
define( function( require ) {
  'use strict';

  // modules
  var inherit = require( 'PHET_CORE/inherit' );
  var PoolableMixin = require( 'PHET_CORE/PoolableMixin' );
  var cleanArray = require( 'PHET_CORE/cleanArray' );
  var scenery = require( 'SCENERY/scenery' );
  var FittedBlock = require( 'SCENERY/display/FittedBlock' );
  var Util = require( 'SCENERY/util/Util' );
  var Color = require( 'SCENERY/util/Color' );

  scenery.PixiBlock = function PixiBlock( display, renderer, transformRootInstance, filterRootInstance ) {
    this.initialize( display, renderer, transformRootInstance, filterRootInstance );
  };
  var PixiBlock = scenery.PixiBlock;

  inherit( FittedBlock, PixiBlock, {
    initialize: function( display, renderer, transformRootInstance, filterRootInstance ) {

      this.initializeFittedBlock( display, renderer, transformRootInstance );

      // PixiBlocks are hard-coded to take the full display size (as opposed to svg and canvas)
      // Since we saw some jitter on iPad, see #318 and generally expect WebGL layers to span the entire display
      // In the future, it would be good to understand what was causing the problem and make webgl consistent
      // with svg and canvas again.
      this.fit = FittedBlock.FULL_DISPLAY;

      this.filterRootInstance = filterRootInstance;

      this.dirtyDrawables = cleanArray( this.dirtyDrawables );

      // TODO: Maybe reuse the WebGLRenderer and use an initialize pattern()?

      // Create the Pixi renderer.
      // Note.  This cannot be called `renderer` or it will interfere with scenery internals
      this.pixiRenderer = PIXI.autoDetectRenderer( 400, 300, { transparent: true } );
      this.domElement = this.pixiRenderer.view;

      this.stage = new PIXI.Stage();

      // reset any fit transforms that were applied
      // TODO: What is force acceleration?
      Util.prepareForTransform( this.pixiRenderer.view, this.forceAcceleration );
      Util.unsetTransform( this.pixiRenderer.view ); // clear out any transforms that could have been previously applied

      // store our backing scale so we don't have to look it up while fitting
//      this.backingScale = ( renderer & Renderer.bitmaskWebGLLowResolution ) ? 1 : scenery.Util.backingScale( this.gl );

      this.initializeWebGLState();

      sceneryLog && sceneryLog.PixiBlock && sceneryLog.PixiBlock( 'initialized #' + this.id );
      // TODO: dirty list of nodes (each should go dirty only once, easier than scanning all?)

      return this;
    },

    initializeWebGLState: function() {

      // TODO: Maybe initialize the pixiRenderer, if it is reused during pooling?
//      this.pixiRenderer.initialize();
    },

    setSizeFullDisplay: function() {

      // TODO: Allow scenery to change the size of the WebGLRenderer.view
      var size = this.display.getSize();

      // TODO: Set size
      //this.pixiRenderer.setCanvasSize( size.width, size.height );
    },

    setSizeFitBounds: function() {
      // TODO: Allow scenery to change the size of the WebGLRenderer.view

      var x = this.fitBounds.minX;
      var y = this.fitBounds.minY;
      //OHTWO TODO PERFORMANCE: see if we can get a speedup by putting the backing scale in our transform instead of with CSS?
      Util.setTransform( 'matrix(1,0,0,1,' + x + ',' + y + ')', this.pixiRenderer.view, this.forceAcceleration ); // reapply the translation as a CSS transform

      // TODO: Set size
      //this.pixiRenderer.setCanvasSize( this.fitBounds.width, this.fitBounds.height );

      //TODO: How to handle this in WebGLRenderer?
//      this.updateWebGLDimension( -x, -y, this.fitBounds.width, this.fitBounds.height );
    },

    update: function() {
      sceneryLog && sceneryLog.PixiBlock && sceneryLog.PixiBlock( 'update #' + this.id );
      sceneryLog && sceneryLog.PixiBlock && sceneryLog.push();

      if ( this.dirty && !this.disposed ) {
        this.dirty = false;

        while ( this.dirtyDrawables.length ) {
          this.dirtyDrawables.pop().update();
        }

        // udpate the fit BEFORE drawing, since it may change our offset
        this.updateFit();

        this.pixiRenderer.render( this.stage );
      }

      sceneryLog && sceneryLog.PixiBlock && sceneryLog.pop();
    },

    dispose: function() {
      sceneryLog && sceneryLog.PixiBlock && sceneryLog.PixiBlock( 'dispose #' + this.id );

      this.pixiRenderer.dispose();

      // clear references
      cleanArray( this.dirtyDrawables );

      FittedBlock.prototype.dispose.call( this );
    },

    markDirtyDrawable: function( drawable ) {
      sceneryLog && sceneryLog.dirty && sceneryLog.dirty( 'markDirtyDrawable on PixiBlock#' + this.id + ' with ' + drawable.toString() );

      assert && assert( drawable );

      // TODO: instance check to see if it is a canvas cache (usually we don't need to call update on our drawables)
      this.dirtyDrawables.push( drawable );
      this.markDirty();
    },

    addDrawable: function( drawable ) {
      sceneryLog && sceneryLog.PixiBlock && sceneryLog.PixiBlock( '#' + this.id + '.addDrawable ' + drawable.toString() );

      FittedBlock.prototype.addDrawable.call( this, drawable );

      drawable.initializeContext( this );
    },

    removeDrawable: function( drawable ) {
      sceneryLog && sceneryLog.PixiBlock && sceneryLog.PixiBlock( '#' + this.id + '.removeDrawable ' + drawable.toString() );

      FittedBlock.prototype.removeDrawable.call( this, drawable );
    },

    onIntervalChange: function( firstDrawable, lastDrawable ) {
      sceneryLog && sceneryLog.PixiBlock && sceneryLog.PixiBlock( '#' + this.id + '.onIntervalChange ' + firstDrawable.toString() + ' to ' + lastDrawable.toString() );

      FittedBlock.prototype.onIntervalChange.call( this, firstDrawable, lastDrawable );
    },

    onPotentiallyMovedDrawable: function( drawable ) {
      sceneryLog && sceneryLog.PixiBlock && sceneryLog.PixiBlock( '#' + this.id + '.onPotentiallyMovedDrawable ' + drawable.toString() );
      sceneryLog && sceneryLog.PixiBlock && sceneryLog.push();

      assert && assert( drawable.parentDrawable === this );

      // For now, mark it as dirty so that we redraw anything containing it. In the future, we could have more advanced
      // behavior that figures out the intersection-region for what was moved and what it was moved past, but that's
      // a harder problem.
      drawable.markDirty();

      sceneryLog && sceneryLog.PixiBlock && sceneryLog.pop();
    },

    // This method can be called to simulate context loss using the khronos webgl-debug context loss simulator, see #279
    simulateWebGLContextLoss: function() {
      console.log( 'simulating webgl context loss in PixiBlock' );
      assert && assert( this.scene.webglMakeLostContextSimulatingCanvas );
      this.pixiRenderer.view.loseContextInNCalls( 5 );
    },

    toString: function() {
      return 'PixiBlock#' + this.id + '-' + FittedBlock.fitString[ this.fit ];
    }
  }, {
    // Statics
    fragmentTypeFill: 0,
    fragmentTypeTexture: 1
  } );

  /* jshint -W064 */
  PoolableMixin( PixiBlock, {
    constructorDuplicateFactory: function( pool ) {
      return function( display, renderer, transformRootInstance, filterRootInstance ) {
        if ( pool.length ) {
          sceneryLog && sceneryLog.PixiBlock && sceneryLog.PixiBlock( 'new from pool' );
          return pool.pop().initialize( display, renderer, transformRootInstance, filterRootInstance );
        }
        else {
          sceneryLog && sceneryLog.PixiBlock && sceneryLog.PixiBlock( 'new from constructor' );
          return new PixiBlock( display, renderer, transformRootInstance, filterRootInstance );
        }
      };
    }
  } );

  return PixiBlock;
} );
<|endoftext|>


<commit_before>/* ====================================================================
 * eldarion-ajax.min.js v0.14.0
 * eldarion-ajax-core v0.13.0
 * eldarion-ajax-handlers v0.1.2
 * ====================================================================
 * Copyright (c) 2015, Eldarion, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *
 *     * Redistributions in binary form must reproduce the above copyright notice,
 *       this list of conditions and the following disclaimer in the documentation
 *       and/or other materials provided with the distribution.
 *
 *     * Neither the name of Eldarion, Inc. nor the names of its contributors may
 *       be used to endorse or promote products derived from this software without
 *       specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * ==================================================================== */
if(document.all&&!window.setTimeout.isPolyfill){var __nativeST__=window.setTimeout;window.setTimeout=function(e,t){var o=Array.prototype.slice.call(arguments,2);return __nativeST__(e instanceof Function?function(){e.apply(null,o)}:e,t)},window.setTimeout.isPolyfill=!0}if(document.all&&!window.setInterval.isPolyfill){var __nativeSI__=window.setInterval;window.setInterval=function(e,t){var o=Array.prototype.slice.call(arguments,2);return __nativeSI__(e instanceof Function?function(){e.apply(null,o)}:e,t)},window.setInterval.isPolyfill=!0}!function(e,t){"use strict";"function"==typeof define&&define.amd?define(["jquery"],t):t("object"==typeof exports?require("jquery"):e.jQuery)}(this,function(e){"use strict";var t=function(){};t.prototype._ajax=function(t,o,a,n){t.trigger("eldarion-ajax:begin",[t]);var r=t.triggerHandler("eldarion-ajax:modify-data",n),c="application/x-www-form-urlencoded; charset=UTF-8",i=!0,p=!0,s="object"==typeof n;r&&(n=r),s&&(c=!1,i=!1,p=!1),e.ajax({url:o,type:a,dataType:"json",data:n,cache:p,processData:i,contentType:c,headers:{"X-Eldarion-Ajax":!0}}).done(function(e,o,a){e||(e={}),t.trigger("eldarion-ajax:success",[t,e,o,a])}).fail(function(e,o,a){t.trigger("eldarion-ajax:error",[t,e,o,a])}).always(function(o,a,n){e(document).trigger("eldarion-ajax:complete",[t,o,a,n])})},t.prototype.click=function(o){var a=e(this),n=a.attr("href"),r=a.data("method"),c=a.data("data"),i=null,p=null;r||(r="get"),c&&(i={},c.split(",").map(function(t){p=t.split(":"),0===p[1].indexOf("#")?i[p[0]]=e(p[1]).val():i[p[0]]=p[1]})),o.preventDefault(),t.prototype._ajax(a,n,r,i)},t.prototype.submit=function(o){var a=e(this),n=a.attr("action"),r=a.attr("method");o.preventDefault(),void 0===window.FormData?t.prototype._ajax(a,n,r,a.serialize()):t.prototype._ajax(a,n,r,new FormData(a[0]))},t.prototype.cancel=function(t){var o=e(this),a=o.attr("data-cancel-closest");t.preventDefault(),o.closest(a).remove()},t.prototype.timeout=function(o,a){var n=e(a),r=n.data("timeout"),c=n.data("url"),i=n.data("method");i||(i="get"),window.setTimeout(t.prototype._ajax,r,n,c,i,null)},t.prototype.interval=function(o,a){var n=e(a),r=n.data("interval"),c=n.data("url"),i=n.data("method");i||(i="get"),window.setInterval(t.prototype._ajax,r,n,c,i,null)},e(function(){e("body").on("click","a.ajax",t.prototype.click),e("body").on("submit","form.ajax",t.prototype.submit),e("body").on("click","a[data-cancel-closest]",t.prototype.cancel),e("[data-timeout]").each(t.prototype.timeout),e("[data-interval]").each(t.prototype.interval)})}),function(e,t){"use strict";"function"==typeof define&&define.amd?define(["jquery"],t):t("object"==typeof exports?require("jquery"):e.jQuery)}(this,function(e){"use strict";var t=function(){};t.prototype.redirect=function(e,t,o){return o.location?(window.location.href=o.location,!1):void 0},t.prototype.replace=function(t,o,a){e(o.data("replace")).replaceWith(a.html)},t.prototype.replaceClosest=function(e,t,o){t.closest(t.data("replace-closest")).replaceWith(o.html)},t.prototype.replaceInner=function(t,o,a){e(o.data("replace-inner")).html(a.html)},t.prototype.replaceClosestInner=function(e,t,o){t.closest(t.data("replace-closest-inner")).html(o.html)},t.prototype.append=function(t,o,a){e(o.data("append")).append(a.html)},t.prototype.prepend=function(t,o,a){e(o.data("prepend")).prepend(a.html)},t.prototype.refresh=function(t,o){e.each(e(o.data("refresh")),function(t,o){e.getJSON(e(o).data("refresh-url"),function(t){e(o).replaceWith(t.html)})})},t.prototype.refreshClosest=function(t,o){e.each(e(o.data("refresh-closest")),function(t,a){e.getJSON(e(a).data("refresh-url"),function(t){o.closest(e(a)).replaceWith(t.html)})})},t.prototype.clear=function(t,o){e(o.data("clear")).html("")},t.prototype.remove=function(t,o){e(o.data("remove")).remove()},t.prototype.clearClosest=function(e,t){t.closest(t.data("clear-closest")).html("")},t.prototype.removeClosest=function(e,t){t.closest(t.data("remove-closest")).remove()},t.prototype.fragments=function(t,o,a){a.fragments&&e.each(a.fragments,function(t,o){e(t).replaceWith(o)}),a["inner-fragments"]&&e.each(a["inner-fragments"],function(t,o){e(t).html(o)}),a["append-fragments"]&&e.each(a["append-fragments"],function(t,o){e(t).append(o)}),a["prepend-fragments"]&&e.each(a["prepend-fragments"],function(t,o){e(t).prepend(o)})},e(function(){e(document).on("eldarion-ajax:success",t.prototype.redirect),e(document).on("eldarion-ajax:success",t.prototype.fragments),e(document).on("eldarion-ajax:success","[data-replace]",t.prototype.replace),e(document).on("eldarion-ajax:success","[data-replace-closest]",t.prototype.replaceClosest),e(document).on("eldarion-ajax:success","[data-replace-inner]",t.prototype.replaceInner),e(document).on("eldarion-ajax:success","[data-replace-closest-inner]",t.prototype.replaceClosestInner),e(document).on("eldarion-ajax:success","[data-append]",t.prototype.append),e(document).on("eldarion-ajax:success","[data-prepend]",t.prototype.prepend),e(document).on("eldarion-ajax:success","[data-refresh]",t.prototype.refresh),e(document).on("eldarion-ajax:success","[data-refresh-closest]",t.prototype.refreshClosest),e(document).on("eldarion-ajax:success","[data-clear]",t.prototype.clear),e(document).on("eldarion-ajax:success","[data-remove]",t.prototype.remove),e(document).on("eldarion-ajax:success","[data-clear-closest]",t.prototype.clearClosest),e(document).on("eldarion-ajax:success","[data-remove-closest]",t.prototype.removeClosest)})});
<commit_msg>Update minified version<commit_after>/* ====================================================================
 * eldarion-ajax.min.js v0.14.0
 * eldarion-ajax-core v0.13.0
 * eldarion-ajax-handlers v0.1.2
 * ====================================================================
 * Copyright (c) 2015, Eldarion, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *
 *     * Redistributions in binary form must reproduce the above copyright notice,
 *       this list of conditions and the following disclaimer in the documentation
 *       and/or other materials provided with the distribution.
 *
 *     * Neither the name of Eldarion, Inc. nor the names of its contributors may
 *       be used to endorse or promote products derived from this software without
 *       specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * ==================================================================== */
if(document.all&&!window.setTimeout.isPolyfill){var __nativeST__=window.setTimeout;window.setTimeout=function(e,t){var o=Array.prototype.slice.call(arguments,2);return __nativeST__(e instanceof Function?function(){e.apply(null,o)}:e,t)},window.setTimeout.isPolyfill=!0}if(document.all&&!window.setInterval.isPolyfill){var __nativeSI__=window.setInterval;window.setInterval=function(e,t){var o=Array.prototype.slice.call(arguments,2);return __nativeSI__(e instanceof Function?function(){e.apply(null,o)}:e,t)},window.setInterval.isPolyfill=!0}!function(e,t){"use strict";"function"==typeof define&&define.amd?define(["jquery"],t):t("object"==typeof exports?require("jquery"):e.jQuery)}(this,function(e){"use strict";var t=function(){};t.prototype._ajax=function(t,o,a,n){t.trigger("eldarion-ajax:begin",[t]);var r=t.triggerHandler("eldarion-ajax:modify-data",n),c="application/x-www-form-urlencoded; charset=UTF-8",i=!0,p=!0,s="object"==typeof n;r&&(n=r),s&&(c=!1,i=!1,p=!1),e.ajax({url:o,type:a,dataType:"json",data:n,cache:p,processData:i,contentType:c,headers:{"X-Eldarion-Ajax":!0}}).done(function(e,o,a){e||(e={}),t.trigger("eldarion-ajax:success",[t,e,o,a])}).fail(function(e,o,a){t.trigger("eldarion-ajax:error",[t,e,o,a])}).always(function(o,a,n){e(document).trigger("eldarion-ajax:complete",[t,o,a,n])})},t.prototype.click=function(o){var a=e(this),n=a.attr("href"),r=a.data("method"),c=a.data("data"),i=null,p=null;r||(r="get"),c&&(i={},c.split(",").map(function(t){p=t.split(":"),i[p[0]]=0===p[1].indexOf("#")?e(p[1]).val():p[1]})),o.preventDefault(),t.prototype._ajax(a,n,r,i)},t.prototype.submit=function(o){var a=e(this),n=a.attr("action"),r=a.attr("method");o.preventDefault(),void 0===window.FormData?t.prototype._ajax(a,n,r,a.serialize()):t.prototype._ajax(a,n,r,new FormData(a[0]))},t.prototype.cancel=function(t){var o=e(this),a=o.attr("data-cancel-closest");t.preventDefault(),o.closest(a).remove()},t.prototype.timeout=function(o,a){var n=e(a),r=n.data("timeout"),c=n.data("url"),i=n.data("method");i||(i="get"),window.setTimeout(t.prototype._ajax,r,n,c,i,null)},t.prototype.interval=function(o,a){var n=e(a),r=n.data("interval"),c=n.data("url"),i=n.data("method");i||(i="get"),window.setInterval(t.prototype._ajax,r,n,c,i,null)},e(function(){e("body").on("click","a.ajax",t.prototype.click),e("body").on("submit","form.ajax",t.prototype.submit),e("body").on("click","a[data-cancel-closest]",t.prototype.cancel),e("[data-timeout]").each(t.prototype.timeout),e("[data-interval]").each(t.prototype.interval)})}),function(e,t){"use strict";"function"==typeof define&&define.amd?define(["jquery"],t):t("object"==typeof exports?require("jquery"):e.jQuery)}(this,function(e){"use strict";var t=function(){};t.prototype.redirect=function(e,t,o){return o.location?(window.location.href=o.location,!1):void 0},t.prototype.replace=function(t,o,a){e(o.data("replace")).replaceWith(a.html)},t.prototype.replaceClosest=function(e,t,o){t.closest(t.data("replace-closest")).replaceWith(o.html)},t.prototype.replaceInner=function(t,o,a){e(o.data("replace-inner")).html(a.html)},t.prototype.replaceClosestInner=function(e,t,o){t.closest(t.data("replace-closest-inner")).html(o.html)},t.prototype.append=function(t,o,a){e(o.data("append")).append(a.html)},t.prototype.prepend=function(t,o,a){e(o.data("prepend")).prepend(a.html)},t.prototype.refresh=function(t,o){e.each(e(o.data("refresh")),function(t,o){e.getJSON(e(o).data("refresh-url"),function(t){e(o).replaceWith(t.html)})})},t.prototype.refreshClosest=function(t,o){e.each(e(o.data("refresh-closest")),function(t,a){e.getJSON(e(a).data("refresh-url"),function(t){o.closest(e(a)).replaceWith(t.html)})})},t.prototype.clear=function(t,o){e(o.data("clear")).html("")},t.prototype.remove=function(t,o){e(o.data("remove")).remove()},t.prototype.clearClosest=function(e,t){t.closest(t.data("clear-closest")).html("")},t.prototype.removeClosest=function(e,t){t.closest(t.data("remove-closest")).remove()},t.prototype.fragments=function(t,o,a){a.fragments&&e.each(a.fragments,function(t,o){e(t).replaceWith(o)}),a["inner-fragments"]&&e.each(a["inner-fragments"],function(t,o){e(t).html(o)}),a["append-fragments"]&&e.each(a["append-fragments"],function(t,o){e(t).append(o)}),a["prepend-fragments"]&&e.each(a["prepend-fragments"],function(t,o){e(t).prepend(o)})},e(function(){e(document).on("eldarion-ajax:success",t.prototype.redirect),e(document).on("eldarion-ajax:success",t.prototype.fragments),e(document).on("eldarion-ajax:success","[data-replace]",t.prototype.replace),e(document).on("eldarion-ajax:success","[data-replace-closest]",t.prototype.replaceClosest),e(document).on("eldarion-ajax:success","[data-replace-inner]",t.prototype.replaceInner),e(document).on("eldarion-ajax:success","[data-replace-closest-inner]",t.prototype.replaceClosestInner),e(document).on("eldarion-ajax:success","[data-append]",t.prototype.append),e(document).on("eldarion-ajax:success","[data-prepend]",t.prototype.prepend),e(document).on("eldarion-ajax:success","[data-refresh]",t.prototype.refresh),e(document).on("eldarion-ajax:success","[data-refresh-closest]",t.prototype.refreshClosest),e(document).on("eldarion-ajax:success","[data-clear]",t.prototype.clear),e(document).on("eldarion-ajax:success","[data-remove]",t.prototype.remove),e(document).on("eldarion-ajax:success","[data-clear-closest]",t.prototype.clearClosest),e(document).on("eldarion-ajax:success","[data-remove-closest]",t.prototype.removeClosest)})});<|endoftext|>


<commit_before>game.PlayerEntity = me.Entity.extend({
	init: function(x, y, settings){
		this._super(me.Entity, 'init', [x, y, {
			image: "player",
			width: 64,
			height: 64,
			spritewidth: "64",
			spriteheight: "64",
			getShape: function(){
				return(new me.Rect(0, 0, 64, 64)).toPolygon();
			}
		}]);

		this.type = "PlayerEntity";
		this.health = 20;
		this.body.setVelocity(5, 20);
		//sets movement speed
		//the "20" allows the y-location to change
		this.facing = "right";
		this.now = new Date().getTime();
		this.lastHit = this.now;
		this.lastAttack = new Date().getTime();
		//havent used attack as of video 17
		me.game.viewport.follow(this.pos, me.game.viewport.AXIS.BOTH);

		this.renderable.addAnimation("idle", [78]);
		this.renderable.addAnimation("walk", [117, 118, 119, 120, 121, 122, 123, 124, 125], 80);
		this.renderable.addAnimation("attack", [65, 66, 67, 68, 69, 70, 71, 72], 80)

		this.renderable.setCurrentAnimation("idle");
	},

	update: function(delta){
		this.now = new Date().getTime();
		if(me.input.isKeyPressed("right")){
			//adds to the position of my "x" by the velocity defined above in setVelocity() and multiplying it by me.timer.tick
			//me.timer.tick makes the movement appear smooth
			this.body.vel.x += this.body.accel.x * me.timer.tick;
			this.facing = "right";
			//keeps track of what direction your character is going
			this.flipX(true);
		}
		else if(me.input.isKeyPressed("left")){
			//adds to the position of my "x" by the velocity defined above in setVelocity() and multiplying it by me.timer.tick
			//me.timer.tick makes the movement appear smooth
			this.body.vel.x -= this.body.accel.x * me.timer.tick;
			this.facing = "left";
			//keeps track of what direction your character is going
			this.flipX(false);
		}
		else{
			this.body.vel.x = 0;
		}

		if(me.input.isKeyPressed("jump") && !this.body.jumping && !this.body.falling){
			this.body.jumping = true;
			this.body.vel.y -= this.body.accel.y * me.timer.tick;
		}
		//allows our player to jump, binds to key pressed in play.js

		if(me.input.isKeyPressed("attack")){
			if(!this.renderable.isCurrentAnimation("attack")){
				//sets the current animation to attack and once that is over goes back to the idle animation
				this.renderable.setCurrentAnimation("attack", "idle");
				//makes it so that the next time we start this sequence we begin from the first animation, not wherever we left off when we switched to another animation
				this.renderable.setAnimationFrame();
			}
		}

		else if(this.body.vel.x !== 0 && !this.renderable.isCurrentAnimation("attack")){
			if(!this.renderable.isCurrentAnimation("walk")){
				this.renderable.setCurrentAnimation("walk");
			}
		}
		//allows the character to walk
		else if(!this.renderable.isCurrentAnimation("attack")){
			this.renderable.setCurrentAnimation("idle");
		}
		//makes the character return to idle when not moving

		me.collision.check(this, true, this.collideHandler.bind(this), true);
		//passing on paramaters about character pertaining to collision

		this.body.update(delta);

		this._super(me.Entity, "update", [delta]);
		return true;
	},

	loseHealth: function(damage){
		this.health = this.health - damage;
		console.log(this.health - damage);
	},

	collideHandler: function(response){
		if(response.b.type==='EnemyBaseEntity'){
			var ydif = this.pos.y - response.b.pos.y;
			var xdif = this.pos.x - response.b.pos.x;
			//response.b represents whatever we're colliding with

			console.log("xdif" + xdif + "ydif" + ydif);

			if(ydif<-40 && xdif<70 && xdif>-35){
				this.body.falling = false;
				this.body.vel.y = -1;
			}
			//the ydif was moved to before the xdif because the console reads from top to bottom, and should take collisions from above as a first priority

			else if(xdif>-35 && this.facing==='right' && (xdif<0)){
				this.body.vel.x = 0;
				this.pos.x = this.pos.x - 1;
			}
			else if(xdif<70 && this.facing==='left' && (xdif>0)){
				this.body.vel.x = 0;
				this.pos.x = this.pos.x + 1;
			}

			if(this.renderable.isCurrentAnimation("attack") && this.now-this.lastHit >= 1000){
				console.log("tower Hit");
				this.lastHit = this.now;
				response.b.loseHealth();
			}
			//checking to see if it's been 1000 milliseconds (1 second) since the base was hit, so the player doesn't keep attacking over and over again

		}
	}

});
//classes have both entities capitalized, while methods have only the second entity in caps
game.PlayerBaseEntity = me.Entity.extend({
	init : function(x, y, settings){
		this._super(me.Entity, 'init', [x, y, {
			image: "tower",
			width: 100,
			height: 100,
			spritewidth: "100",
			spriteheight: "100",
			getShape: function(){
				return (new me.Rect(0, 0, 100, 70)).toPolygon();
			}

		}]);

		this.broken = false;
		this.health = 10;
		this.alwaysUpdate = true;
		this.body.onCollision = this.onCollision.bind(this);
		this.type = "PlayerBase";

		this.renderable.addAnimation("idle", [0]);
		this.renderable.addAnimation("broken", [1]);
		this.renderable.setCurrentAnimation("idle");
		//adds the animation of the player base to the game screen
	},

	update:function(delta){
		if(this.health<=0){
			this.broken = true;
			this.renderable.setCurrentAnimation("broken");
		}
		//kills the game if the health reaches or goes below zero
		this.body.update(delta);

		this._super(me.Entity, "update", [delta]);
		return true;
	},

	loseHealth: function(damage){
		this.health = this.health - damage;
	},

	onCollision: function(){

	}
});

game.EnemyBaseEntity = me.Entity.extend({
	init : function(x, y, settings){
		this._super(me.Entity, 'init', [x, y, {
			image: "tower",
			width: 100,
			height: 100,
			spritewidth: "100",
			spriteheight: "100",
			getShape: function(){
				return (new me.Rect(0, 0, 100, 70)).toPolygon();
			}

		}]);

		this.broken = false;
		this.health = 10;
		this.alwaysUpdate = true;
		this.body.onCollision = this.onCollision.bind(this);
		this.type = "EnemyBaseEntity";

		this.renderable.addAnimation("idle", [0]);
		this.renderable.addAnimation("broken", [1]);
		this.renderable.setCurrentAnimation("idle");
		//adds the animation of the enemy base to the game screen
	},

	update:function(delta){
		if(this.health<=0){
			this.broken = true;
			this.renderable.setCurrentAnimation("broken");
		}
		//renders the base obsolite should it reach zero
		this.body.update(delta);

		this._super(me.Entity, "update", [delta]);
		return true;
		//delta represents time
	},

	onCollision: function(){

	},

	loseHealth: function(){
		this.health--;
	}
});
//this second "base" entity is for the enemy tower

game.EnemyCreep = me.Entity.extend({
	init: function(x, y, settings){
		this._super(me.Entity, 'init', [x, y, {
			image: "creep1",
			width: 32,
			height: 64,
			spritewidth: "32",
			spriteheight: "64",
			getShape: function(){
				return (new me.Rect(0, 0, 32, 64)).toPolygon();
			}
		}]);
		this.health = 10;
		this.alwaysUpdate = true;
		this.attacking = false;
		//this.attacking lets us know if the enemy is currently attacking
		this.lastAttacking = new Date().getTime();
		//keeps track of when our creep last attacked anything
		this.lastHit = new Date().getTime();
		//keeps track of the last time our creep hit anything
		this.now = new Date().getTime();
		this.body.setVelocity(3, 20);

		this.type = "EnemyCreep";

		this.renderable.addAnimation("walk", [3, 4, 5], 80);
		this.renderable.setCurrentAnimation("walk");
	},

	update: function(delta){
		this.now = new Date().getTime();

		this.body.vel.x -= this.body.accel.x * me.timer.tick;
		//makes the creep land on the ground floor and animate in a negative direction (left)

		me.collision.check(this, true, this.collideHandler.bind(this), true);

		this.body.update(delta);

		this._super(me.Entity, "update", [delta]);
		//calls to the super

		return true;
	},

	collideHandler: function(response){
		if(response.b.type==='PlayerBase'){
			this.attacking=true;
			this.lastAttacking=this.now;
			this.body.vel.x = 0;
			//keeps moving the creep to the right to maintain its position
			this.pos.x = this.pos.x + 1;
			//checks that it has been at least one second since this creep hit a base

			if((this.now-this.lastHit >= 1000)){
				//updates the lastHit timer
				this.lastHit = this.now;
				response.b.loseHealth(1);
				//makes the player base call its loseHealth function and passes it a damage of one
			}
		}
		else if(response.b.type === 'PlayerEntity'){
			var xdif = this.pos.x - response.b.pos.x;

			this.attacking=true;
			//this.lastAttacking=this.now;
			if(xdif>0){
				this.pos.x = this.pos.x + 1;
				this.body.vel.x = 0;
			}

			if((this.now-this.lastHit >= 1000 && xdif>0)){
				this.lastHit = this.now;
				response.b.loseHealth(1);
			}
		}
	}
});
//more or less the same code as our previous entities - this time for the creeps

game.GameManager = Object.extend({
	init: function(x, y, settings){
		this.now = new Date().getTime();
		this.lastCreep = new Date().getTime();

		this.alwaysUpdate = true;
	},

	update: function(){
		this.now = new Date().getTime();

		if(Math.round(this.now/1000)%10 ===0 && (this.now - this.lastCreep >= 1000)){
			//% (mod) checks to see if we have a multiple of 10
			//makes u wait at least a second for the next creep to spawn
			this.lastCreep = this.now;
			//this.now is the timer
			var creepe = me.pool.pull("EnemyCreep", 1000, 0, {});
			me.game.world.addChild(creepe, 5);
		}
		//keeps track of our timer and whether or not new creeps should be made

		return true;
	}
});<commit_msg>Comments added to video 22<commit_after>game.PlayerEntity = me.Entity.extend({
	init: function(x, y, settings){
		this._super(me.Entity, 'init', [x, y, {
			image: "player",
			width: 64,
			height: 64,
			spritewidth: "64",
			spriteheight: "64",
			getShape: function(){
				return(new me.Rect(0, 0, 64, 64)).toPolygon();
			}
		}]);

		this.type = "PlayerEntity";
		this.health = 20;
		this.body.setVelocity(5, 20);
		//sets movement speed
		//the "20" allows the y-location to change
		this.facing = "right";
		this.now = new Date().getTime();
		this.lastHit = this.now;
		this.lastAttack = new Date().getTime();
		//havent used attack as of video 17
		me.game.viewport.follow(this.pos, me.game.viewport.AXIS.BOTH);

		this.renderable.addAnimation("idle", [78]);
		this.renderable.addAnimation("walk", [117, 118, 119, 120, 121, 122, 123, 124, 125], 80);
		this.renderable.addAnimation("attack", [65, 66, 67, 68, 69, 70, 71, 72], 80)

		this.renderable.setCurrentAnimation("idle");
	},

	update: function(delta){
		this.now = new Date().getTime();
		if(me.input.isKeyPressed("right")){
			//adds to the position of my "x" by the velocity defined above in setVelocity() and multiplying it by me.timer.tick
			//me.timer.tick makes the movement appear smooth
			this.body.vel.x += this.body.accel.x * me.timer.tick;
			this.facing = "right";
			//keeps track of what direction your character is going
			this.flipX(true);
		}
		else if(me.input.isKeyPressed("left")){
			//adds to the position of my "x" by the velocity defined above in setVelocity() and multiplying it by me.timer.tick
			//me.timer.tick makes the movement appear smooth
			this.body.vel.x -= this.body.accel.x * me.timer.tick;
			this.facing = "left";
			//keeps track of what direction your character is going
			this.flipX(false);
		}
		else{
			this.body.vel.x = 0;
		}

		if(me.input.isKeyPressed("jump") && !this.body.jumping && !this.body.falling){
			this.body.jumping = true;
			this.body.vel.y -= this.body.accel.y * me.timer.tick;
		}
		//allows our player to jump, binds to key pressed in play.js

		if(me.input.isKeyPressed("attack")){
			if(!this.renderable.isCurrentAnimation("attack")){
				//sets the current animation to attack and once that is over goes back to the idle animation
				this.renderable.setCurrentAnimation("attack", "idle");
				//makes it so that the next time we start this sequence we begin from the first animation, not wherever we left off when we switched to another animation
				this.renderable.setAnimationFrame();
			}
		}

		else if(this.body.vel.x !== 0 && !this.renderable.isCurrentAnimation("attack")){
			if(!this.renderable.isCurrentAnimation("walk")){
				this.renderable.setCurrentAnimation("walk");
			}
		}
		//allows the character to walk
		else if(!this.renderable.isCurrentAnimation("attack")){
			this.renderable.setCurrentAnimation("idle");
		}
		//makes the character return to idle when not moving

		me.collision.check(this, true, this.collideHandler.bind(this), true);
		//passing on paramaters about character pertaining to collision

		this.body.update(delta);

		this._super(me.Entity, "update", [delta]);
		return true;
	},

	loseHealth: function(damage){
		this.health = this.health - damage;
		console.log(this.health - damage);
	},
	//causes depletion of health

	collideHandler: function(response){
		if(response.b.type==='EnemyBaseEntity'){
			var ydif = this.pos.y - response.b.pos.y;
			var xdif = this.pos.x - response.b.pos.x;
			//response.b represents whatever we're colliding with

			console.log("xdif" + xdif + "ydif" + ydif);

			if(ydif<-40 && xdif<70 && xdif>-35){
				this.body.falling = false;
				this.body.vel.y = -1;
			}
			//the ydif was moved to before the xdif because the console reads from top to bottom, and should take collisions from above as a first priority

			else if(xdif>-35 && this.facing==='right' && (xdif<0)){
				this.body.vel.x = 0;
				this.pos.x = this.pos.x - 1;
			}
			else if(xdif<70 && this.facing==='left' && (xdif>0)){
				this.body.vel.x = 0;
				this.pos.x = this.pos.x + 1;
			}

			if(this.renderable.isCurrentAnimation("attack") && this.now-this.lastHit >= 1000){
				console.log("tower Hit");
				this.lastHit = this.now;
				response.b.loseHealth();
			}
			//checking to see if it's been 1000 milliseconds (1 second) since the base was hit, so the player doesn't keep attacking over and over again

		}
	}

});
//classes have both entities capitalized, while methods have only the second entity in caps
game.PlayerBaseEntity = me.Entity.extend({
	init : function(x, y, settings){
		this._super(me.Entity, 'init', [x, y, {
			image: "tower",
			width: 100,
			height: 100,
			spritewidth: "100",
			spriteheight: "100",
			getShape: function(){
				return (new me.Rect(0, 0, 100, 70)).toPolygon();
			}

		}]);

		this.broken = false;
		this.health = 10;
		this.alwaysUpdate = true;
		this.body.onCollision = this.onCollision.bind(this);
		this.type = "PlayerBase";

		this.renderable.addAnimation("idle", [0]);
		this.renderable.addAnimation("broken", [1]);
		this.renderable.setCurrentAnimation("idle");
		//adds the animation of the player base to the game screen
	},

	update:function(delta){
		if(this.health<=0){
			this.broken = true;
			this.renderable.setCurrentAnimation("broken");
		}
		//kills the game if the health reaches or goes below zero
		this.body.update(delta);

		this._super(me.Entity, "update", [delta]);
		return true;
	},

	loseHealth: function(damage){
		this.health = this.health - damage;
	},

	onCollision: function(){

	}
});

game.EnemyBaseEntity = me.Entity.extend({
	init : function(x, y, settings){
		this._super(me.Entity, 'init', [x, y, {
			image: "tower",
			width: 100,
			height: 100,
			spritewidth: "100",
			spriteheight: "100",
			getShape: function(){
				return (new me.Rect(0, 0, 100, 70)).toPolygon();
			}

		}]);

		this.broken = false;
		this.health = 10;
		this.alwaysUpdate = true;
		this.body.onCollision = this.onCollision.bind(this);
		this.type = "EnemyBaseEntity";

		this.renderable.addAnimation("idle", [0]);
		this.renderable.addAnimation("broken", [1]);
		this.renderable.setCurrentAnimation("idle");
		//adds the animation of the enemy base to the game screen
	},

	update:function(delta){
		if(this.health<=0){
			this.broken = true;
			this.renderable.setCurrentAnimation("broken");
		}
		//renders the base obsolite should it reach zero
		this.body.update(delta);

		this._super(me.Entity, "update", [delta]);
		return true;
		//delta represents time
	},

	onCollision: function(){

	},

	loseHealth: function(){
		this.health--;
	}
});
//this second "base" entity is for the enemy tower

game.EnemyCreep = me.Entity.extend({
	init: function(x, y, settings){
		this._super(me.Entity, 'init', [x, y, {
			image: "creep1",
			width: 32,
			height: 64,
			spritewidth: "32",
			spriteheight: "64",
			getShape: function(){
				return (new me.Rect(0, 0, 32, 64)).toPolygon();
			}
		}]);
		this.health = 10;
		this.alwaysUpdate = true;
		this.attacking = false;
		//this.attacking lets us know if the enemy is currently attacking
		this.lastAttacking = new Date().getTime();
		//keeps track of when our creep last attacked anything
		this.lastHit = new Date().getTime();
		//keeps track of the last time our creep hit anything
		this.now = new Date().getTime();
		this.body.setVelocity(3, 20);

		this.type = "EnemyCreep";

		this.renderable.addAnimation("walk", [3, 4, 5], 80);
		this.renderable.setCurrentAnimation("walk");
	},

	update: function(delta){
		this.now = new Date().getTime();

		this.body.vel.x -= this.body.accel.x * me.timer.tick;
		//makes the creep land on the ground floor and animate in a negative direction (left)

		me.collision.check(this, true, this.collideHandler.bind(this), true);

		this.body.update(delta);

		this._super(me.Entity, "update", [delta]);
		//calls to the super

		return true;
	},

	collideHandler: function(response){
		if(response.b.type==='PlayerBase'){
			this.attacking=true;
			this.lastAttacking=this.now;
			this.body.vel.x = 0;
			//keeps moving the creep to the right to maintain its position
			this.pos.x = this.pos.x + 1;
			//checks that it has been at least one second since this creep hit a base

			if((this.now-this.lastHit >= 1000)){
				//updates the lastHit timer
				this.lastHit = this.now;
				response.b.loseHealth(1);
				//makes the player base call its loseHealth function and passes it a damage of one
			}
		}
		else if(response.b.type === 'PlayerEntity'){
			var xdif = this.pos.x - response.b.pos.x;

			this.attacking=true;
			//this.lastAttacking=this.now;
			if(xdif>0){
				this.pos.x = this.pos.x + 1;
				this.body.vel.x = 0;
			}
			//makes sure you have to be behind the creep

			if((this.now-this.lastHit >= 1000 && xdif>0)){
				this.lastHit = this.now;
				response.b.loseHealth(1);
			}
		}
	}
});
//more or less the same code as our previous entities - this time for the creeps

game.GameManager = Object.extend({
	init: function(x, y, settings){
		this.now = new Date().getTime();
		this.lastCreep = new Date().getTime();

		this.alwaysUpdate = true;
	},

	update: function(){
		this.now = new Date().getTime();

		if(Math.round(this.now/1000)%10 ===0 && (this.now - this.lastCreep >= 1000)){
			//% (mod) checks to see if we have a multiple of 10
			//makes u wait at least a second for the next creep to spawn
			this.lastCreep = this.now;
			//this.now is the timer
			var creepe = me.pool.pull("EnemyCreep", 1000, 0, {});
			me.game.world.addChild(creepe, 5);
		}
		//keeps track of our timer and whether or not new creeps should be made

		return true;
	}
});<|endoftext|>


<commit_before>//adds a specific player
game.PlayerEntity = me.Entity.extend({
	init: function(x, y, settings) {
		this._super(me.Entity, 'init', [x, y, {
			image: "player",
			width: 64,
			height: 64,
			spritewidth: "64",
			spriteheight: "64",
			getShape: function() {
				return(new me.Rect(0, 0, 64, 64)).toPolygon();
			}
		}]);
			//sets the spawn
		this.body.setVelocity(5, 20);
		//Keeps track of which direction your character is going
		this.facing = "right";
		me.game.viewport.follow(this.pos, me.game.viewport.AXIS.BOTH);
			//grabs animation from image
		this.renderable.addAnimation("idle", [78]);
		this.renderable.addAnimation("walk", [117, 118, 119, 120, 121, 122, 123, 124, 125], 80);
		this.renderable.addAnimation("attack", [65, 66, 67, 68, 69, 70, 71, 72], 80);

		this.renderable.setCurrentAnimation("idle");

	},

	update: function(delta){
			//binds a key
		if(me.input.isKeyPressed("right")){
			//adds to the position of my x by the velocity defined above in
			//setVelocity() and multiplying it by me.timer.tick.
			//me.timer.tick makes the movement look smooth
			this.body.vel.x += this.body.accel.x * me.timer.tick;
			this.facing = "right";
			this.flipX(true);
			//set player to move left
		}else if(me.input.isKeyPressed("left")){
			this.facing = "left";
			this.body.vel.x -=this.body.accel.x * me.timer.tick;
			//flips animation
			this.flipX(false);
		}else{
			this.body.vel.x = 0;
		}
			//sets animation
			// && !this.jumping && !this.falling makes it so you can't
			// double jump while jumping or falling
		if(me.input.isKeyPressed("jump") && !this.body.jumping && !this.body.falling){
			this.body.jumping = true;
			this.body.vel.y -= this.body.accel.y * me.timer.tick;
		}

			//takes binded key from play.js and uses it
		if(me.input.isKeyPressed("attack")){
			if(!this.renderable.isCurrentAnimation("attack")){
				console.log(!this.renderable.isCurrentAnimation("attack"));
			//sets the current animation to attack and once that is over
			//goes back to the idle animation
				this.renderable.setCurrentAnimation("attack", "idle");
			//makes it so that the next time we start this sequence, we begin
			//from the first animation, not wherever we left off when we
			//switched to another animation
				this.renderable.setAnimationFrame();
			}
		}

			//sets current animation
		else if(this.body.vel.x !== 0){
			if(!this.renderable.isCurrentAnimation("walk")){
				this.renderable.setCurrentAnimation("walk");
			}
		}
		else{
			this.renderable.setCurrentAnimation("idle");
		}

		if(me.input.isKeyPressed("attack")){
			if(!this.renderable.isCurrentAnimation("attack")){
				this.renderable.setCurrentAnimation("attack", "idle");
				this.renderable.setAnimationFrame();
			}
		}
			//Makes perameter
		me.collision.check(this, true, this.collideHandler.bind(this), true);

		this.body.update(delta);

		this._super(me.Entity, "update", [delta]);
		return true;

	},
			//Hold all information for collision
	collideHandler: function(response){
		if(response.b.type==='EnemyBaseEntity'){
			var ydif = this.pos.y - response.b.pos.y;
			var xdif = this.pos.x - response.b.pos.x;

			console.log("xdif" + xdif + ydif);
			//sets barrier on right side of the enemy base
			if(xdif>-35 && this.facing=='right' && (xdif<0)){
				this.body.vel.x = 0;
				this.pos.x = this.pos.x -1;
			//sets barrier on left side of the enemy base
			// && x(y)dif>(<)0 makes it so the barrier doesn't work while facibg the other way
			}else if(xdif<70 && this.facing=='left' && xdif>0){
				this.body.vel.x = 0;
				this.pos.x = this.pos.x +1;

			}
		}
	}
});
	//adds base class
game.PlayerBaseEntity = me.Entity.extend({
	init : function(x, y, settings){
		this._super(me.Entity, 'init', [x, y, {
			//adds image
			image: "tower",
			width: 100,
			height: 100,
			spritewidth: "100",
			spriteheight: "100",
			getShape: function() {
				return (new me.Rect(0, 0, 100, 70)).toPolygon();
			}
		}]);
			//variable that say that tower is not destroyed
		this.broken = false;
		this.health = 10;
		this.alwaysUpdate = true;
		//if someone runs with the tower, they will collide
		this.body.onCollision = this.onCollision.bind(this);

		this.type = "PlayerBaseEntity";

		//adds animation for PlayerBase
		this.renderable.addAnimation("idle", [0]);
		//burning animation
		this.renderable.addAnimation("broken", [1]);
		//normal animation
		this.renderable.setCurrentAnimation("idle");
	},

	update:function(delta) {
		//if health is below 0, then you should die
		if(this.health<=0){
			this.broken = true;
			this.renderable.setCurrentAnimation("broken");
		}
		this.body.update(delta);

	this._super(me.Entity, "update", [delta]);
	return true;
	},

	onCollision: function(){

	}

});

game.EnemyBaseEntity = me.Entity.extend({
	init : function(x, y, settings){
		this._super(me.Entity, 'init', [x, y, {
			//adds image
			image: "tower",
			width: 100,
			height: 100,
			spritewidth: "100",
			spriteheight: "100",
			getShape: function() {
				return (new me.Rect(0, 0, 100, 70)).toPolygon();
			}
		}]);
			//variable that say that tower is not destroyed
		this.broken = false;
		this.health = 10;
		this.alwaysUpdate = true;
		//if someone runs with the tower, they will collide
		this.body.onCollision = this.onCollision.bind(this);

		this.type = "EnemyBaseEntity";
			//sets animation for EnemyBase
		this.renderable.addAnimation("idle", [0]);
			//burned base
		this.renderable.addAnimation("broken", [1]);
			//fixed base
		this.renderable.setCurrentAnimation("idle");
	},

	update:function(delta) {
		//if health is below 0, then you should die
		if(this.health<=0){
			this.broken = true;
			this.renderable.setCurrentAnimation("broken");
		}
		this.body.update(delta);

	this._super(me.Entity, "update", [delta]);
	return true;
	},

	onCollision: function(){

	}

});<commit_msg>Video 16 No Comments<commit_after>//adds a specific player
game.PlayerEntity = me.Entity.extend({
	init: function(x, y, settings) {
		this._super(me.Entity, 'init', [x, y, {
			image: "player",
			width: 64,
			height: 64,
			spritewidth: "64",
			spriteheight: "64",
			getShape: function() {
				return(new me.Rect(0, 0, 64, 64)).toPolygon();
			}
		}]);
			//sets the spawn
		this.body.setVelocity(5, 20);
		//Keeps track of which direction your character is going
		this.facing = "right";
		me.game.viewport.follow(this.pos, me.game.viewport.AXIS.BOTH);
			//grabs animation from image
		this.renderable.addAnimation("idle", [78]);
		this.renderable.addAnimation("walk", [117, 118, 119, 120, 121, 122, 123, 124, 125], 80);
		this.renderable.addAnimation("attack", [65, 66, 67, 68, 69, 70, 71, 72], 80);

		this.renderable.setCurrentAnimation("idle");

	},

	update: function(delta){
			//binds a key
		if(me.input.isKeyPressed("right")){
			//adds to the position of my x by the velocity defined above in
			//setVelocity() and multiplying it by me.timer.tick.
			//me.timer.tick makes the movement look smooth
			this.body.vel.x += this.body.accel.x * me.timer.tick;
			this.facing = "right";
			this.flipX(true);
			//set player to move left
		}else if(me.input.isKeyPressed("left")){
			this.facing = "left";
			this.body.vel.x -=this.body.accel.x * me.timer.tick;
			//flips animation
			this.flipX(false);
		}else{
			this.body.vel.x = 0;
		}
			//sets animation
			// && !this.jumping && !this.falling makes it so you can't
			// double jump while jumping or falling
		if(me.input.isKeyPressed("jump") && !this.body.jumping && !this.body.falling){
			this.body.jumping = true;
			this.body.vel.y -= this.body.accel.y * me.timer.tick;
		}

			//takes binded key from play.js and uses it
		if(me.input.isKeyPressed("attack")){
			if(!this.renderable.isCurrentAnimation("attack")){
				console.log(!this.renderable.isCurrentAnimation("attack"));
			//sets the current animation to attack and once that is over
			//goes back to the idle animation
				this.renderable.setCurrentAnimation("attack", "idle");
			//makes it so that the next time we start this sequence, we begin
			//from the first animation, not wherever we left off when we
			//switched to another animation
				this.renderable.setAnimationFrame();
			}
		}

			//sets current animation
		else if(this.body.vel.x !== 0){
			if(!this.renderable.isCurrentAnimation("walk")){
				this.renderable.setCurrentAnimation("walk");
			}
		}
		else{
			this.renderable.setCurrentAnimation("idle");
		}

		if(me.input.isKeyPressed("attack")){
			if(!this.renderable.isCurrentAnimation("attack")){
				this.renderable.setCurrentAnimation("attack", "idle");
				this.renderable.setAnimationFrame();
			}
		}
			//Makes perameter
		me.collision.check(this, true, this.collideHandler.bind(this), true);

		this.body.update(delta);

		this._super(me.Entity, "update", [delta]);
		return true;

	},
			//Hold all information for collision
	collideHandler: function(response){
		if(response.b.type==='EnemyBaseEntity'){
			var ydif = this.pos.y - response.b.pos.y;
			var xdif = this.pos.x - response.b.pos.x;

			console.log("xdif" + xdif + ydif);

			if(ydif<-40 && xdif< 70 && xdif>-35){
				this.body.falling = false;
				this.body.vel.y = -1;
			}
			//sets barrier on right side of the enemy base
			else if(xdif>-35 && this.facing=='right' && (xdif<0)){
				this.body.vel.x = 0;
				this.pos.x = this.pos.x -1;
			//sets barrier on left side of the enemy base
			// && x(y)dif>(<)0 makes it so the barrier doesn't work while facibg the other way
			}else if(xdif<70 && this.facing=='left' && xdif>0){
				this.body.vel.x = 0;
				this.pos.x = this.pos.x +1;
			}
		}
	}
});
	//adds base class
game.PlayerBaseEntity = me.Entity.extend({
	init : function(x, y, settings){
		this._super(me.Entity, 'init', [x, y, {
			//adds image
			image: "tower",
			width: 100,
			height: 100,
			spritewidth: "100",
			spriteheight: "100",
			getShape: function() {
				return (new me.Rect(0, 0, 100, 70)).toPolygon();
			}
		}]);
			//variable that say that tower is not destroyed
		this.broken = false;
		this.health = 10;
		this.alwaysUpdate = true;
		//if someone runs with the tower, they will collide
		this.body.onCollision = this.onCollision.bind(this);

		this.type = "PlayerBaseEntity";

		//adds animation for PlayerBase
		this.renderable.addAnimation("idle", [0]);
		//burning animation
		this.renderable.addAnimation("broken", [1]);
		//normal animation
		this.renderable.setCurrentAnimation("idle");
	},

	update:function(delta) {
		//if health is below 0, then you should die
		if(this.health<=0){
			this.broken = true;
			this.renderable.setCurrentAnimation("broken");
		}
		this.body.update(delta);

	this._super(me.Entity, "update", [delta]);
	return true;
	},

	onCollision: function(){

	}

});

game.EnemyBaseEntity = me.Entity.extend({
	init : function(x, y, settings){
		this._super(me.Entity, 'init', [x, y, {
			//adds image
			image: "tower",
			width: 100,
			height: 100,
			spritewidth: "100",
			spriteheight: "100",
			getShape: function() {
				return (new me.Rect(0, 0, 100, 70)).toPolygon();
			}
		}]);
			//variable that say that tower is not destroyed
		this.broken = false;
		this.health = 10;
		this.alwaysUpdate = true;
		//if someone runs with the tower, they will collide
		this.body.onCollision = this.onCollision.bind(this);

		this.type = "EnemyBaseEntity";
			//sets animation for EnemyBase
		this.renderable.addAnimation("idle", [0]);
			//burned base
		this.renderable.addAnimation("broken", [1]);
			//fixed base
		this.renderable.setCurrentAnimation("idle");
	},

	update:function(delta) {
		//if health is below 0, then you should die
		if(this.health<=0){
			this.broken = true;
			this.renderable.setCurrentAnimation("broken");
		}
		this.body.update(delta);

	this._super(me.Entity, "update", [delta]);
	return true;
	},

	onCollision: function(){

	}

});<|endoftext|>