Advertisement
vmars316

Quick.js

Mar 17th, 2016
177
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /**
  2.  * Copyright (c) 2014, 2015 Diogo Schneider
  3.  *
  4.  * Released under The MIT License (MIT)
  5.  *
  6.  * https://github.com/dgsprb/quick
  7.  */
  8.  
  9. (function () {
  10.  
  11.     "use strict";
  12.  
  13.     var CANVAS_TAG = "canvas";
  14.     var CONTEXT = "2d";
  15.     var KEY_DOWN = "keydown";
  16.     var KEY_UP = "keyup";
  17.     var MOUSE_DOWN = "mousedown";
  18.     var MOUSE_MOVE = "mousemove";
  19.     var MOUSE_UP = "mouseup";
  20.     var RADIAN_DEGREES = 180;
  21.     var TOUCH_END = "touchend";
  22.     var TOUCH_MOVE = "touchmove";
  23.     var TOUCH_START = "touchstart";
  24.  
  25.     var CommandEnum = {
  26.         "UP" : 0,
  27.         "DOWN" : 1,
  28.         "LEFT" : 2,
  29.         "RIGHT" : 3,
  30.         "A" : 4,
  31.         "B" : 5,
  32.         "X" : 6,
  33.         "Y" : 7,
  34.         "SELECT" : 8,
  35.         "START" : 9
  36.     };
  37.  
  38.     var Quick  = (function () {
  39.  
  40.         var DEFAULT_AUTO_SCALE = true;
  41.         var DEFAULT_FRAME_TIME = 30;
  42.         var DEFAULT_KEEP_ASPECT = false;
  43.         var DEFAULT_NAME = "Game";
  44.         var DEFAULT_NUMBER_OF_LAYERS = 1;
  45.         var IMG_TAG = "img";
  46.         var LOADING_TIMEOUT = 100;
  47.         var PX = "px";
  48.         var RESIZE_EVENT = "resize";
  49.  
  50.         var autoScale = DEFAULT_AUTO_SCALE;
  51.         var canvas;
  52.         var everyOther = true;
  53.         var frameTime;
  54.         var keepAspect = DEFAULT_KEEP_ASPECT;
  55.         var images;
  56.         var input;
  57.         var isRunning;
  58.         var isTransitioning = false;
  59.         var name = DEFAULT_NAME;
  60.         var numberOfLayers = DEFAULT_NUMBER_OF_LAYERS;
  61.         var realWidth = 0;
  62.         var realHeight = 0;
  63.         var renderableLists = [];
  64.         var scene;
  65.         var sceneFactory;
  66.         var sound;
  67.         var transition;
  68.         var width = 0, height = 0;
  69.  
  70.         var Quick = {};
  71.  
  72.         Quick.init = function (firstSceneFactory, canvasElement) {
  73.             sceneFactory = firstSceneFactory;
  74.             canvas = canvasElement || document.getElementsByTagName(CANVAS_TAG)[0];
  75.             width = canvas.width;
  76.             height = canvas.height;
  77.             realWidth = width;
  78.             realHeight = height;
  79.             images = document.getElementsByTagName(IMG_TAG);
  80.             input = new Input();
  81.             isRunning = true;
  82.             sound = new Sound();
  83.             addEventListener(RESIZE_EVENT, scale, false);
  84.             autoScale && scale();
  85.             polyfill();
  86.             this.setFrameTime();
  87.  
  88.             for (var i = 0; i < numberOfLayers; ++i) {
  89.                 renderableLists.push(new RenderableList());
  90.             }
  91.  
  92.             load();
  93.         };
  94.  
  95.         Quick.addControllerDevice = function (device) {
  96.             input.addController(device);
  97.         };
  98.  
  99.         Quick.clear = function () {
  100.             var context = canvas.getContext(CONTEXT);
  101.             context.clearRect(0, 0, width, height);
  102.         };
  103.  
  104.         Quick.fadeOut = function () {
  105.             sound.fadeOut();
  106.         };
  107.  
  108.         Quick.getBoundary = function () {
  109.             return new Rect(0, 0, Quick.getWidth(), Quick.getHeight());
  110.         };
  111.  
  112.         Quick.getBottom = function () {
  113.             return height - 1;
  114.         };
  115.  
  116.         Quick.getCenter = function () {
  117.             return new Point(this.getCenterX(), this.getCenterY());
  118.         };
  119.  
  120.         Quick.getCenterX = function () {
  121.             return Math.floor(this.getWidth() / 2);
  122.         };
  123.  
  124.         Quick.getCenterY = function () {
  125.             return Math.floor(this.getHeight() / 2);
  126.         };
  127.  
  128.         Quick.getHeight = function () {
  129.             return height;
  130.         };
  131.  
  132.         Quick.getOffsetLeft = function () {
  133.             return canvas.offsetLeft;
  134.         };
  135.  
  136.         Quick.getOffsetTop = function () {
  137.             return canvas.offsetTop;
  138.         };
  139.  
  140.         Quick.getRight = function () {
  141.             return width - 1;
  142.         };
  143.  
  144.         Quick.getController = function (id) {
  145.             return input.getController(id);
  146.         };
  147.  
  148.         Quick.getEveryOther = function () {
  149.             return everyOther;
  150.         };
  151.  
  152.         Quick.getFrameTime = function () {
  153.             return frameTime;
  154.         };
  155.  
  156.         Quick.getPointer = function (id) {
  157.             return input.getPointer(id);
  158.         };
  159.  
  160.         Quick.getRealHeight = function () {
  161.             return realHeight;
  162.         };
  163.  
  164.         Quick.getRealWidth = function () {
  165.             return realWidth;
  166.         };
  167.  
  168.         Quick.getWidth = function () {
  169.             return width;
  170.         };
  171.  
  172.         Quick.load = function () {
  173.             return localStorage.saveData && JSON.parse(localStorage.saveData);
  174.         };
  175.  
  176.         Quick.mute = function () {
  177.             sound.mute();
  178.         };
  179.  
  180.         Quick.paint = function (renderable, index) {
  181.             var layer = renderableLists[index || 0];
  182.             layer.add(renderable);
  183.         };
  184.  
  185.         Quick.play = function (id) {
  186.             sound.play(id);
  187.         };
  188.  
  189.         Quick.playTheme = function (name) {
  190.             sound.playTheme(name);
  191.         };
  192.  
  193.         Quick.random = function (ceil) {
  194.             var random = Math.random();
  195.             var raw = random * (ceil + 1);
  196.             return Math.floor(raw);
  197.         };
  198.  
  199.         Quick.save = function (data) {
  200.             localStorage.saveData = JSON.stringify(data);
  201.         };
  202.  
  203.         Quick.setAutoScale = function (customAutoScale) {
  204.             autoScale = customAutoScale == undefined || customAutoScale;
  205.         };
  206.  
  207.         Quick.setFrameTime = function (customFrameTime) {
  208.             frameTime = customFrameTime || DEFAULT_FRAME_TIME;
  209.         };
  210.  
  211.         Quick.setKeepAspect = function (customKeepAspect) {
  212.             keepAspect = customKeepAspect || DEFAULT_KEEP_ASPECT;
  213.         };
  214.  
  215.         Quick.setName = function (customName) {
  216.             name = customName;
  217.             document.title = name;
  218.         };
  219.  
  220.         Quick.setNumberOfLayers = function (customNumberOfLayers) {
  221.             numberOfLayers = customNumberOfLayers;
  222.         };
  223.  
  224.         Quick.stopTheme = function () {
  225.             sound.stopTheme();
  226.         };
  227.  
  228.         function load() {
  229.             for (var i = 0; i < images.length; ++i) {
  230.                 var image = images[i];
  231.  
  232.                 if (!image.complete) {
  233.                     setTimeout(onTimeout, LOADING_TIMEOUT);
  234.                     return;
  235.                 }
  236.             }
  237.  
  238.             scene = sceneFactory();
  239.             loop();
  240.  
  241.             function onTimeout() {
  242.                 load();
  243.             }
  244.         }
  245.  
  246.         function loop() {
  247.             var startTime = Date.now();
  248.             var context = canvas.getContext(CONTEXT);
  249.             everyOther = !everyOther;
  250.             input.update();
  251.  
  252.             if (transition != null) {
  253.                 if (transition.sync()) {
  254.                     transition = null;
  255.                 }
  256.             } else {
  257.                 if (isTransitioning) {
  258.                     isTransitioning = false;
  259.                     scene = scene.getNext();
  260.                 }
  261.  
  262.                 if (scene.sync()) {
  263.                     isTransitioning = true;
  264.                     transition = scene.getTransition();
  265.                 } else {
  266.                     scene.update();
  267.                 }
  268.             }
  269.  
  270.             sound.update();
  271.  
  272.             for (var i = 0; i < renderableLists.length; ++i) {
  273.                 var layer = renderableLists[i];
  274.                 layer.render(context);
  275.             }
  276.  
  277.             var elapsedTime = Date.now() - startTime;
  278.             var interval = frameTime - elapsedTime;
  279.             setTimeout(onTimeout, interval);
  280.  
  281.             function onTimeout() {
  282.                 isRunning && requestAnimationFrame(loop);
  283.             }
  284.         }
  285.  
  286.         function polyfill() {
  287.             if (!window.requestAnimationFrame) {
  288.                 window.requestAnimationFrame = requestAnimationFrameFacade;
  289.             }
  290.  
  291.             function requestAnimationFrameFacade(functionReference) {
  292.                 functionReference();
  293.             }
  294.         }
  295.  
  296.         function scale() {
  297.             var width, height;
  298.  
  299.             if (keepAspect) {
  300.                 var proportion = window.innerWidth / canvas.width;
  301.  
  302.                 if (window.innerHeight < canvas.height * proportion) {
  303.                     proportion = window.innerHeight / canvas.height;
  304.                 }
  305.  
  306.                 width = canvas.width * proportion;
  307.                 height = canvas.height * proportion
  308.             } else {
  309.                 width = window.innerWidth;
  310.                 height = window.innerHeight;
  311.             }
  312.  
  313.             realWidth = width;
  314.             realHeight = height;
  315.             canvas.style.width = width + PX;
  316.             canvas.style.height = height + PX;
  317.         }
  318.  
  319.         return Quick;
  320.  
  321.     })();
  322.  
  323.     var ImageFactory = (function () {
  324.  
  325.         var ImageFactory = {};
  326.  
  327.         ImageFactory.flip = function (image) {
  328.             return invert(image, false, true);
  329.         };
  330.  
  331.         ImageFactory.mirror = function (image) {
  332.             return invert(image, true, false);
  333.         };
  334.  
  335.         ImageFactory.rotate = function (image, degrees) {
  336.             if (degrees % 360 == 0 ) {
  337.                 return image;
  338.             }
  339.  
  340.             var radians = toRadians(degrees);
  341.             var canvas = document.createElement(CANVAS_TAG);
  342.             var sideA = image.width;
  343.             var sideB = image.height;
  344.  
  345.             if (degrees == 90 || degrees == 270) {
  346.                 sideA = image.height;
  347.                 sideB = image.width;
  348.             }
  349.  
  350.             canvas.width = sideA;
  351.             canvas.height = sideB;
  352.             var context = canvas.getContext(CONTEXT);
  353.             context.translate(canvas.width / 2, canvas.height / 2);
  354.             context.rotate(radians);
  355.             context.drawImage(image, -image.width / 2, -image.height / 2);
  356.             return canvas;
  357.         };
  358.  
  359.         function invert(image, isMirror, isFlip) {
  360.             var canvas = document.createElement(CANVAS_TAG);
  361.             canvas.width = image.width;
  362.             canvas.height = image.height;
  363.             var context = canvas.getContext(CONTEXT);
  364.             context.translate(isMirror ? canvas.width : 0, isFlip ? canvas.height : 0);
  365.             context.scale(isMirror ? -1 : 1, isFlip ? - 1 : 1);
  366.             context.drawImage(image, 0, 0);
  367.             return canvas;
  368.         }
  369.  
  370.         return ImageFactory;
  371.  
  372.     })();
  373.  
  374.     var Mouse = (function () {
  375.  
  376.         function Mouse(event) {
  377.             var that = this;
  378.             this.buffer = false;
  379.             this.position = new Point();
  380.             addEventListener(MOUSE_DOWN, onMouseDown, false);
  381.             addEventListener(MOUSE_MOVE, onMouseMove, false);
  382.             addEventListener(MOUSE_UP, onMouseUp, false);
  383.             event && onMouseDown(event);
  384.  
  385.             function onMouseDown(event) {
  386.                 event.preventDefault();
  387.                 that.buffer = true;
  388.             }
  389.  
  390.             function onMouseUp(event) {
  391.                 event.preventDefault();
  392.                 that.buffer = false;
  393. // vm               console.log(' function onMouseUp(event) ');
  394.             }
  395.  
  396.             function onMouseMove(event) {
  397.                 event.preventDefault();
  398.                 that.updateCoordinates(event);
  399.             }
  400.         }
  401.  
  402.         Mouse.prototype.getCommand = function () {
  403.             return this.buffer;
  404.         };
  405.  
  406.         Mouse.prototype.getX = function () {
  407.             return this.position.getX();
  408.         };
  409.  
  410.         Mouse.prototype.getY = function () {
  411.             return this.position.getY();
  412.         };
  413.  
  414.         Mouse.prototype.updateCoordinates = function (event) {
  415.             this.position.setX(event.x || event.clientX);
  416.             this.position.setY(event.y || event.clientY);
  417.         };
  418.  
  419.         return Mouse;
  420.  
  421.     })();
  422.  
  423.     var Touch = (function () {
  424.  
  425.         var CHANGED_TOUCHES = "changedTouches";
  426.  
  427.         function Touch(event) {
  428.             var that = this;
  429.             this.buffer = false;
  430.             this.position = new Point();
  431.             addEventListener(TOUCH_END, onTouchEnd, false);
  432.             addEventListener(TOUCH_MOVE, onTouchMove, false);
  433.             addEventListener(TOUCH_START, onTouchStart, false);
  434.             onTouchStart(event);
  435.  
  436.             function onTouchEnd(event) {
  437.                 event.preventDefault();
  438.                 that.buffer = false;
  439.                 that.updateCoordinates(event);
  440.             }
  441.  
  442.             function onTouchMove(event) {
  443.                 event.preventDefault();
  444.                 that.updateCoordinates(event);
  445.             }
  446.  
  447.             function onTouchStart(event) {
  448.                 event.preventDefault();
  449.                 that.buffer = true;
  450.                 that.updateCoordinates(event);
  451.             }
  452.         }
  453.  
  454.         Touch.prototype.getCommand = function () {
  455.             return this.buffer;
  456.         };
  457.  
  458.         Touch.prototype.getX = function () {
  459.             return this.position.getX();
  460.         };
  461.  
  462.         Touch.prototype.getY = function () {
  463.             return this.position.getY();
  464.         };
  465.  
  466.         Touch.prototype.updateCoordinates = function (event) {
  467.             var touches = event[CHANGED_TOUCHES];
  468.             var touch = touches[0];
  469.             this.position.setX(touch.pageX);
  470.             this.position.setY(touch.pageY);
  471.         };
  472.  
  473.         return Touch;
  474.  
  475.     })();
  476.  
  477.     var Pointer = (function () {
  478.  
  479.         function Pointer() {
  480.             this.active = false;
  481.             this.device = null;
  482.             this.hold = false;
  483.             this.position = new Point();
  484.         }
  485.  
  486.         Pointer.prototype.getDown = function () {
  487.             return this.active;
  488.         };
  489.  
  490.         Pointer.prototype.getPush = function () {
  491.             return this.active && !this.hold;
  492.         };
  493.  
  494.         Pointer.prototype.setDevice = function (device) {
  495.             this.device = device;
  496.         };
  497.  
  498.         Pointer.prototype.update = function () {
  499.             if (!this.device) {
  500.                 return;
  501.             }
  502.  
  503.             this.hold = false;
  504.             var last = this.active;
  505.             this.active = this.device.getCommand();
  506.  
  507.             if (this.active && last) {
  508.                 this.hold = true;
  509.             }
  510.  
  511.             var realX = this.device.getX() - Quick.getOffsetLeft();
  512.             var realY = this.device.getY() - Quick.getOffsetTop();
  513.             this.position.setX(Math.floor(realX * Quick.getWidth() / Quick.getRealWidth()));
  514.             this.position.setY(Math.floor(realY * Quick.getHeight() / Quick.getRealHeight()));
  515.         };
  516.  
  517.         Pointer.prototype.getPosition = function () {
  518.             return this.position;
  519.         };
  520.  
  521.         return Pointer;
  522.  
  523.     })();
  524.  
  525.     var Controller = (function () {
  526.  
  527.         function Controller() {
  528.             this.active = {};
  529.             this.device = null;
  530.             this.hold = {};
  531.         }
  532.  
  533.         Controller.prototype.keyDown = function (commandEnum) {
  534.             return this.active[commandEnum];
  535.         };
  536.  
  537.         Controller.prototype.keyPush = function (commandEnum) {
  538.             return this.active[commandEnum] && !this.hold[commandEnum];
  539.         };
  540.  
  541.         Controller.prototype.setDevice = function (device) {
  542.             this.device = device;
  543.         };
  544.  
  545.         Controller.prototype.update = function () {
  546.             if (!this.device) {
  547.                 return;
  548.             }
  549.  
  550.             this.hold = {};
  551.             var last = this.active;
  552.             this.active = this.device.getCommands();
  553.  
  554.             for (var i in this.active) {
  555.                 if (this.active.hasOwnProperty(i)) {
  556.                     if (last[i]) {
  557.                         this.hold[i] = true;
  558.                     }
  559.                 }
  560.             }
  561.         };
  562.  
  563.         return Controller;
  564.  
  565.     })();
  566.  
  567.     var GamePad = (function () {
  568.  
  569.         var ANALOG_THRESHOLD = 0.5;
  570.         var PRESSED = "pressed";
  571.  
  572.         var AxisEnum = {
  573.             "LEFT_X" : 0,
  574.             "LEFT_Y" : 1,
  575.             "RIGHT_X" : 2,
  576.             "RIGHT_Y" : 3
  577.         };
  578.  
  579.         var ButtonEnum = {
  580.             "A" : 0,
  581.             "B" : 1,
  582.             "X" : 2,
  583.             "Y" : 3,
  584.             "L1" : 4,
  585.             "R1" : 5,
  586.             "L2" : 6,
  587.             "R2" : 7,
  588.             "SELECT" : 8,
  589.             "START" : 9,
  590.             "L3" : 10,
  591.             "R3" : 11,
  592.             "UP" : 12,
  593.             "DOWN" : 13,
  594.             "LEFT" : 14,
  595.             "RIGHT" : 15
  596.         };
  597.  
  598.         var ButtonToCommandMap = {};
  599.             ButtonToCommandMap[ButtonEnum.UP] = CommandEnum.UP;
  600.             ButtonToCommandMap[ButtonEnum.DOWN] = CommandEnum.DOWN;
  601.             ButtonToCommandMap[ButtonEnum.LEFT] = CommandEnum.LEFT;
  602.             ButtonToCommandMap[ButtonEnum.RIGHT] = CommandEnum.RIGHT;
  603.             ButtonToCommandMap[ButtonEnum.A] = CommandEnum.A;
  604.             ButtonToCommandMap[ButtonEnum.B] = CommandEnum.B;
  605.             ButtonToCommandMap[ButtonEnum.X] = CommandEnum.X;
  606.             ButtonToCommandMap[ButtonEnum.Y] = CommandEnum.Y;
  607.             ButtonToCommandMap[ButtonEnum.START] = CommandEnum.START;
  608.             ButtonToCommandMap[ButtonEnum.SELECT] = CommandEnum.SELECT;
  609.  
  610.         function GamePad(id) {
  611.             this.id = id || 0;
  612.         }
  613.  
  614.         GamePad.prototype.getCommands = function () {
  615.             var result = {};
  616.  
  617.             if (Input.getGamePadAxes(this.id)[AxisEnum.LEFT_Y] < - ANALOG_THRESHOLD) {
  618.                 result[CommandEnum.UP] = true;
  619.             } else if (Input.getGamePadAxes(this.id)[AxisEnum.LEFT_Y] > ANALOG_THRESHOLD) {
  620.                 result[CommandEnum.DOWN] = true;
  621.             }
  622.  
  623.             if (Input.getGamePadAxes(this.id)[AxisEnum.LEFT_X] < - ANALOG_THRESHOLD) {
  624.                 result[CommandEnum.LEFT] = true;
  625.             } else if (Input.getGamePadAxes(this.id)[AxisEnum.LEFT_X] > ANALOG_THRESHOLD) {
  626.                 result[CommandEnum.RIGHT] = true;
  627.             }
  628.  
  629.             var buttons = Input.getGamePadButtons(this.id);
  630.  
  631.             for (var i in ButtonToCommandMap) {
  632.                 if (ButtonToCommandMap.hasOwnProperty(i)) {
  633.                     if (buttons[i] && buttons[i][PRESSED]) {
  634.                         result[ButtonToCommandMap[i]] = true;
  635.                     }
  636.                 }
  637.             }
  638.  
  639.             return result;
  640.         };
  641.  
  642.         return GamePad;
  643.  
  644.     })();
  645.  
  646.     var Input = (function () {
  647.  
  648.         var AXES = "axes";
  649.  
  650.         function Input() {
  651.             this.controllers = [];
  652.             this.controllerQueue = [];
  653.             this.controllerRequestQueue = [];
  654.             this.pointers = [];
  655.             this.pointerQueue = [];
  656.             this.pointerRequestQueue = [];
  657.             this.gamePads = 0;
  658.             this.waitKeyboard();
  659.             this.waitMouse();
  660.             this.waitTouch();
  661.         }
  662.  
  663.         Input.getGamePadAxes = function (id) {
  664.             if (getGamePads()[id]) {
  665.                 return getGamePads()[id][AXES];
  666.             }
  667.  
  668.             return [];
  669.         };
  670.  
  671.         Input.getGamePadButtons = function (id) {
  672.             var gamePad = getGamePads()[id];
  673.             return gamePad && gamePad.buttons || [];
  674.         };
  675.  
  676.         Input.prototype.addController = function (device) {
  677.             this.controllerQueue.push(device);
  678.             this.checkControllerQueues();
  679.         };
  680.  
  681.         Input.prototype.addPointer = function (device) {
  682.             this.pointerQueue.push(device);
  683.             this.checkPointerQueues();
  684.         };
  685.  
  686.         Input.prototype.checkGamePads = function () {
  687.             if (getGamePads()[this.gamePads]) {
  688.                 this.addController(new GamePad(this.gamePads++));
  689.             }
  690.         };
  691.  
  692.         Input.prototype.checkControllerQueues = function () {
  693.             if (this.controllerRequestQueue.length > 0 && this.controllerQueue.length > 0) {
  694.                 var requester = this.controllerRequestQueue.shift();
  695.                 var device = this.controllerQueue.shift();
  696.                 requester.setDevice(device);
  697.             }
  698.         };
  699.  
  700.         Input.prototype.checkPointerQueues = function () {
  701.             if (this.pointerRequestQueue.length > 0 && this.pointerQueue.length > 0) {
  702.                 var requester = this.pointerRequestQueue.shift();
  703.                 var device = this.pointerQueue.shift();
  704.                 requester.setDevice(device);
  705.             }
  706.         };
  707.  
  708.         Input.prototype.getController = function (id) {
  709.             id = id || 0;
  710.  
  711.             if (this.controllers.length < id + 1) {
  712.                 var controller = new Controller();
  713.                 this.controllers.push(controller);
  714.                 this.controllerRequestQueue.push(controller);
  715.                 this.checkControllerQueues();
  716.             }
  717.  
  718.             return this.controllers[id];
  719.         };
  720.  
  721.         Input.prototype.getPointer = function (id) {
  722.             id = id || 0;
  723.  
  724.             if (this.pointers.length < id + 1) {
  725.                 var pointer = new Pointer();
  726.                 this.pointers.push(pointer);
  727.                 this.pointerRequestQueue.push(pointer);
  728.                 this.checkPointerQueues();
  729.             }
  730.  
  731.             return this.pointers[id];
  732.         };
  733.  
  734.         Input.prototype.update = function () {
  735.             this.checkGamePads();
  736.  
  737.             for (var i in this.controllers) {
  738.                 if (this.controllers.hasOwnProperty(i)) {
  739.                     var controller = this.controllers[i];
  740.                     controller.update();
  741.                 }
  742.             }
  743.  
  744.             for (var j in this.pointers) {
  745.                 if (this.pointers.hasOwnProperty(j)) {
  746.                     var pointer = this.pointers[j];
  747.                     pointer.update();
  748.                 }
  749.             }
  750.         };
  751.  
  752.         Input.prototype.waitKeyboard = function () {
  753.             var that = this;
  754.             addEventListener(KEY_DOWN, onKeyDown, false);
  755.  
  756.             function onKeyDown(event) {
  757.                 removeEventListener(KEY_DOWN, onKeyDown, false);
  758.                 that.addController(new Keyboard(event));
  759.             }
  760.         };
  761.  
  762.         Input.prototype.waitMouse = function () {
  763.             var that = this;
  764.             addEventListener(MOUSE_DOWN, onMouseDown, false);
  765.  
  766.             function onMouseDown(event) {
  767.                 removeEventListener(MOUSE_DOWN, onMouseDown, false);
  768.                 that.addPointer(new Mouse(event));
  769.             }
  770.         };
  771.  
  772.         Input.prototype.waitTouch = function () {
  773.             var that = this;
  774.             addEventListener(TOUCH_START, onTouchStart, false);
  775.  
  776.             function onTouchStart(event) {
  777.                 removeEventListener(TOUCH_START, onTouchStart, false);
  778.                 that.addPointer(new Touch(event));
  779.             }
  780.         };
  781.  
  782.         function getGamePads() {
  783.             if (navigator.getGamepads) {
  784.                 return navigator.getGamepads();
  785.             }
  786.  
  787.             return [];
  788.         }
  789.  
  790.         return Input;
  791.  
  792.     })();
  793.  
  794.     var Keyboard = (function () {
  795.  
  796.         var KeyEnum = {
  797.             "ENTER" : 13,
  798.             "SHIFT" : 16,
  799.             "CTRL" : 17,
  800.             "ALT" : 18,
  801.             "ESC" : 27,
  802.             "SPACE" : 32,
  803.             "LEFT" : 37,
  804.             "UP" : 38,
  805.             "RIGHT" : 39,
  806.             "DOWN" : 40,
  807.             "D" : 68,
  808.             "E" : 69,
  809.             "F" : 70,
  810.             "I" : 73,
  811.             "J" : 74,
  812.             "K" : 75,
  813.             "L" : 76,
  814.             "S" : 83,
  815.             "F5" : 116,
  816.             "F11" : 122,
  817.             "F12" : 123
  818.         };
  819.  
  820.         var KeyToCommandMap = {};
  821.             KeyToCommandMap[KeyEnum.UP] = CommandEnum.UP;
  822.             KeyToCommandMap[KeyEnum.E] = CommandEnum.UP;
  823.             KeyToCommandMap[KeyEnum.I] = CommandEnum.UP;
  824.             KeyToCommandMap[KeyEnum.DOWN] = CommandEnum.DOWN;
  825.             KeyToCommandMap[KeyEnum.D] = CommandEnum.DOWN;
  826.             KeyToCommandMap[KeyEnum.K] = CommandEnum.DOWN;
  827.             KeyToCommandMap[KeyEnum.LEFT] = CommandEnum.LEFT;
  828.             KeyToCommandMap[KeyEnum.S] = CommandEnum.LEFT;
  829.             KeyToCommandMap[KeyEnum.J] = CommandEnum.LEFT;
  830.             KeyToCommandMap[KeyEnum.RIGHT] = CommandEnum.RIGHT;
  831.             KeyToCommandMap[KeyEnum.F] = CommandEnum.RIGHT;
  832.             KeyToCommandMap[KeyEnum.L] = CommandEnum.RIGHT;
  833.             KeyToCommandMap[KeyEnum.SPACE] = CommandEnum.A;
  834.             KeyToCommandMap[KeyEnum.ALT] = CommandEnum.B;
  835.             KeyToCommandMap[KeyEnum.CTRL] = CommandEnum.X;
  836.             KeyToCommandMap[KeyEnum.SHIFT] = CommandEnum.Y;
  837.             KeyToCommandMap[KeyEnum.ENTER] = CommandEnum.START;
  838.             KeyToCommandMap[KeyEnum.ESC] = CommandEnum.SELECT;
  839.  
  840.         var PassThrough = [];
  841.             PassThrough[KeyEnum.F5] = true;
  842.             PassThrough[KeyEnum.F11] = true;
  843.             PassThrough[KeyEnum.F12] = true;
  844.  
  845.         function Keyboard(event) {
  846.             var that = this;
  847.             this.buffer = {};
  848.             addEventListener(KEY_DOWN, onKeyDown, false);
  849.             addEventListener(KEY_UP, onKeyUp, false);
  850.             onKeyDown(event);
  851.  
  852.             function onKeyDown(event) {
  853.                 PassThrough[event.keyCode] || event.preventDefault();
  854.                 onKey(event.keyCode, true);
  855.             }
  856.  
  857.             function onKeyUp(event) {
  858.                 onKey(event.keyCode, false);
  859.             }
  860.  
  861.             function onKey(keyCode, isDown) {
  862.                 that.buffer[KeyToCommandMap[keyCode]] = isDown;
  863.             }
  864.         }
  865.  
  866.         Keyboard.prototype.getCommands = function () {
  867.             var result = {};
  868.  
  869.             for (var i in this.buffer) {
  870.                 if (this.buffer.hasOwnProperty(i)) {
  871.                     if (this.buffer[i]) {
  872.                         result[i] = true;
  873.                     }
  874.                 }
  875.             }
  876.  
  877.             return result;
  878.         };
  879.  
  880.         return Keyboard;
  881.  
  882.     })();
  883.  
  884.     var RenderableList = (function () {
  885.  
  886.         function RenderableList() {
  887.             this.elements = [];
  888.         }
  889.  
  890.         RenderableList.prototype.add = function (renderable) {
  891.             this.elements.push(renderable);
  892.         };
  893.  
  894.         RenderableList.prototype.render = function (context) {
  895.             for (var i = 0; i < this.elements.length; ++i) {
  896.                 var renderable = this.elements[i];
  897.                 renderable.render(context);
  898.             }
  899.  
  900.             this.elements.length = 0;
  901.         };
  902.  
  903.         return RenderableList;
  904.  
  905.     })();
  906.  
  907.     var Scene = (function () {
  908.  
  909.         function Scene() {
  910.             this.delegate = null;
  911.             this.gameObjects = [];
  912.             this.nextObjects = [];
  913.             this.expiration = -1;
  914.             this.isExpired = false;
  915.             this.tick = -1;
  916.             this.transition = null;
  917.         }
  918.  
  919.         Scene.prototype.add = function (gameObject) {
  920.             gameObject.setScene(this);
  921.             gameObject.init();
  922.             this.nextObjects.push(gameObject);
  923.             gameObject.move(gameObject.getSpeedX() * -1, gameObject.getSpeedY() * -1);
  924.         };
  925.  
  926.         Scene.prototype.build = function (map, tileFactory, offsetX, offsetY) {
  927.             tileFactory = tileFactory || function (id) { return new BaseTile(id) };
  928.  
  929.             for (var i = 0; i < map.length; ++i) {
  930.                 var line = map[i];
  931.  
  932.                 for (var j = 0; j < line.length; ++j) {
  933.                     var id = map[i][j];
  934.  
  935.                     if (id) {
  936.                         var tile = tileFactory(id);
  937.                         var x = offsetX ? offsetX : tile.getWidth();
  938.                         var y = offsetY ? offsetY : tile.getHeight();
  939.                         tile.setTop(i * y);
  940.                         tile.setLeft(j * x);
  941.                         this.add(tile);
  942.                     }
  943.                 }
  944.             }
  945.  
  946.         };
  947.  
  948.         Scene.prototype.expire = function () {
  949.             this.isExpired = true;
  950.         };
  951.  
  952.         Scene.prototype.sync = function () {
  953.             if (this.isExpired) {
  954.                 return true;
  955.             }
  956.  
  957.             var gameObjects = [];
  958.             var solidGameObjects = [];
  959.  
  960.             for (var i = 0; i < this.gameObjects.length; ++i) {
  961.                 var gameObject = this.gameObjects[i];
  962.                 gameObject.update();
  963.  
  964.                 if (gameObject.sync()) {
  965.                     if (gameObject.getEssential()) {
  966.                         this.expire();
  967.                     }
  968.                 } else {
  969.                     if (gameObject.getSolid()) {
  970.                         solidGameObjects.push(gameObject);
  971.                     }
  972.  
  973.                     gameObjects.push(gameObject);
  974.                     Quick.paint(gameObject, gameObject.getLayerIndex());
  975.                 }
  976.             }
  977.  
  978.             checkCollisions(solidGameObjects);
  979.             this.gameObjects = gameObjects.concat(this.nextObjects);
  980.             this.nextObjects = [];
  981.  
  982.             if (++this.tick == this.expiration) {
  983.                 this.expire();
  984.             }
  985.  
  986.             return false;
  987.         };
  988.  
  989.         Scene.prototype.getNext = function () {
  990.             if (this.delegate && this.delegate.getNext) {
  991.                 return this.delegate.getNext();
  992.             }
  993.         };
  994.  
  995.         Scene.prototype.getObjectsWithTag = function (tag) {
  996.             var result = [];
  997.  
  998.             for (var i = 0; i < this.gameObjects.length; ++i) {
  999.                 var gameObject = this.gameObjects[i];
  1000.  
  1001.                 if (gameObject.hasTag(tag)) {
  1002.                     result.push(gameObject);
  1003.                 }
  1004.             }
  1005.  
  1006.             return result;
  1007.         };
  1008.  
  1009.         Scene.prototype.getTick = function () {
  1010.             return this.tick;
  1011.         };
  1012.  
  1013.         Scene.prototype.getTransition = function () {
  1014.             return this.transition;
  1015.         };
  1016.  
  1017.         Scene.prototype.setDelegate = function (delegate) {
  1018.             this.delegate = delegate;
  1019.         };
  1020.  
  1021.         Scene.prototype.setExpiration = function (expiration) {
  1022.             this.expiration = expiration;
  1023.         };
  1024.  
  1025.         Scene.prototype.setTransition = function (transition) {
  1026.             this.transition = transition;
  1027.         };
  1028.  
  1029.         Scene.prototype.update = function () {
  1030.             this.delegate && this.delegate.update && this.delegate.update();
  1031.         };
  1032.  
  1033.         function checkCollisions(gameObjects) {
  1034.             var length = gameObjects.length;
  1035.  
  1036.             for (var i = 0; i < length - 1; ++i) {
  1037.                 var leftGameObject = gameObjects[i];
  1038.  
  1039.                 for (var j = i + 1; j < length; ++j) {
  1040.                     var rightGameObject = gameObjects[j];
  1041.  
  1042.                     if (leftGameObject.hasCollision(rightGameObject)) {
  1043.                         leftGameObject.onCollision(rightGameObject);
  1044.                         rightGameObject.onCollision(leftGameObject);
  1045.                     }
  1046.                 }
  1047.             }
  1048.         }
  1049.  
  1050.         return Scene;
  1051.  
  1052.     })();
  1053.  
  1054.     var Sound = (function () {
  1055.  
  1056.         var DEFAULT_MUTE = false;
  1057.         var DEFAULT_SOUND_EFFECTS_VOLUME = 0.3;
  1058.  
  1059.         function Sound() {
  1060.             this.isFading = false;
  1061.             this.isMute = DEFAULT_MUTE;
  1062.             this.nextThemeName = null;
  1063.             this.queue = {};
  1064.             this.theme = null;
  1065.             this.volume = 100;
  1066.         }
  1067.  
  1068.         Sound.prototype.fadeOut = function () {
  1069.             if (!this.theme) {
  1070.                 return;
  1071.             }
  1072.  
  1073.             this.isFading = true;
  1074.             this.volume = 100;
  1075.         };
  1076.  
  1077.         Sound.prototype.mute = function () {
  1078.             this.isMute = !this.isMute;
  1079.  
  1080.             if (!this.isMute) {
  1081.                 this.theme.play();
  1082.             } else {
  1083.                 this.theme.pause();
  1084.             }
  1085.         };
  1086.  
  1087.         Sound.prototype.pause = function () {
  1088.             if (this.theme) {
  1089.                 this.theme.pause();
  1090.             }
  1091.         };
  1092.  
  1093.         Sound.prototype.play = function (id) {
  1094.             if (this.isMute) {
  1095.                 return;
  1096.             }
  1097.  
  1098.             this.queue[id] = true;
  1099.         };
  1100.  
  1101.         Sound.prototype.playTheme = function (id) {
  1102.             if (this.theme && this.theme.currentTime > 0) {
  1103.                 this.nextThemeName = id;
  1104.  
  1105.                 if (!this.isFading) {
  1106.                     this.fadeOut();
  1107.                 }
  1108.  
  1109.                 return;
  1110.             }
  1111.  
  1112.             this.stopTheme();
  1113.             this.theme = document.getElementById(id);
  1114.  
  1115.             if (this.theme.currentTime > 0) {
  1116.                 this.theme.currentTime = 0;
  1117.             }
  1118.  
  1119.             if (this.isMute) {
  1120.                 return;
  1121.             }
  1122.  
  1123.             this.theme.volume = 1;
  1124.             this.theme.play();
  1125.         };
  1126.  
  1127.         Sound.prototype.resume = function () {
  1128.             if (this.isMute) {
  1129.                 return;
  1130.             }
  1131.  
  1132.             if (this.theme.paused) {
  1133.                 this.theme.play();
  1134.             }
  1135.         };
  1136.  
  1137.         Sound.prototype.stopTheme = function () {
  1138.             if (this.theme) {
  1139.                 this.theme.pause();
  1140.                 this.theme.currentTime = 0;
  1141.             }
  1142.         };
  1143.  
  1144.         Sound.prototype.update = function () {
  1145.             for (var i in this.queue) {
  1146.                 if (this.queue.hasOwnProperty(i)) {
  1147.                     var sound = document.getElementById(i);
  1148.                     sound.pause();
  1149.  
  1150.                     if (sound.currentTime > 0) {
  1151.                         sound.currentTime = 0;
  1152.                     }
  1153.  
  1154.                     sound.volume = DEFAULT_SOUND_EFFECTS_VOLUME;
  1155.                     sound.play();
  1156.                 }
  1157.             }
  1158.  
  1159.             this.queue = {};
  1160.  
  1161.             if (this.isFading) {
  1162.                 if (--this.volume > 0) {
  1163.                     this.theme.volume = this.volume / 100;
  1164.                 } else {
  1165.                     this.isFading = false;
  1166.                     this.theme = null;
  1167.  
  1168.                     if (this.nextThemeName) {
  1169.                         this.playTheme(this.nextThemeName);
  1170.                         this.nextThemeName = null;
  1171.                     }
  1172.                 }
  1173.             }
  1174.         };
  1175.  
  1176.         return Sound;
  1177.  
  1178.     })();
  1179.  
  1180.     var Point = (function () {
  1181.  
  1182.         function Point(x, y) {
  1183.             this.setAccelerationX();
  1184.             this.setAccelerationY();
  1185.             this.setMaxSpeedX();
  1186.             this.setMaxSpeedY();
  1187.             this.setSpeedX();
  1188.             this.setSpeedY();
  1189.             this.setX(x);
  1190.             this.setY(y);
  1191.             this.lastX = this.x;
  1192.             this.lastY = this.y;
  1193.         }
  1194.  
  1195.         Point.prototype.bounceX = function () {
  1196.             this.setSpeedX(this.getSpeedX() * -1);
  1197.             this.moveX(this.getSpeedX());
  1198.         };
  1199.  
  1200.         Point.prototype.bounceY = function () {
  1201.             this.setSpeedY(this.getSpeedY() * -1);
  1202.             this.moveY(this.getSpeedY());
  1203.         };
  1204.  
  1205.         Point.prototype.getAccelerationX = function () {
  1206.             return this.accelerationX;
  1207.         };
  1208.  
  1209.         Point.prototype.getAccelerationY = function () {
  1210.             return this.accelerationY;
  1211.         };
  1212.  
  1213.         Point.prototype.getAngle = function () {
  1214.             return toDegrees(Math.atan2(this.getSpeedY(), this.getSpeedX()));
  1215.         };
  1216.  
  1217.         Point.prototype.getCenter = function () {
  1218.             return this;
  1219.         };
  1220.  
  1221.         Point.prototype.getCenterX = function () {
  1222.             return this.x;
  1223.         };
  1224.  
  1225.         Point.prototype.getCenterY = function () {
  1226.             return this.y;
  1227.         };
  1228.  
  1229.         Point.prototype.getDirection = function () {
  1230.             var direction = new Direction();
  1231.  
  1232.             if (this.getX() < this.getLastX()) {
  1233.                 direction.setLeft();
  1234.             } else if (this.getX() > this.getLastX()) {
  1235.                 direction.setRight();
  1236.             }
  1237.  
  1238.             if (this.getY() < this.getLastY()) {
  1239.                 direction.setTop();
  1240.             } else if (this.getY() > this.getLastY()) {
  1241.                 direction.setBottom();
  1242.             }
  1243.  
  1244.             return direction;
  1245.         };
  1246.  
  1247.         Point.prototype.getLastPosition = function () {
  1248.             return new Point(this.getLastX(), this.getLastY());
  1249.         };
  1250.  
  1251.         Point.prototype.getLastX = function () {
  1252.             return this.lastX;
  1253.         };
  1254.  
  1255.         Point.prototype.getLastY = function () {
  1256.             return this.lastY;
  1257.         };
  1258.  
  1259.         Point.prototype.getSpeedX = function () {
  1260.             return this.speedX;
  1261.         };
  1262.  
  1263.         Point.prototype.getSpeedY = function () {
  1264.             return this.speedY;
  1265.         };
  1266.  
  1267.         Point.prototype.getX = function () {
  1268.             return this.x;
  1269.         };
  1270.  
  1271.         Point.prototype.getY = function () {
  1272.             return this.y;
  1273.         };
  1274.  
  1275.         Point.prototype.move = function (width, height) {
  1276.             this.moveX(width);
  1277.             this.moveY(height);
  1278.         };
  1279.  
  1280.         Point.prototype.moveX = function (width) {
  1281.             this.setX(this.getX() + width);
  1282.         };
  1283.  
  1284.         Point.prototype.moveY = function (height) {
  1285.             this.setY(this.getY() + height);
  1286.         };
  1287.  
  1288.         Point.prototype.setAccelerationX = function (accelerationX) {
  1289.             this.accelerationX = accelerationX || 0;
  1290.         };
  1291.  
  1292.         Point.prototype.setAccelerationY = function (accelerationY) {
  1293.             this.accelerationY = accelerationY || 0;
  1294.         };
  1295.  
  1296.         Point.prototype.setMaxSpeedX = function (maxSpeedX) {
  1297.             this.maxSpeedX = maxSpeedX || 0;
  1298.         };
  1299.  
  1300.         Point.prototype.setMaxSpeedY = function (maxSpeedY) {
  1301.             this.maxSpeedY = maxSpeedY || 0;
  1302.         };
  1303.  
  1304.         Point.prototype.setPosition = function (point) {
  1305.             this.setX(point.getX());
  1306.             this.setY(point.getY());
  1307.         };
  1308.  
  1309.         Point.prototype.setSpeedToAngle = function (speed, degrees) {
  1310.             var radians = toRadians(degrees);
  1311.             this.setSpeedX(speed * Math.cos(radians));
  1312.             this.setSpeedY(speed * Math.sin(radians));
  1313.         };
  1314.  
  1315.         Point.prototype.setSpeedToPoint = function (speed, point) {
  1316.             var squareDistance = Math.abs(this.getCenterX() - point.getX()) + Math.abs(this.getCenterY() - point.getY());
  1317.             this.setSpeedX((point.getX() - this.getCenterX()) * speed / squareDistance);
  1318.             this.setSpeedY((point.getY() - this.getCenterY()) * speed / squareDistance);
  1319.         };
  1320.  
  1321.         Point.prototype.setSpeedX = function (speedX) {
  1322.             this.speedX = speedX || 0;
  1323.         };
  1324.  
  1325.         Point.prototype.setSpeedY = function (speedY) {
  1326.             this.speedY = speedY || 0;
  1327.         };
  1328.  
  1329.         Point.prototype.setX = function (x) {
  1330.             this.x = x || 0;
  1331.         };
  1332.  
  1333.         Point.prototype.setY = function (y) {
  1334.             this.y = y || 0;
  1335.         };
  1336.  
  1337.         Point.prototype.stop = function () {
  1338.             this.setSpeedX(0);
  1339.             this.setSpeedY(0);
  1340.         };
  1341.  
  1342.         Point.prototype.sync = function () {
  1343.             this.setSpeedX(this.getSpeedX() + this.accelerationX);
  1344.  
  1345.             if (this.maxSpeedX && this.getSpeedX() > this.maxSpeedX) {
  1346.                 this.setSpeedX(this.maxSpeedX);
  1347.             }
  1348.  
  1349.             this.setSpeedY(this.getSpeedY() + this.accelerationY);
  1350.  
  1351.             if (this.maxSpeedY && this.getSpeedY() > this.maxSpeedY) {
  1352.                 this.setSpeedY(this.maxSpeedY);
  1353.             }
  1354.  
  1355.             this.lastX = this.getX();
  1356.             this.lastY = this.getY();
  1357.             this.move(this.getSpeedX(), this.getSpeedY());
  1358.             return false;
  1359.         };
  1360.  
  1361.         return Point;
  1362.  
  1363.     })();
  1364.  
  1365.     var Rect = (function () {
  1366.  
  1367.         function Rect(x, y, width, height) {
  1368.             Point.call(this, x, y);
  1369.             this.setHeight(height);
  1370.             this.setWidth(width);
  1371.         }
  1372.  
  1373.         Rect.prototype = Object.create(Point.prototype);
  1374.  
  1375.         Rect.prototype.bounceFrom = function (direction) {
  1376.             if ((this.getSpeedX() < 0 && direction.getLeft()) || (this.getSpeedX() > 0 && direction.getRight())) {
  1377.                 this.bounceX();
  1378.             }
  1379.  
  1380.             if ((this.getSpeedY() < 0 && direction.getTop()) || (this.getSpeedY() > 0 && direction.getBottom())) {
  1381.                 this.bounceY();
  1382.             }
  1383.         };
  1384.  
  1385.         Rect.prototype.getBottom = function () {
  1386.             return this.getY() + this.getHeight() - 1;
  1387.         };
  1388.  
  1389.         Rect.prototype.getCenter = function () {
  1390.             return new Point(this.getCenterX(), this.getCenterY());
  1391.         };
  1392.  
  1393.         Rect.prototype.getCenterX = function () {
  1394.             return this.getX() + this.getHalfWidth();
  1395.         };
  1396.  
  1397.         Rect.prototype.getCenterY = function () {
  1398.             return this.getY() + this.getHalfHeight();
  1399.         };
  1400.  
  1401.         Rect.prototype.getCollision = function (rect) {
  1402.             var direction = new Direction();
  1403.  
  1404.             var ta = this.getTop();
  1405.             var ra = this.getRight();
  1406.             var ba = this.getBottom();
  1407.             var la = this.getLeft();
  1408.             var xa = this.getCenterX();
  1409.             var ya = this.getCenterY();
  1410.  
  1411.             var tb = rect.getTop();
  1412.             var rb = rect.getRight();
  1413.             var bb = rect.getBottom();
  1414.             var lb = rect.getLeft();
  1415.  
  1416.             if (xa <= lb && ra < rb) {
  1417.                 direction.setRight();
  1418.             } else if (xa >= rb && la > lb) {
  1419.                 direction.setLeft();
  1420.             }
  1421.  
  1422.             if (ya <= tb && ba < bb) {
  1423.                 direction.setBottom();
  1424.             } else if (ya >= bb && ta > tb) {
  1425.                 direction.setTop();
  1426.             }
  1427.  
  1428.             return direction;
  1429.         };
  1430.  
  1431.         Rect.prototype.getHalfHeight = function () {
  1432.             return Math.floor(this.getHeight() / 2);
  1433.         };
  1434.  
  1435.         Rect.prototype.getHalfWidth = function () {
  1436.             return Math.floor(this.getWidth() / 2);
  1437.         };
  1438.  
  1439.         Rect.prototype.getHeight = function () {
  1440.             return this.height;
  1441.         };
  1442.  
  1443.         Rect.prototype.getLeft = function () {
  1444.             return this.getX();
  1445.         };
  1446.  
  1447.         Rect.prototype.getRight = function () {
  1448.             return this.getX() + this.getWidth() - 1;
  1449.         };
  1450.  
  1451.         Rect.prototype.getTop = function () {
  1452.             return this.getY();
  1453.         };
  1454.  
  1455.         Rect.prototype.getWidth = function () {
  1456.             return this.width;
  1457.         };
  1458.  
  1459.         Rect.prototype.hasCollision = function (rect) {
  1460.             return !(
  1461.                 this.getLeft() > rect.getRight() ||
  1462.                 this.getRight() < rect.getLeft() ||
  1463.                 this.getTop() > rect.getBottom() ||
  1464.                 this.getBottom() < rect.getTop()
  1465.             );
  1466.         };
  1467.  
  1468.         Rect.prototype.increase = function (width, height) {
  1469.             this.increaseWidth(width);
  1470.             this.increaseHeight(height);
  1471.         };
  1472.  
  1473.         Rect.prototype.increaseHeight = function (height) {
  1474.             this.setHeight(this.getHeight() + height);
  1475.         };
  1476.  
  1477.         Rect.prototype.increaseWidth = function (width) {
  1478.             this.setWidth(this.getWidth() + width);
  1479.         };
  1480.  
  1481.         Rect.prototype.setBottom = function (y) {
  1482.             this.setY(y - this.getHeight() + 1);
  1483.         };
  1484.  
  1485.         Rect.prototype.setCenter = function (point) {
  1486.             this.setCenterX(point.getX());
  1487.             this.setCenterY(point.getY());
  1488.         };
  1489.  
  1490.         Rect.prototype.setCenterX = function (x) {
  1491.             this.setX(x - this.getHalfWidth());
  1492.         };
  1493.  
  1494.         Rect.prototype.setCenterY = function (y) {
  1495.             this.setY(y - this.getHalfHeight());
  1496.         };
  1497.  
  1498.         Rect.prototype.setHeight = function (height) {
  1499.             this.height = height || 0;
  1500.         };
  1501.  
  1502.         Rect.prototype.setLeft = function (x) {
  1503.             this.setX(x);
  1504.         };
  1505.  
  1506.         Rect.prototype.setRight = function (x) {
  1507.             this.setX(x - this.getWidth() + 1);
  1508.         };
  1509.  
  1510.         Rect.prototype.setSize = function (width, height) {
  1511.             this.setWidth(width);
  1512.  
  1513.             if (arguments.length > 1) {
  1514.                 this.setHeight(height);
  1515.             } else {
  1516.                 this.setHeight(width);
  1517.             }
  1518.         };
  1519.  
  1520.         Rect.prototype.setTop = function (y) {
  1521.             this.setY(y);
  1522.         };
  1523.  
  1524.         Rect.prototype.setWidth = function (width) {
  1525.             this.width = width || 0;
  1526.         };
  1527.  
  1528.         return Rect;
  1529.  
  1530.     })();
  1531.  
  1532.     var Direction = (function () {
  1533.  
  1534.         function Direction() {
  1535.             this.isBottom = false;
  1536.             this.isLeft = false;
  1537.             this.isRight = false;
  1538.             this.isTop = false;
  1539.         }
  1540.  
  1541.         Direction.prototype.getBottom = function () {
  1542.             return this.isBottom;
  1543.         };
  1544.  
  1545.         Direction.prototype.getLeft = function () {
  1546.             return this.isLeft;
  1547.         };
  1548.  
  1549.         Direction.prototype.getRight = function () {
  1550.             return this.isRight;
  1551.         };
  1552.  
  1553.         Direction.prototype.getTop = function () {
  1554.             return this.isTop;
  1555.         };
  1556.  
  1557.         Direction.prototype.setBottom = function (isBottom) {
  1558.             this.isBottom = isBottom == undefined || isBottom;
  1559.         };
  1560.  
  1561.         Direction.prototype.setLeft = function (isLeft) {
  1562.             this.isLeft = isLeft == undefined || isLeft;
  1563.         };
  1564.  
  1565.         Direction.prototype.setRight = function (isRight) {
  1566.             this.isRight = isRight == undefined || isRight;
  1567.         };
  1568.  
  1569.         Direction.prototype.setTop = function (isTop) {
  1570.             this.isTop = isTop == undefined || isTop;
  1571.         };
  1572.  
  1573.         return Direction;
  1574.  
  1575.     })();
  1576.  
  1577.     var Frame = (function () {
  1578.  
  1579.         function Frame(image, duration) {
  1580.             this.duration = duration || 0;
  1581.             this.image = image || new Image();
  1582.         }
  1583.  
  1584.         Frame.prototype.getDuration = function () {
  1585.             return this.duration;
  1586.         };
  1587.  
  1588.         Frame.prototype.getHeight = function () {
  1589.             return this.image.height;
  1590.         };
  1591.  
  1592.         Frame.prototype.getImage = function () {
  1593.             return this.image;
  1594.         };
  1595.  
  1596.         Frame.prototype.getWidth = function () {
  1597.             return this.image.width;
  1598.         };
  1599.  
  1600.         return Frame;
  1601.  
  1602.     })();
  1603.  
  1604.     var Animation = (function () {
  1605.  
  1606.         function Animation(frames) {
  1607.             this.setFrames(frames);
  1608.         }
  1609.  
  1610.         Animation.prototype.getHeight = function () {
  1611.             return this.frame.getHeight();
  1612.         };
  1613.  
  1614.         Animation.prototype.getImage = function () {
  1615.             return this.frame.getImage();
  1616.         };
  1617.  
  1618.         Animation.prototype.getWidth = function () {
  1619.             return this.frame.getWidth();
  1620.         };
  1621.  
  1622.         Animation.prototype.setFrameIndex = function (frameIndex) {
  1623.             if (frameIndex < this.frames.length && frameIndex > -1) {
  1624.                 this.frameIndex = frameIndex;
  1625.                 this.tick = 0;
  1626.                 this.frame = this.frames[frameIndex];
  1627.                 return true;
  1628.             }
  1629.  
  1630.             return false;
  1631.         };
  1632.  
  1633.         Animation.prototype.setFrames = function (frames) {
  1634.             this.frames = frames || [new Frame()];
  1635.             this.setFrameIndex(0);
  1636.         };
  1637.  
  1638.         Animation.prototype.update = function () {
  1639.             var hasLooped = false;
  1640.  
  1641.             if (this.frame.getDuration() && ++this.tick > this.frame.getDuration()) {
  1642.                 var index = this.frameIndex + 1;
  1643.  
  1644.                 if (index == this.frames.length) {
  1645.                     hasLooped = true;
  1646.                     index = 0;
  1647.                 }
  1648.  
  1649.                 this.setFrameIndex(index);
  1650.             }
  1651.  
  1652.             return hasLooped;
  1653.         };
  1654.  
  1655.         return Animation;
  1656.  
  1657.     })();
  1658.  
  1659.     var Sprite = (function () {
  1660.  
  1661.         function Sprite() {
  1662.             Rect.call(this);
  1663.             this.animation = null;
  1664.             this.boundary = null;
  1665.             this.delegate = null;
  1666.         }
  1667.  
  1668.         Sprite.prototype = Object.create(Rect.prototype);
  1669.  
  1670.         Sprite.prototype.getImage = function () {
  1671.             return this.animation.getImage();
  1672.         };
  1673.  
  1674.         Sprite.prototype.offBoundary = function () {
  1675.             if (this.delegate && this.delegate.offBoundary) {
  1676.                 this.delegate.offBoundary();
  1677.             } else {
  1678.                 this.expire();
  1679.             }
  1680.         };
  1681.  
  1682.         Sprite.prototype.onAnimationLoop = function () {
  1683.             this.delegate && this.delegate.onAnimationLoop && this.delegate.onAnimationLoop();
  1684.         };
  1685.  
  1686.         Sprite.prototype.render = function (context) {
  1687.             if (this.animation) {
  1688.                 var image = this.getImage();
  1689.                 var x = Math.floor(this.getX());
  1690.                 var y = Math.floor(this.getY());
  1691.                 context.drawImage(image, x, y, this.getWidth(), this.getHeight());
  1692.             }
  1693.         };
  1694.  
  1695.         Sprite.prototype.setAnimation = function (animation) {
  1696.             if (this.animation == animation) {
  1697.                 return;
  1698.             }
  1699.  
  1700.             this.animation = animation;
  1701.             this.animation.setFrameIndex(0);
  1702.             this.setHeight(this.animation.getHeight());
  1703.             this.setWidth(this.animation.getWidth());
  1704.         };
  1705.  
  1706.         Sprite.prototype.setBoundary = function (rect) {
  1707.             this.boundary = rect || Quick.getBoundary();
  1708.         };
  1709.  
  1710.         Sprite.prototype.setDelegate = function (delegate) {
  1711.             this.delegate = delegate;
  1712.         };
  1713.  
  1714.         Sprite.prototype.setImage = function (image) {
  1715.             this.setAnimation(new Animation([new Frame(image)]));
  1716.         };
  1717.  
  1718.         Sprite.prototype.setImageId = function (id) {
  1719.             this.setImage(document.getElementById(id));
  1720.         };
  1721.  
  1722.         Sprite.prototype.sync = function () {
  1723.             var result = Rect.prototype.sync.call(this);
  1724.  
  1725.             if (this.animation && this.animation.update()) {
  1726.                 this.onAnimationLoop();
  1727.             }
  1728.  
  1729.             if (this.boundary && !this.hasCollision(this.boundary)) {
  1730.                 this.offBoundary();
  1731.             }
  1732.  
  1733.             return result;
  1734.         };
  1735.  
  1736.         return Sprite;
  1737.  
  1738.     })();
  1739.  
  1740.     var GameObject = (function () {
  1741.  
  1742.         function GameObject() {
  1743.             Sprite.call(this);
  1744.             this.color = null;
  1745.             this.layerIndex = 0;
  1746.             this.isEssential = false;
  1747.             this.expiration = -1;
  1748.             this.isExpired = false;
  1749.             this.isSolid = false;
  1750.             this.isVisible = true;
  1751.             this.scene = null;
  1752.             this.tags = {};
  1753.             this.tick = 0;
  1754.         }
  1755.  
  1756.         GameObject.prototype = Object.create(Sprite.prototype);
  1757.  
  1758.         GameObject.prototype.addTag = function (tag) {
  1759.             this.tags[tag] = true;
  1760.         };
  1761.  
  1762.         GameObject.prototype.expire = function () {
  1763.             this.isExpired = true;
  1764.         };
  1765.  
  1766.         GameObject.prototype.getColor = function () {
  1767.             return this.color;
  1768.         };
  1769.  
  1770.         GameObject.prototype.getEssential = function () {
  1771.             return this.isEssential;
  1772.         };
  1773.  
  1774.         GameObject.prototype.getExpired = function () {
  1775.             return this.isExpired;
  1776.         };
  1777.  
  1778.         GameObject.prototype.getLayerIndex = function () {
  1779.             return this.layerIndex;
  1780.         };
  1781.  
  1782.         GameObject.prototype.getScene = function () {
  1783.             return this.scene;
  1784.         };
  1785.  
  1786.         GameObject.prototype.getSolid = function () {
  1787.             return this.isSolid;
  1788.         };
  1789.  
  1790.         GameObject.prototype.getTick = function () {
  1791.             return this.tick;
  1792.         };
  1793.  
  1794.         GameObject.prototype.getVisible = function () {
  1795.             return this.isVisible;
  1796.         };
  1797.  
  1798.         GameObject.prototype.hasTag = function (tag) {
  1799.             return this.tags[tag]
  1800.         };
  1801.  
  1802.         GameObject.prototype.init = function () {
  1803.             this.delegate && this.delegate.init && this.delegate.init();
  1804.         };
  1805.        
  1806.         GameObject.prototype.onCollision = function (gameObject) {
  1807.             this.delegate && this.delegate.onCollision && this.delegate.onCollision(gameObject);
  1808.         };
  1809.  
  1810.         GameObject.prototype.setColor = function (color) {
  1811.             this.color = color;
  1812.         };
  1813.  
  1814.         GameObject.prototype.setEssential = function (isEssential) {
  1815.             this.isEssential = isEssential == undefined || isEssential;
  1816.         };
  1817.  
  1818.         GameObject.prototype.setLayerIndex = function (layerIndex) {
  1819.             this.layerIndex = layerIndex || 0;
  1820.         };
  1821.  
  1822.         GameObject.prototype.setScene = function (scene) {
  1823.             this.scene = scene;
  1824.         };
  1825.  
  1826.         GameObject.prototype.setSolid = function (isSolid) {
  1827.             this.isSolid = isSolid == undefined || isSolid;
  1828.         };
  1829.  
  1830.         GameObject.prototype.setVisible = function (isVisible) {
  1831.             this.isVisible = isVisible == undefined || isVisible;
  1832.         };
  1833.  
  1834.         GameObject.prototype.setExpiration = function (expiration) {
  1835.             this.expiration = expiration;
  1836.         };
  1837.  
  1838.         GameObject.prototype.render = function (context) {
  1839.             if (!this.isVisible) {
  1840.                 return;
  1841.             }
  1842.  
  1843.             if (this.color) {
  1844.                 var x = Math.floor(this.getX());
  1845.                 var y = Math.floor(this.getY());
  1846.                 context.fillStyle = this.color;
  1847.                 context.fillRect(x, y, this.getWidth(), this.getHeight());
  1848.             }
  1849.  
  1850.             Sprite.prototype.render.call(this, context);
  1851.         };
  1852.  
  1853.         GameObject.prototype.sync = function () {
  1854.             if (this.getExpired()) {
  1855.                 return true;
  1856.             }
  1857.  
  1858.             if (++this.tick == this.expiration) {
  1859.                 this.expire();
  1860.             }
  1861.  
  1862.             return Sprite.prototype.sync.call(this);
  1863.         };
  1864.  
  1865.         GameObject.prototype.update = function () {
  1866.             this.delegate && this.delegate.update && this.delegate.update();
  1867.         };
  1868.  
  1869.         return GameObject;
  1870.  
  1871.     })();
  1872.  
  1873.     var Text = (function () {
  1874.  
  1875.         var FONT_SUFFIX = "Font";
  1876.         var LINE_FEED = "\n";
  1877.         var SPACE = 4;
  1878.         var SPACE_CHARACTER = " ";
  1879.         var SPACING = 0;
  1880.  
  1881.         function Text(string) {
  1882.             GameObject.call(this);
  1883.             this.setString(string || "");
  1884.         }
  1885.  
  1886.         Text.prototype = Object.create(GameObject.prototype);
  1887.  
  1888.         Text.prototype.getString = function () {
  1889.             return this.string;
  1890.         };
  1891.  
  1892.         Text.prototype.parse = function (context) {
  1893.             var height = 0;
  1894.             var width = 0;
  1895.             var x = 0;
  1896.             var y = 0;
  1897.  
  1898.             for (var i = 0; i < this.string.length; ++i) {
  1899.                 var character = this.string[i];
  1900.  
  1901.                 if (character == SPACE_CHARACTER) {
  1902.                     x += SPACE + SPACING;
  1903.                 } else if (character == LINE_FEED) {
  1904.                     x = 0;
  1905.                     y += height + SPACING;
  1906.                 } else {
  1907.                     var image = document.getElementById(character + FONT_SUFFIX);
  1908.  
  1909.                     if (context) {
  1910.                         context.drawImage(image, this.getX() + x, this.getY() + y, image.width, image.height);
  1911.                     }
  1912.  
  1913.                     x += image.width + SPACING;
  1914.  
  1915.                     if (x > width) {
  1916.                         width = x;
  1917.                     }
  1918.  
  1919.                     if (image.height > height) {
  1920.                         height = image.height;
  1921.                     }
  1922.                 }
  1923.             }
  1924.  
  1925.             this.setWidth(width);
  1926.             this.setHeight(y + height);
  1927.         };
  1928.  
  1929.         Text.prototype.render = function (context) {
  1930.             this.parse(context);
  1931.         };
  1932.  
  1933.         Text.prototype.setString = function (string) {
  1934.             this.string = string;
  1935.             this.parse();
  1936.         };
  1937.  
  1938.         return Text;
  1939.  
  1940.     })();
  1941.  
  1942.     var BaseTile = (function () {
  1943.  
  1944.         function BaseTile(id) {
  1945.             GameObject.call(this);
  1946.             this.setImageId(id);
  1947.         }
  1948.  
  1949.         BaseTile.prototype = Object.create(GameObject.prototype);
  1950.  
  1951.         return BaseTile;
  1952.  
  1953.     })();
  1954.  
  1955.     var BaseTransition = (function () {
  1956.  
  1957.         var COLOR = "Black";
  1958.         var FRAMES = 32;
  1959.  
  1960.         function BaseTransition() {
  1961.             GameObject.call(this);
  1962.             this.setColor(COLOR);
  1963.             this.setHeight(Quick.getHeight());
  1964.             this.increase = Quick.getWidth() / FRAMES;
  1965.         }
  1966.  
  1967.         BaseTransition.prototype = Object.create(GameObject.prototype);
  1968.  
  1969.         BaseTransition.prototype.sync = function () {
  1970.             if (this.getWidth() > Quick.getWidth()) {
  1971.                 return true;
  1972.             }
  1973.  
  1974.             this.increaseWidth(this.increase);
  1975.             Quick.paint(this);
  1976.             return GameObject.prototype.sync.call(this);
  1977.         };
  1978.  
  1979.         return BaseTransition;
  1980.  
  1981.     })();
  1982.  
  1983.     function toDegrees(radians) {
  1984.         return radians * RADIAN_DEGREES / Math.PI;
  1985.     }
  1986.  
  1987.     function toRadians(degrees) {
  1988.         return degrees * Math.PI / RADIAN_DEGREES;
  1989.     }
  1990.  
  1991.     function publish() {
  1992.         if (!window.com) {
  1993.             window.com = {};
  1994.         }
  1995.  
  1996.         if (!window.com.dgsprb) {
  1997.             window.com.dgsprb = {};
  1998.         }
  1999.  
  2000.         window.com.dgsprb.quick = {
  2001.             "Animation" : Animation,
  2002.             "BaseTile" : BaseTile,
  2003.             "BaseTransition" : BaseTransition,
  2004.             "CommandEnum" : CommandEnum,
  2005.             "Controller" : Controller,
  2006.             "Frame" : Frame,
  2007.             "GameObject" : GameObject,
  2008.             "ImageFactory" : ImageFactory,
  2009.             "Mouse" : Mouse,
  2010.             "Point" : Point,
  2011.             "Quick" : Quick,
  2012.             "Rect" : Rect,
  2013.             "Scene" : Scene,
  2014.             "Sprite" : Sprite,
  2015.             "Text" : Text
  2016.         };
  2017.     }
  2018.  
  2019.     publish();
  2020.  
  2021. })();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement