From 2174455ae8a9e5fc346aaea62a9e2e18c5e969e9 Mon Sep 17 00:00:00 2001 From: Michele Bini Date: Sun, 5 Oct 2014 23:53:10 +0200 Subject: Updated the demo with swimming animation for main character; simplify key events handling in jaws code diff --git a/.gitmodules b/.gitmodules index 7fb3f75..d4da416 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "htmlcup"] path = htmlcup url = ./htmlcup +[submodule "jaws"] + path = jaws + url = https://github.com/ippa/jaws.git diff --git a/README.md b/README.md new file mode 100644 index 0000000..58cd490 --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +Vaquitas are the most endangered and smallest marine cetacean. + +The sources here include a web page and an ocean-themed game featuring Vaquita characters both compilable with CoffeeScript and htmlcup. + +The game is not playable yet but is a demo. + +Consult LICENSE and the individual files for copyright, licensing and autorship details. + diff --git a/attic/game-debug.html b/attic/game-debug.html new file mode 100644 index 0000000..52935f8 --- /dev/null +++ b/attic/game-debug.html @@ -0,0 +1,269 @@ + +Vilma the Vaquita
\ No newline at end of file diff --git a/attic/game-debug.html.coffee b/attic/game-debug.html.coffee new file mode 100644 index 0000000..3877da7 --- /dev/null +++ b/attic/game-debug.html.coffee @@ -0,0 +1,311 @@ +# Copyright (c) 2013, 2014 Michele Bini + +# A game featuring a Vaquita, the smallest, most endagered marine cetacean + +# This program is available under the terms of the MIT License + +version = "0.0.11" + +{ htmlcup } = require 'htmlcup' + +htmlcup[x] = htmlcup.compileTag x for x in [ "svg", "rect", "g", "ellipse", "polygon", "line", "image", "defs", "linearGradient", "stop", "use" ] + +title = "Vilma the Vaquita" + +fs = require 'fs' + +datauri = (t, x)-> "data:#{t};base64,#{new Buffer(fs.readFileSync(x)).toString("base64")}" +datauripng = (x)-> datauri "image/png", x +datauriicon = (x)-> datauri "image/x-icon", x + +icon = datauriicon "vaquita.ico" +pixyvaquita = datauripng "pixyvaquita_v2.png" +pixyvaquita_v105 = datauripng "pixyvaquita_v105_v.png" +frames = + _: pixyvaquita + _v105: pixyvaquita_v105 + twistleft: datauripng "pixyvaquita_v2_twistleft.png" + +useSvg = true + +genPage = -> + htmlcup.html5Page -> + @head -> + @meta charset:"utf-8" + @link rel:"shortcut icon", href:icon + @title title + @style type: "text/css", + """ + body { + /* background:pink; */ + /* background: #69B2FF; */ + /* background: #21AFF8; */ + /* background: #0286E8; */ + /* background: #1096EE; */ + background:black; + text-align: center; + font-size: 22px; + font-family: Helvetica; + } + .banner { + border: 5px solid white; + border: 5px solid white rgba(255,255,255,0.9); + box-shadow: 0 2px 4px blue; + margin: 1em; + } + p { + color:white; + color:rgba(255,255,255,0.9); + margin-top:0.418em; + margin-bottom:0.418em; + margin-left:auto; + margin-right:auto; + width:22em; + max-width:100%; + text-shadow: 0 1px 1px blue; + } + a { + /* + color:rgb(200,255,255); + color:rgba(200,255,255,0.9); + */ + color:white; + color:rgba(255,255,255,0.9); + text-decoration:none; + display: inline-block; + border: 1px solid white; + padding: 0 0.2em; + border-radius: 0.2em; + -moz-border-radius: 0.2em; + -webkit-border-radius: 0.2em; + -ie-border-radius: 0.2em; + } + a:hover { + background-color:rgba(20,70,180,1.0); + } + .petition { + margin:0.418em; + padding:0.618em; + } + .petition a { + font-size:127.2%; + box-shadow: 0 2px 4px blue; + margin:0.3em; + } + .page { + width: 100%; + height: 100%; + margin: 0; + border: 0; + } + .centering { + display: table; + padding: 0; + } + .centered { + display: table-cell; + vertical-align: middle; + text-align: center; + } + .inline-block { + display: inline-block; + } + .dynamic-section { + display: inline-block; + vertical-align:middle; + max-width:100%; + } + .flip-lr { + -moz-transform: scaleX(-1); + -o-transform: scaleX(-1); + -webkit-transform: scaleX(-1); + transform: scaleX(-1); + filter: FlipH; + -ms-filter: "FlipH"; + } + image, .pixelart { + image-rendering:optimizeSpeed; /* Legal fallback */ + image-rendering:-moz-crisp-edges; /* Firefox */ + image-rendering:-o-crisp-edges; /* Opera */ + image-rendering:-webkit-optimize-contrast; /* Safari */ + image-rendering:optimize-contrast; /* CSS3 Proposed */ + image-rendering:crisp-edges; /* CSS4 Proposed */ + image-rendering:pixelated; /* CSS4 Proposed */ + -ms-interpolation-mode:nearest-neighbor; /* IE8+ */ + } + /* + .pixelart { + image-rendering: -moz-crisp-edges; + -ms-interpolation-mode: nearest-neighbor; + image-rendering: pixelated; + image-rendering: crisp-edges; + } + */ + g.flipped { + transform:scale(-1,1); + } + .dimmed { + opacity: 0.2; + } + .dimmed:hover { + opacity: 1; + } + """ + @body -> + @div class:"centering page", -> + @div class:"centered", -> + @div -> @a class:"dimmed", "Vilma the Vaquita - v#{version}" + if useSvg + @svg id:"sea-svgroot", width:"960", height:"720", -> + @defs -> + @linearGradient id:"grad1", x1:"0%", y1:"0%", x2:"0%", y2:"100%", -> + @stop offset:"0%", style:"stop-color:rgb(255,255,255);stop-opacity:1" + @stop offset:"25%", style:"stop-color:rgb(100,200,250);stop-opacity:1" + @stop offset:"50%", style:"stop-color:rgb(0,80,240);stop-opacity:1" + @stop offset:"75%", style:"stop-color:rgb(0,0,180);stop-opacity:1" + @stop offset:"100%", style:"stop-color:rgb(0,0,0);stop-opacity:1" + for k,v of frames + @g id:k, -> + @g transform:"translate(-18,-15)", -> + @image width:"50", height:"30", "xlink:href":v + @rect x:"0", y:"0", width:"960", height:"720", fill:"url(#grad1)" + @g transform:"scale(2)", -> + @g id:"sea", transform:"translate(240,180)", -> + @use "xlink:href":"#_" + else + @canvas width:"960", height:"720", -> + @div -> @a class:"dimmed", target:"_blank", href:"index.html", "Learn about Vaquitas" + gameObjects = null + @script type:"text/javascript", "gameObjects=#{JSON.stringify(gameObjects)};" + @coffeeScript -> + svgroot = document.getElementById("sea-svgroot") + + reportErrors = (x)-> + try + x() + catch error + try + alert error.toString() + catch error2 + alert error + + screen_x1 = 240 + screen_y1 = 180 + vaquitas = [ ] + vaquitaObj = + update: (x, y)-> + if !window.abcd + window.abcd = 1 + vx = @vx + Math.floor(Math.random()*3) - 1 + vy = @vy + Math.floor(Math.random()*3) - 1 + x = @x + y = @y + rx = 0.5 * x / screen_x1 + ry = 0.5 * y / screen_y1 + if (s = vx * vx + vy * vy * 2) > 6 + vx = Math.round(vx * 0.9 + rx) + vy = Math.round(vy * 0.9 + ry) + @x = x -= @vx = vx + @y = y -= @vy = vy + if vx > 0 + @scaleX = 1 + else if vx < 0 + @scaleX = -1 + @e.setAttribute "transform", "translate(#{x}, #{y}) scale(#{@scaleX}, 1)" + m = @m; m.e = x; m.f = y; m.a = @scaleX + # @e.transform.baseVal.consolidate() + # @e.transform.baseVal.initialize(@e.transform.baseVal.matrix) + sea = document.getElementById "sea" + v = sea.firstChild + + getTransformMatrix = (el)-> + transformListXX = el.transform.baseVal + transformMatrixXX = svgroot.createSVGMatrix() + transformXX = svgroot.createSVGTransform() + transformXX.setMatrix(transformMatrixXX) + transformListXX.initialize(transformXX) + transformXX.matrix + + addVaquita = -> + n = v.cloneNode() + n.setAttribute "opacity", "0.5" + n.href.baseVal = "#_v105" if Math.random(0) > 0.5 + # n.setAttribute "transform", "" + sea.appendChild n + angle = Math.random() * 6.28 + vaquita = + e: n + m: getTransformMatrix(n) + x: Math.sin(angle) * 300 + y: Math.cos(angle) * 300 + vx: 0 + vy: 0 + scaleX: 1 + __proto__: vaquitaObj + vaquita.update() + vaquitas.push vaquita + + leftKey = 37 + upKey = 38 + rightKey = 39 + downKey = 40 + usedKeys = [ leftKey, upKey, rightKey, downKey ] + + keyDownActions = + 32: addVaquita + + pressedKeys = { } + pressedKeys[k] = 0 for k in usedKeys + + window.addEventListener 'keydown', (event)-> + code = event.keyCode + keyDownActions[ code ]?(event) + pressedKeys[ code ] = 1 + window.addEventListener 'keyup', (event)-> + pressedKeys[ event.keyCode ] = 0 + + do (x = 0, y = 0)-> reportErrors -> + time = 0 + vx = 0 + vy = 0 + ax = 0 + ay = 0 + # s = 1 + # x = 0 + # y = 0 + scaleX = 1 + scaleY = 1 + + window.cf = currentFrame = v.href + transformMatrix = getTransformMatrix(v) + transformMatrix.a = scaleX + transformMatrix.e = x + transformMatrix.f = y + + gameFrame = -> reportErrors -> + if (time & 0xff) is 0x00 and vaquitas.length < 4 + addVaquita() + # s += 0.001 + x -= vx = pressedKeys[leftKey] - pressedKeys[rightKey] + y -= pressedKeys[upKey] - pressedKeys[downKey] + if vx > 0 + scaleX = 1 + else if vx < 0 + scaleX = -1 + v.setAttribute("transform", "translate(#{x}, #{y}) scale(#{scaleX}, #{scaleY})") + # transform = v.transform.baseVal.getItem(0) + # transformMatrix.a = scaleX + # transformMatrix.e = x + # transformMatrix.f = y + if (time % 3) is 0 + if currentFrame.baseVal is "#twistleft" + currentFrame .baseVal = "#_" + else if vx isnt 0 + currentFrame.baseVal = "#twistleft" + # transformList.initialize(transform) + vq.update() for vq in vaquitas + time++ + + setInterval gameFrame, 40 + +genPage() diff --git a/game-debug.html b/game-debug.html deleted file mode 100644 index 52935f8..0000000 --- a/game-debug.html +++ /dev/null @@ -1,269 +0,0 @@ - -Vilma the Vaquita
\ No newline at end of file diff --git a/game-debug.html.coffee b/game-debug.html.coffee deleted file mode 100644 index e9645f5..0000000 --- a/game-debug.html.coffee +++ /dev/null @@ -1,319 +0,0 @@ -# Copyright (c) 2013, 2014 Michele Bini - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the version 3 of the GNU General Public License -# as published by the Free Software Foundation. - -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -version = "0.0.10" - -{ htmlcup } = require 'htmlcup' - -htmlcup[x] = htmlcup.compileTag x for x in [ "svg", "rect", "g", "ellipse", "polygon", "line", "image", "defs", "linearGradient", "stop", "use" ] - -title = "Vilma the Vaquita" - -fs = require 'fs' - -datauri = (t, x)-> "data:#{t};base64,#{new Buffer(fs.readFileSync(x)).toString("base64")}" -datauripng = (x)-> datauri "image/png", x -datauriicon = (x)-> datauri "image/x-icon", x - -icon = datauriicon "vaquita.ico" -pixyvaquita = datauripng "pixyvaquita_v2.png" -pixyvaquita_v105 = datauripng "pixyvaquita_v105_v.png" -frames = - _: pixyvaquita - _v105: pixyvaquita_v105 - twistleft: datauripng "pixyvaquita_v2_twistleft.png" - -useSvg = true - -genPage = -> - htmlcup.html5Page -> - @head -> - @meta charset:"utf-8" - @link rel:"shortcut icon", href:icon - @title title - @style type: "text/css", - """ - body { - /* background:pink; */ - /* background: #69B2FF; */ - /* background: #21AFF8; */ - /* background: #0286E8; */ - /* background: #1096EE; */ - background:black; - text-align: center; - font-size: 22px; - font-family: Helvetica; - } - .banner { - border: 5px solid white; - border: 5px solid white rgba(255,255,255,0.9); - box-shadow: 0 2px 4px blue; - margin: 1em; - } - p { - color:white; - color:rgba(255,255,255,0.9); - margin-top:0.418em; - margin-bottom:0.418em; - margin-left:auto; - margin-right:auto; - width:22em; - max-width:100%; - text-shadow: 0 1px 1px blue; - } - a { - /* - color:rgb(200,255,255); - color:rgba(200,255,255,0.9); - */ - color:white; - color:rgba(255,255,255,0.9); - text-decoration:none; - display: inline-block; - border: 1px solid white; - padding: 0 0.2em; - border-radius: 0.2em; - -moz-border-radius: 0.2em; - -webkit-border-radius: 0.2em; - -ie-border-radius: 0.2em; - } - a:hover { - background-color:rgba(20,70,180,1.0); - } - .petition { - margin:0.418em; - padding:0.618em; - } - .petition a { - font-size:127.2%; - box-shadow: 0 2px 4px blue; - margin:0.3em; - } - .page { - width: 100%; - height: 100%; - margin: 0; - border: 0; - } - .centering { - display: table; - padding: 0; - } - .centered { - display: table-cell; - vertical-align: middle; - text-align: center; - } - .inline-block { - display: inline-block; - } - .dynamic-section { - display: inline-block; - vertical-align:middle; - max-width:100%; - } - .flip-lr { - -moz-transform: scaleX(-1); - -o-transform: scaleX(-1); - -webkit-transform: scaleX(-1); - transform: scaleX(-1); - filter: FlipH; - -ms-filter: "FlipH"; - } - image, .pixelart { - image-rendering:optimizeSpeed; /* Legal fallback */ - image-rendering:-moz-crisp-edges; /* Firefox */ - image-rendering:-o-crisp-edges; /* Opera */ - image-rendering:-webkit-optimize-contrast; /* Safari */ - image-rendering:optimize-contrast; /* CSS3 Proposed */ - image-rendering:crisp-edges; /* CSS4 Proposed */ - image-rendering:pixelated; /* CSS4 Proposed */ - -ms-interpolation-mode:nearest-neighbor; /* IE8+ */ - } - /* - .pixelart { - image-rendering: -moz-crisp-edges; - -ms-interpolation-mode: nearest-neighbor; - image-rendering: pixelated; - image-rendering: crisp-edges; - } - */ - g.flipped { - transform:scale(-1,1); - } - .dimmed { - opacity: 0.2; - } - .dimmed:hover { - opacity: 1; - } - """ - @body -> - @div class:"centering page", -> - @div class:"centered", -> - @div -> @a class:"dimmed", "Vilma the Vaquita - v#{version}" - if useSvg - @svg id:"sea-svgroot", width:"960", height:"720", -> - @defs -> - @linearGradient id:"grad1", x1:"0%", y1:"0%", x2:"0%", y2:"100%", -> - @stop offset:"0%", style:"stop-color:rgb(255,255,255);stop-opacity:1" - @stop offset:"25%", style:"stop-color:rgb(100,200,250);stop-opacity:1" - @stop offset:"50%", style:"stop-color:rgb(0,80,240);stop-opacity:1" - @stop offset:"75%", style:"stop-color:rgb(0,0,180);stop-opacity:1" - @stop offset:"100%", style:"stop-color:rgb(0,0,0);stop-opacity:1" - for k,v of frames - @g id:k, -> - @g transform:"translate(-18,-15)", -> - @image width:"50", height:"30", "xlink:href":v - @rect x:"0", y:"0", width:"960", height:"720", fill:"url(#grad1)" - @g transform:"scale(2)", -> - @g id:"sea", transform:"translate(240,180)", -> - @use "xlink:href":"#_" - else - @canvas width:"960", height:"720", -> - @div -> @a class:"dimmed", target:"_blank", href:"index.html", "Learn about Vaquitas" - gameObjects = null - @script type:"text/javascript", "gameObjects=#{JSON.stringify(gameObjects)};" - @coffeeScript -> - svgroot = document.getElementById("sea-svgroot") - - reportErrors = (x)-> - try - x() - catch error - try - alert error.toString() - catch error2 - alert error - - screen_x1 = 240 - screen_y1 = 180 - vaquitas = [ ] - vaquitaObj = - update: (x, y)-> - if !window.abcd - window.abcd = 1 - vx = @vx + Math.floor(Math.random()*3) - 1 - vy = @vy + Math.floor(Math.random()*3) - 1 - x = @x - y = @y - rx = 0.5 * x / screen_x1 - ry = 0.5 * y / screen_y1 - if (s = vx * vx + vy * vy * 2) > 6 - vx = Math.round(vx * 0.9 + rx) - vy = Math.round(vy * 0.9 + ry) - @x = x -= @vx = vx - @y = y -= @vy = vy - if vx > 0 - @scaleX = 1 - else if vx < 0 - @scaleX = -1 - @e.setAttribute "transform", "translate(#{x}, #{y}) scale(#{@scaleX}, 1)" - m = @m; m.e = x; m.f = y; m.a = @scaleX - # @e.transform.baseVal.consolidate() - # @e.transform.baseVal.initialize(@e.transform.baseVal.matrix) - sea = document.getElementById "sea" - v = sea.firstChild - - getTransformMatrix = (el)-> - transformListXX = el.transform.baseVal - transformMatrixXX = svgroot.createSVGMatrix() - transformXX = svgroot.createSVGTransform() - transformXX.setMatrix(transformMatrixXX) - transformListXX.initialize(transformXX) - transformXX.matrix - - addVaquita = -> - n = v.cloneNode() - n.setAttribute "opacity", "0.5" - n.href.baseVal = "#_v105" if Math.random(0) > 0.5 - # n.setAttribute "transform", "" - sea.appendChild n - angle = Math.random() * 6.28 - vaquita = - e: n - m: getTransformMatrix(n) - x: Math.sin(angle) * 300 - y: Math.cos(angle) * 300 - vx: 0 - vy: 0 - scaleX: 1 - __proto__: vaquitaObj - vaquita.update() - vaquitas.push vaquita - - leftKey = 37 - upKey = 38 - rightKey = 39 - downKey = 40 - usedKeys = [ leftKey, upKey, rightKey, downKey ] - - keyDownActions = - 32: addVaquita - - pressedKeys = { } - pressedKeys[k] = 0 for k in usedKeys - - window.addEventListener 'keydown', (event)-> - code = event.keyCode - keyDownActions[ code ]?(event) - pressedKeys[ code ] = 1 - window.addEventListener 'keyup', (event)-> - pressedKeys[ event.keyCode ] = 0 - - do (x = 0, y = 0)-> reportErrors -> - time = 0 - vx = 0 - vy = 0 - ax = 0 - ay = 0 - # s = 1 - # x = 0 - # y = 0 - scaleX = 1 - scaleY = 1 - - window.cf = currentFrame = v.href - transformMatrix = getTransformMatrix(v) - transformMatrix.a = scaleX - transformMatrix.e = x - transformMatrix.f = y - - gameFrame = -> reportErrors -> - if (time & 0xff) is 0x00 and vaquitas.length < 4 - addVaquita() - # s += 0.001 - x -= vx = pressedKeys[leftKey] - pressedKeys[rightKey] - y -= pressedKeys[upKey] - pressedKeys[downKey] - if vx > 0 - scaleX = 1 - else if vx < 0 - scaleX = -1 - v.setAttribute("transform", "translate(#{x}, #{y}) scale(#{scaleX}, #{scaleY})") - # transform = v.transform.baseVal.getItem(0) - # transformMatrix.a = scaleX - # transformMatrix.e = x - # transformMatrix.f = y - if (time % 3) is 0 - if currentFrame.baseVal is "#twistleft" - currentFrame .baseVal = "#_" - else if vx isnt 0 - currentFrame.baseVal = "#twistleft" - # transformList.initialize(transform) - vq.update() for vq in vaquitas - time++ - - setInterval gameFrame, 40 - -genPage() diff --git a/game.html b/game.html index dbc0536..ffb3936 100644 --- a/game.html +++ b/game.html @@ -1,5 +1,5 @@ -Vilma the Vaquita Demo
Vilma the Vaquita Demo v0.0.12 - Learn about Vaquitas
\ No newline at end of file diff --git a/game.html.coffee b/game.html.coffee index d31c1af..4184cca 100644 --- a/game.html.coffee +++ b/game.html.coffee @@ -1,24 +1,16 @@ # Copyright (c) 2013, 2014 Michele Bini -# This program is free software: you can redistribute it and/or modify -# it under the terms of the version 3 of the GNU General Public License -# as published by the Free Software Foundation. +# A game featuring a Vaquita, the smallest, most endagered marine cetacean -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. +# This program is available under the terms of the MIT License -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +version = "0.1.54" { htmlcup } = require 'htmlcup' -version = "0.0.12" - htmlcup[x] = htmlcup.compileTag x for x in [ "svg", "rect", "g", "ellipse", "polygon", "line", "image", "defs", "linearGradient", "stop", "use" ] -title = "Vilma the Vaquita Demo" +title = "Vilma the Vaquita" fs = require 'fs' @@ -36,7 +28,7 @@ frames = gameName = "#{title} v#{version}" -useSvg = true +htmlcup.jsFile = (f)-> @script type:"text/javascript", (fs.readFileSync(f).toString()) genPage = -> htmlcup.html5Page -> @@ -58,6 +50,7 @@ genPage = -> font-family: Helvetica; color:white; color:rgba(255,255,255,0.9); + margin:0; } .banner { border: 5px solid white; @@ -65,14 +58,16 @@ genPage = -> box-shadow: 0 2px 4px blue; margin: 1em; } - p { + footer, p { margin-top:0.418em; margin-bottom:0.418em; margin-left:auto; margin-right:auto; + text-shadow: 0 1px 1px blue; + } + p { width:22em; max-width:100%; - text-shadow: 0 1px 1px blue; } a { /* @@ -164,8 +159,12 @@ genPage = -> @body -> @div class:"centering page", -> @div class:"centered", -> - if useSvg - @svg id:"sea-svgroot", width:"960", height:"720", -> + @div style:"visibility:hidden;position:absolute", -> + @img id:"pixyvaquita", src:pixyvaquita + @img id:"pixyvaquita_105", src:frames._v105 + @img id:"pixyvaquita_twistleft", src:frames.twistleft + @div style:"position:relative", -> + @svg id:"sea-svgroot", width:"960", height:"720", style:"position:absolute;opacity:0.9;z-index:-1000", -> @defs -> @linearGradient id:"grad1", x1:"0%", y1:"0%", x2:"0%", y2:"100%", -> @stop offset:"0%", style:"stop-color:rgb(255,255,255);stop-opacity:1" @@ -173,142 +172,156 @@ genPage = -> @stop offset:"50%", style:"stop-color:rgb(0,80,240);stop-opacity:1" @stop offset:"75%", style:"stop-color:rgb(0,0,180);stop-opacity:1" @stop offset:"100%", style:"stop-color:rgb(0,0,0);stop-opacity:1" - for k,v of frames - @g id:k, -> - @g transform:"translate(-18,-15)", -> - @image width:"50", height:"30", "xlink:href":v @rect x:"0", y:"0", width:"960", height:"720", fill:"url(#grad1)" - @g transform:"scale(2)", -> - @g id:"sea", transform:"translate(240,180)", -> - @use "xlink:href":"#_" - else - @canvas width:"960", height:"720", -> - @div class:"dim", -> + @canvas width:"960", height:"720", -> + @footer class:"dim", -> @span gameName @span " - " @a target:"_blank", href:"index.html", "Learn about Vaquitas" + @span id:"fps" gameObjects = null @script type:"text/javascript", "gameObjects=#{JSON.stringify(gameObjects)};" - @coffeeScript -> - svgroot = document.getElementById("sea-svgroot") + @script type:"text/javascript", "__hasProp = {}.hasOwnProperty; __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };" + @jsFile "jaws/jaws-min.js" + # @jsFile "jaws-assets-named.js" + @coffeeScript -> do -> + # svgroot = document.getElementById("sea-svgroot") + + # reportErrors = (x)-> + # try + # x() + # catch error + # try + # alert error.toString() + # catch error2 + # alert error screen_x1 = 240 screen_y1 = 180 - vaquitas = [ ] - vaquitaObj = - update: (x, y)-> - if !window.abcd - window.abcd = 1 - vx = @vx + Math.floor(Math.random()*3) - 1 - vy = @vy + Math.floor(Math.random()*3) - 1 - x = @x - y = @y - rx = 0.5 * x / screen_x1 - ry = 0.5 * y / screen_y1 - if (s = vx * vx + vy * vy * 2) > 6 - vx = Math.round(vx * 0.9 + rx) - vy = Math.round(vy * 0.9 + ry) - @x = x -= @vx = vx - @y = y -= @vy = vy - if vx > 0 - @scaleX = 1 - else if vx < 0 - @scaleX = -1 - @e.setAttribute "transform", "translate(#{x}, #{y}) scale(#{@scaleX}, 1)" - # m = @m; m.e = x; m.f = y; m.a = @scaleX - sea = document.getElementById "sea" - v = sea.firstChild - - getTransformMatrix = (el)-> - transformListXX = el.transform.baseVal - transformMatrixXX = svgroot.createSVGMatrix() - transformXX = svgroot.createSVGTransform() - transformXX.setMatrix(transformMatrixXX) - transformListXX.initialize(transformXX) - transformXX.matrix - - addVaquita = -> - n = v.cloneNode() - n.setAttribute "opacity", "0.5" - n.href.baseVal = "#_v105" if Math.random(0) > 0.5 - # n.setAttribute "transform", "" - sea.appendChild n - angle = Math.random() * 6.28 - vaquita = - e: n - # m: getTransformMatrix(n) - x: Math.sin(angle) * 300 - y: Math.cos(angle) * 300 - vx: 0 - vy: 0 - scaleX: 1 - __proto__: vaquitaObj - vaquita.update() - vaquitas.push vaquita - - leftKey = 37 - upKey = 38 - rightKey = 39 - downKey = 40 - usedKeys = [ leftKey, upKey, rightKey, downKey ] - - keyDownActions = - 32: addVaquita - - pressedKeys = { } - pressedKeys[k] = 0 for k in usedKeys - - keydown = (event)-> - code = event.keyCode - keyDownActions[ code ]?(event) - pressedKeys[ code ] = 1 - keydown = (event)-> - pressedKeys[ event.keyCode ] = 0 - window.addEventListener 'keydown', keydown, true - window.addEventListener 'keyup', keyup, true - - do (x = 0, y = 0)-> - time = 0 - vx = 0 - vy = 0 - ax = 0 - ay = 0 - # s = 1 - # x = 0 - # y = 0 - scaleX = 1 - scaleY = 1 - - window.cf = currentFrame = v.href - # transformMatrix = getTransformMatrix(v) - # transformMatrix.a = scaleX - # transformMatrix.e = x - # transformMatrix.f = y + + jaws.onload = -> + class Demo + { left: leftKey, right: rightKey, up: upKey, down: downKey, space: spaceKey } = jaws.keyCodes + Sprite = class extends jaws.Sprite + # caller needs to set lr for flip center + constructor: -> + super + image: @image + x: 0 + y: 0 + scale: 2 + FlippableSprite = class extends Sprite + draw: -> + @flipped = @lr >= 0 + @x = (screen_x1 + @px + @lr) * 2 + @y = (screen_y1 + @py - 5) * 2 + super() + Vaquita = class extends FlippableSprite + constructor: -> + @lr = 18 + super() + draw: -> + if @vx < 0 + @lr = - 18 + else if @vx > 0 + @lr = 18 + super() + AiVaquita = class extends Vaquita + constructor: -> + @image = if Math.random() > 0.5 then pixyvaquita_105 else pixyvaquita + super() + draw: -> + vx = @vx + Math.floor(Math.random()*3) - 1 + vy = @vy + Math.floor(Math.random()*3) - 1 + x = @px + y = @py + rx = 0.5 * x / screen_x1 + ry = 0.5 * y / screen_y1 + if (s = vx * vx + vy * vy * 2) > 6 + vx = Math.round(vx * 0.9 - rx) + vy = Math.round(vy * 0.9 - ry) + @px += @vx = vx + @py += @vy = vy + super() + HeroVaquita = class extends Vaquita + twistleft = pixyvaquita_twistleft + constructor: -> + @image = pixyvaquita + @time = 0 + super() + draw: -> + @vx = (if jaws.pressed[leftKey] then -1 else 0) + (if jaws.pressed[rightKey] then 1 else 0) + @vy = (if jaws.pressed[upKey] then -1 else 0) + (if jaws.pressed[downKey] then 1 else 0) + @px += @vx + @py += @vy + if (@time++ % 3) is 0 + if @image is twistleft + @image = pixyvaquita + else if @vx isnt 0 + @image = twistleft + super() + addVaquita: -> + # n = v.cloneNode() + # n.setAttribute "opacity", "0.5" + # n.href.baseVal = "#_v105" if Math.random(0) > 0.5 + # n.setAttribute "transform", "" + # sea.appendChild n + angle = Math.random() * 6.28 + v = new AiVaquita + v.vx = 0 + v.vy = 0 + v.px = Math.floor(Math.sin(angle) * 300) + v.py = Math.floor(Math.cos(angle) * 300) + v.draw() + # vaquita.update() + @vaquitas.push v + constructor: (@vaquitas = [])-> + setup: -> + v = new HeroVaquita # jaws.Sprite x:screen_x1*2, y:screen_y1*2, scale:2, image:pixyvaquita + v.px = 0 + v.py = 0 + v.vx = 0 + v.vy = 0 + @vaquitas.push v + draw: -> + jaws.clear() + @addVaquita() if @vaquitas.length < 7 or jaws.pressed[spaceKey] + v.draw() for v in @vaquitas + if (@gameloop.ticks & 0xff) is 0xff + fps.innerHTML = " - #{@gameloop.fps} fps" + if true + jaws.init() + jaws.setupInput(); + game = new Demo + gameloop = new jaws.GameLoop(game, { fps:24 }) + (game.gameloop = gameloop).start() + else + jaws.start Demo, fps:25 - gameFrame = -> - if (time & 0xff) is 0x00 and vaquitas.length < 4 - addVaquita() - # s += 0.001 - x -= vx = pressedKeys[leftKey] - pressedKeys[rightKey] - y -= pressedKeys[upKey] - pressedKeys[downKey] - if vx > 0 - scaleX = 1 - else if vx < 0 - scaleX = -1 - v.setAttribute("transform", "translate(#{x}, #{y}) scale(#{scaleX}, #{scaleY})") - # # transform = v.transform.baseVal.getItem(0) - # transformMatrix.a = scaleX - # transformMatrix.e = x - # transformMatrix.f = y - if (time % 3) is 0 - if currentFrame.baseVal is "#twistleft" - currentFrame .baseVal = "#_" - else if vx isnt 0 - currentFrame.baseVal = "#twistleft" - # transformList.initialize(transform) - vq.update() for vq in vaquitas - time++ + # gameFrame = -> reportErrors -> + # if (time & 0xff) is 0x00 and vaquitas.length < 4 + # addVaquita() + # # s += 0.001 + # x -= vx = pressedKeys[leftKey] - pressedKeys[rightKey] + # y -= pressedKeys[upKey] - pressedKeys[downKey] + # if vx > 0 + # scaleX = 1 + # else if vx < 0 + # scaleX = -1 + # v.setAttribute("transform", "translate(#{x}, #{y}) scale(#{scaleX}, #{scaleY})") + # # transform = v.transform.baseVal.getItem(0) + # # transformMatrix.a = scaleX + # # transformMatrix.e = x + # # transformMatrix.f = y + # if (time % 3) is 0 + # if currentFrame.baseVal is "#twistleft" + # currentFrame .baseVal = "#_" + # else if vx isnt 0 + # currentFrame.baseVal = "#twistleft" + # # transformList.initialize(transform) + # vq.update() for vq in vaquitas + # time++ - setInterval gameFrame, 40 + # # setInterval gameFrame, 40 genPage() diff --git a/jaws-assets-named.coffee b/jaws-assets-named.coffee new file mode 100644 index 0000000..4a7a5df --- /dev/null +++ b/jaws-assets-named.coffee @@ -0,0 +1,456 @@ +# LGPL-licensed, please consult jawsjs.com +# conversion to coffeescript modification of src_assets.js from 'jawsjs.com' by Michele Bini + +# this supports named assets: like named:ImageName:image.png" + +jaws = ((jaws) -> + + ###* + @fileOverview jaws.assets properties and functions + + Loads and processes image, sound, video, and json assets + (Used internally by JawsJS to create jaws.assets) + + @class Jaws.Assets + @constructor + @property {boolean} bust_cache Add a random argument-string to assets-urls when loading to bypass any cache + @property {boolean} fuchia_to_transparent Convert the color fuchia to transparent when loading .bmp-files + @property {boolean} image_to_canvas Convert all image assets to canvas internally + @property {string} root Rootdir from where all assets are loaded + @property {array} file_type Listing of file postfixes and their associated types + @property {array} can_play Listing of postfixes and (during runtime) populated booleans + ### + + ###* + Returns the length of the resource list + @public + @returns {number} The length of the resource list + ### + + ###* + Set root prefix-path to all assets + + @example + jaws.assets.setRoot("music/").add(["music.mp3", "music.ogg"]).loadAll() + + @public + @param {string} path-prefix for all following assets + @returns {object} self + ### + + ###* + Get one or more resources from their URLs. Supports simple wildcard (you can end a string with "*"). + + @example + jaws.assets.add(["song.mp3", "song.ogg"]) + jaws.assets.get("song.*") // -> Will return song.ogg in firefox and song.mp3 in IE + + @public + @param {string|array} src The resource(s) to retrieve + @returns {array|object} Array or single resource if found in cache. Undefined otherwise. + ### + + # Wildcard? song.*, match against asset-srcs, make sure it's loaded and return content of first match. + + # TODO: self.loaded[src] is false for supported files for some odd reason. + + ###* + Returns if specified resource is currently loading or not + @public + @param {string} src Resource URL + @return {boolean|undefined} If resource is currently loading. Otherwise, undefined. + ### + + ###* + Returns if specified resource is loaded or not + @param src Source URL + @return {boolean|undefined} If specified resource is loaded or not. Otherwise, undefined. + ### + + ###* + Returns lowercase postfix of specified resource + @public + @param {string} src Resource URL + @returns {string} Lowercase postfix of resource + ### + + ###* + Determine type of file (Image, Audio, or Video) from its postfix + @private + @param {string} src Resource URL + @returns {string} Matching type {Image, Audio, Video} or the postfix itself + ### + + ###* + Add URL(s) to asset listing for later loading + @public + @param {string|array|arguments} src The resource URL(s) to add to the asset listing + @example + jaws.assets.add("player.png") + jaws.assets.add(["media/bullet1.png", "media/bullet2.png"]) + jaws.assets.add("foo.png", "bar.png") + jaws.assets.loadAll({onload: start_game}) + ### + + ###* + Iterate through the list of resource URL(s) and load each in turn. + @public + @param {Object} options Object-literal of callback functions + @config {function} [options.onprogress] The function to be called on progress (when one assets of many is loaded) + @config {function} [options.onerror] The function to be called if an error occurs + @config {function} [options.onload] The function to be called when finished + ### + + ###* + Loads a single resource from its given URL + Will attempt to match a resource to known MIME types. + If unknown, loads the file as a blob-object. + + @public + @param {string} src Resource URL + @param {Object} options Object-literal of callback functions + @config {function} [options.onload] Function to be called when assets has loaded + @config {function} [options.onerror] Function to be called if an error occurs + @example + jaws.load("media/foo.png") + jaws.load("http://place.tld/foo.png") + ### + # NOTE: assetLoaded can be called several times during loading. + + #Load everything else as raw blobs... + + # ... But don't load un-supported audio-files. + + # Initial loading callback for all assets for parsing specific filetypes or + # optionally converting images to canvas-objects. + # @private + # @param {EventObject} event The EventObject populated by the calling event + # @see processCallbacks() + + # + # * Only increment load_count ONCE per unique asset. + # * This is needed cause assetLoaded-callback can in certain cases be called several for a single asset... + # * ..and not only Once when it's loaded. + # + + # Called when jaws asset-handler decides that an asset shouldn't be loaded + # For example, an unsupported audio-format won't be loaded. + + # @private + + # Increases the error count and calls processCallbacks with false flag set + # @see processCallbacks() + # @private + # @param {EventObject} event The EventObject populated by the calling event + + # Processes (if set) the callbacks per resource + # @private + # @param {object} asset The asset to be processed + # @param {boolean} ok If an error has occured with the asset loading + # @param {EventObject} event The EventObject populated by the calling event + # @see jaws.start() in core.js + + # Displays the progress of asset handling as an overall percentage of all loading + # (Can be overridden as jaws.assets.displayProgress = function(percent_done) {}) + # @public + # @param {number} percent_done The overall percentage done across all resource handling + + # Make Fuchia (0xFF00FF) transparent (BMPs ONLY) + # @private + # @param {HTMLImageElement} image The Bitmap Image to convert + # @returns {CanvasElement} canvas The translated CanvasElement + + fuchiaToTransparent = (image) -> + return unless jaws.isDrawable(image) + canvas = (if jaws.isImage(image) then jaws.imageToCanvas(image) else image) + context = canvas.getContext("2d") + img_data = context.getImageData(0, 0, canvas.width, canvas.height) + pixels = img_data.data + i = 0 + + while i < pixels.length + # Color: Fuchia + pixels[i + 3] = 0 if pixels[i] is 255 and pixels[i + 1] is 0 and pixels[i + 2] is 255 # Set total see-through transparency + i += 4 + context.putImageData img_data, 0, 0 + canvas + jaws.Assets = Assets = -> + getType = (src) -> + if jaws.isString(src) + postfix = self.getPostfix(src) + (if self.file_type[postfix] then self.file_type[postfix] else postfix) + else + jaws.log.error "jaws.assets.getType: Argument not a String with " + src + return + assetLoaded = (event) -> + asset = @asset + src = asset.src + filetype = getType(asset.src) + try + if filetype is "json" + return if @readyState isnt 4 + self.data[asset.src] = JSON.parse(@responseText) + else if filetype is "image" + new_image = (if self.image_to_canvas then jaws.imageToCanvas(asset.image) else asset.image) + new_image = fuchiaToTransparent(new_image) if self.fuchia_to_transparent and self.getPostfix(asset.src) is "bmp" + self.data[asset.src] = new_image + else if filetype is "audio" and self.can_play[self.getPostfix(asset.src)] + self.data[asset.src] = asset.audio + else if filetype is "video" and self.can_play[self.getPostfix(asset.src)] + self.data[asset.src] = asset.video + else + self.data[asset.src] = @response + catch e + jaws.log.error "Cannot process " + src + " (Message: " + e.message + ", Name: " + e.name + ")" + self.data[asset.src] = null + self.load_count++ unless self.loaded[src] + self.loaded[src] = true + self.loading[src] = false + processCallbacks asset, true, event + return + assetSkipped = (asset) -> + self.loaded[asset.src] = true + self.loading[asset.src] = false + self.load_count++ + processCallbacks asset, true + return + assetError = (event) -> + asset = @asset + self.error_count++ + processCallbacks asset, false, event + return + processCallbacks = (asset, ok, event) -> + percent = parseInt((self.load_count + self.error_count) / self.src_list.length * 100) + if ok + self.onprogress asset.src, percent if self.onprogress + asset.onprogress event if asset.onprogress and event isnt `undefined` + else + self.onerror asset.src, percent if self.onerror + asset.onerror event if asset.onerror and event isnt `undefined` + if percent is 100 + self.onload() if self.onload + self.onprogress = null + self.onerror = null + self.onload = null + return + return new arguments.callee() unless this instanceof arguments.callee + self = this + self.loaded = [] + self.loading = [] + self.src_list = [] + self.data = [] + self.bust_cache = false + self.image_to_canvas = true + self.fuchia_to_transparent = true + self.root = "" + self.file_type = {} + self.file_type["json"] = "json" + self.file_type["wav"] = "audio" + self.file_type["mp3"] = "audio" + self.file_type["ogg"] = "audio" + self.file_type["m4a"] = "audio" + self.file_type["weba"] = "audio" + self.file_type["aac"] = "audio" + self.file_type["mka"] = "audio" + self.file_type["flac"] = "audio" + self.file_type["png"] = "image" + self.file_type["jpg"] = "image" + self.file_type["jpeg"] = "image" + self.file_type["gif"] = "image" + self.file_type["bmp"] = "image" + self.file_type["tiff"] = "image" + self.file_type["mp4"] = "video" + self.file_type["webm"] = "video" + self.file_type["ogv"] = "video" + self.file_type["mkv"] = "video" + self.can_play = {} + try + audioTest = new Audio() + self.can_play["wav"] = !!audioTest.canPlayType("audio/wav; codecs=\"1\"").replace(/^no$/, "") + self.can_play["ogg"] = !!audioTest.canPlayType("audio/ogg; codecs=\"vorbis\"").replace(/^no$/, "") + self.can_play["mp3"] = !!audioTest.canPlayType("audio/mpeg;").replace(/^no$/, "") + self.can_play["m4a"] = !!(audioTest.canPlayType("audio/x-m4a;") or audioTest.canPlayType("audio/aac;")).replace(/^no$/, "") + self.can_play["weba"] = !!audioTest.canPlayType("audio/webm; codecs=\"vorbis\"").replace(/^no$/, "") + self.can_play["aac"] = !!audioTest.canPlayType("audio/aac;").replace(/^no$/, "") + self.can_play["mka"] = !!audioTest.canPlayType("audio/x-matroska;").replace(/^no$/, "") + self.can_play["flac"] = !!audioTest.canPlayType("audio/x-flac;").replace(/^no$/, "") + try + videoTest = document.createElement("video") + self.can_play["mp4"] = !!videoTest.canPlayType("video/mp4;").replace(/^no$/, "") + self.can_play["webm"] = !!videoTest.canPlayType("video/webm; codecs=\"vorbis\"").replace(/^no$/, "") + self.can_play["ogv"] = !!videoTest.canPlayType("video/ogg; codecs=\"vorbis\"").replace(/^no$/, "") + self.can_play["mkv"] = !!videoTest.canPlayType("video/x-matroska;").replace(/^no$/, "") + self.length = -> + self.src_list.length + + self.setRoot = (path) -> + self.root = path + self + + self.get = (src) -> + if jaws.isArray(src) + src.map (i) -> + self.data[i] + + else if jaws.isString(src) + if src[src.length - 1] is "*" + needle = src.replace("*", "") + i = 0 + + while i < self.src_list.length + return self.data[self.src_list[i]] if self.src_list[i].indexOf(needle) is 0 and self.data[self.src_list[i]] + i++ + if self.data[src] + self.data[src] + else + jaws.log.warn "No such asset: " + src, true + else + jaws.log.error "jaws.get: Neither String nor Array. Incorrect URL resource " + src + return + return + + self.isLoading = (src) -> + if jaws.isString(src) + self.loading[src] + else + jaws.log.error "jaws.isLoading: Argument not a String with " + src + return + + self.isLoaded = (src) -> + if jaws.isString(src) + self.loaded[src] + else + jaws.log.error "jaws.isLoaded: Argument not a String with " + src + return + + self.getPostfix = (src) -> + if jaws.isString(src) + src.toLowerCase().match(/.+\.([^?]+)(\?|$)/)[1] + else + jaws.log.error "jaws.assets.getPostfix: Argument not a String with " + src + return + + self.add = (src) -> + list = arguments + list = list[0] if list.length is 1 and jaws.isArray(list[0]) + i = 0 + + while i < list.length + if jaws.isArray(list[i]) + self.add list[i] + else + if jaws.isString(list[i]) + self.src_list.push list[i] + else + jaws.log.error "jaws.assets.add: Neither String nor Array. Incorrect URL resource " + src + i++ + self + + self.loadAll = (options) -> + self.load_count = 0 + self.error_count = 0 + self.onprogress = options.onprogress if options.onprogress and jaws.isFunction(options.onprogress) + self.onerror = options.onerror if options.onerror and jaws.isFunction(options.onerror) + self.onload = options.onload if options.onload and jaws.isFunction(options.onload) + self.src_list.forEach (item) -> + self.load item + return + + self + + self.load = (src, options) -> + options = {} unless options + unless jaws.isString(src) + jaws.log.error "jaws.assets.load: Argument not a String with " + src + return + asset = {} + resolved_src = "" + if parts =/^named:([^:]+):/.exec src + asset.name = parts[1] + src = src.substring parts[0].length + asset.src = src + asset.onload = options.onload + asset.onerror = options.onerror + self.loading[src] = true + parser = RegExp("^((f|ht)tp(s)?:)?//") + if /^[a-z][a-z0-9-]*:/.test(src) + resolved_src = asset.src + else + resolved_src = self.root + asset.src + resolved_src += "?" + parseInt(Math.random() * 10000000) if self.bust_cache + type = getType(asset.src) + if type is "image" + try + asset.image = new Image() + asset.image.asset = asset + asset.image.addEventListener "load", assetLoaded + asset.image.addEventListener "error", assetError + asset.image.src = resolved_src + catch e + jaws.log.error "Cannot load Image resource " + resolved_src + " (Message: " + e.message + ", Name: " + e.name + ")" + else if self.can_play[self.getPostfix(asset.src)] + if type is "audio" + try + asset.audio = new Audio() + asset.audio.asset = asset + asset.audio.addEventListener "error", assetError + asset.audio.addEventListener "canplay", assetLoaded + self.data[asset.src] = asset.audio + asset.audio.src = resolved_src + asset.audio.load() + catch e + jaws.log.error "Cannot load Audio resource " + resolved_src + " (Message: " + e.message + ", Name: " + e.name + ")" + else if type is "video" + try + asset.video = document.createElement("video") + asset.video.asset = asset + self.data[asset.src] = asset.video + asset.video.setAttribute "style", "display:none;" + asset.video.addEventListener "error", assetError + asset.video.addEventListener "canplay", assetLoaded + document.body.appendChild asset.video + asset.video.src = resolved_src + asset.video.load() + catch e + jaws.log.error "Cannot load Video resource " + resolved_src + " (Message: " + e.message + ", Name: " + e.name + ")" + else + if type is "audio" and not self.can_play[self.getPostfix(asset.src)] + assetSkipped asset + return self + try + req = new XMLHttpRequest() + req.asset = asset + req.onreadystatechange = assetLoaded + req.onerror = assetError + req.open "GET", resolved_src, true + req.responseType = "blob" if type isnt "json" + req.send null + catch e + jaws.log.error "Cannot load " + resolved_src + " (Message: " + e.message + ", Name: " + e.name + ")" + self + + self.displayProgress = (percent_done) -> + return unless jaws.isNumber(percent_done) + return unless jaws.context + jaws.context.save() + jaws.context.fillStyle = "black" + jaws.context.fillRect 0, 0, jaws.width, jaws.height + jaws.context.fillStyle = "white" + jaws.context.strokeStyle = "white" + jaws.context.textAlign = "center" + jaws.context.strokeRect 50 - 1, (jaws.height / 2) - 30 - 1, jaws.width - 100 + 2, 60 + 2 + jaws.context.fillRect 50, (jaws.height / 2) - 30, ((jaws.width - 100) / 100) * percent_done, 60 + jaws.context.font = "11px verdana" + jaws.context.fillText "Loading... " + percent_done + "%", jaws.width / 2, jaws.height / 2 - 35 + jaws.context.font = "11px verdana" + jaws.context.fillStyle = "#ccc" + jaws.context.textBaseline = "bottom" + jaws.context.fillText "powered by www.jawsjs.com", jaws.width / 2, jaws.height - 1 + jaws.context.restore() + return + + return + + jaws.assets = new jaws.Assets() + jaws +)(jaws or {}) diff --git a/jaws/jaws-min.js b/jaws/jaws-min.js old mode 100644 new mode 100755 index 82c1680..79fe719 --- a/jaws/jaws-min.js +++ b/jaws/jaws-min.js @@ -1,2 +1,2 @@ -var jaws=function(t){function e(e){t.mouse_x=e.pageX||e.clientX,t.mouse_y=e.pageY||e.clientY;var i=t.canvas?t.canvas:t.dom;t.mouse_x-=i.offsetLeft,t.mouse_y-=i.offsetTop}var i,s;return t.SpriteList=function(){throw"To use SpriteList() you need to include src/extras/sprite_list.js"},t.Audio=function(){throw"To use jaws.Audio() you need to include src/extras/audio.js"},t.title=function(e){return t.isString(e)?e?i.innerHTML=e:i.innerHTML:void t.log.error("jaws.title: Passed in value is not a String.")},t.unpack=function(){var e=["Sprite","SpriteList","Animation","SpriteSheet","Parallax","pressed","QuadTree"];e.forEach(function(e){window[e]?t.log.warn("jaws.unpack: "+e+" already exists in global namespace."):window[e]=t[e]})},t.log=function(e,i){t.isString(e)||(e=JSON.stringify(e)),t.log.on&&(s&&t.log.use_log_element&&(i?s.innerHTML+=e+"
":s.innerHTML=e),console.log&&t.log.use_console&&console.log("JawsJS: ",e))},t.log.on=!0,t.log.use_console=!1,t.log.use_log_element=!0,t.log.warn=function(e){console.warn&&t.log.use_console&&t.log.on?console.warn(e):t.log("[WARNING]: "+JSON.stringify(e),!0)},t.log.error=function(e){console.error&&t.log.use_console&&t.log.on?console.error(e):t.log("[ERROR]: "+JSON.stringify(e),!0)},t.log.info=function(e){console.info&&t.log.use_console&&t.log.on?console.info(e):t.log("[INFO]: "+JSON.stringify(e),!0)},t.log.debug=function(e){console.debug&&t.log.use_console&&t.log.on?console.debug(e):t.log("[DEBUG]: "+JSON.stringify(e),!0)},t.log.clear=function(){s&&(s.innerHTML=""),console.clear&&console.clear()},t.init=function(o){i=document.getElementsByTagName("title")[0],t.url_parameters=t.getUrlParameters(),t.canvas=document.getElementsByTagName("canvas")[0],t.canvas||(t.dom=document.getElementById("canvas")),t.canvas?t.context=t.canvas.getContext("2d"):t.dom?t.dom.style.position="relative":(t.canvas=document.createElement("canvas"),t.canvas.width=o.width,t.canvas.height=o.height,t.context=t.canvas.getContext("2d"),document.body.appendChild(t.canvas)),s=document.getElementById("jaws-log"),t.url_parameters.debug&&(s||(s=document.createElement("div"),s.id="jaws-log",s.style.cssText="overflow: auto; color: #aaaaaa; width: 300px; height: 150px; margin: 40px auto 0px auto; padding: 5px; border: #444444 1px solid; clear: both; font: 10px verdana; text-align: left;",document.body.appendChild(s))),t.url_parameters.bust_cache&&(t.log.info("Busting cache when loading assets"),t.assets.bust_cache=!0),t.context&&t.useCrispScaling(),t.width=t.canvas?t.canvas.width:t.dom.offsetWidth,t.height=t.canvas?t.canvas.height:t.dom.offsetHeight,t.mouse_x=0,t.mouse_y=0,window.addEventListener("mousemove",e)},t.useCrispScaling=function(){t.context.imageSmoothingEnabled=!1,t.context.webkitImageSmoothingEnabled=!1,t.context.mozImageSmoothingEnabled=!1},t.useSmoothScaling=function(){t.context.imageSmoothingEnabled=!0,t.context.webkitImageSmoothingEnabled=!0,t.context.mozImageSmoothingEnabled=!0},t.start=function(e,i,s){function o(e,s){t.log.info(s+"%: "+e,!0),i.loading_screen&&t.assets.displayProgress(s)}function n(e,i){t.log.info(i+"%: Error loading asset "+e,!0)}function a(){t.log.info("all assets loaded",!0),t.switchGameState(e||window,{fps:r},s)}i||(i={});var r=i.fps||60;return void 0===i.loading_screen&&(i.loading_screen=!0),i.width||(i.width=500),i.height||(i.height=300),t.init(i),t.isFunction(e)||t.isObject(e)?t.isObject(s)||void 0===s?(i.loading_screen&&t.assets.displayProgress(0),t.log.info("setupInput()",!0),t.setupInput(),t.log.info("assets.loadAll()",!0),void(t.assets.length()>0?t.assets.loadAll({onprogress:o,onerror:n,onload:a}):a())):void t.log.error("jaws.start: The setup options for the game state is not an object."):void t.log.error("jaws.start: Passed in GameState is niether function or object")},t.switchGameState=function(e,i,s){if(void 0===i&&(i={}),t.isFunction(e)&&(e=new e),!t.isObject(e))return void t.log.error("jaws.switchGameState: Passed in GameState should be a Function or an Object.");var o=i&&i.fps||t.game_loop&&t.game_loop.fps||60,n=i.setup;t.game_loop&&t.game_loop.stop(),t.clearKeyCallbacks(),t.previous_game_state=t.game_state,t.game_state=e,t.game_loop=new t.GameLoop(e,{fps:o,setup:n},s),t.game_loop.start()},t.imageToCanvas=function(e){if(t.isCanvas(e))return e;if(!t.isImage(e))return void t.log.error("jaws.imageToCanvas: Passed in object is not an Image.");var i=document.createElement("canvas");i.src=e.src,i.width=e.width,i.height=e.height;var s=i.getContext("2d");return s.drawImage(e,0,0,e.width,e.height),i},t.forceArray=function(t){return Array.isArray(t)?t:[t]},t.clear=function(){t.context.clearRect(0,0,t.width,t.height)},t.fill=function(e){t.context.fillStyle=e,t.context.fillRect(0,0,t.width,t.height)},t.draw=function(){var e=arguments;1==e.length&&t.isArray(e[0])&&(e=e[0]);for(var i=0;it.width||e.y>t.height:void 0},t.forceInsideCanvas=function(e){e.x&&e.y&&(e.x<0&&(e.x=0),e.x>t.width&&(e.x=t.width),e.y<0&&(e.y=0),e.y>t.height&&(e.y=t.height))},t.getUrlParameters=function(){for(var t,e=[],i=window.location.href.slice(window.location.href.indexOf("?")+1).split("&"),s=0;su;u+=1)for(var d=Math.floor(u/i),f=u*h.width,p=d*e.width,g=0;c>g;g+=1){var m=Math.floor(g/i),w=4*(f+g),y=4*(p+m);h.data[w]=n[y],h.data[w+1]=n[y+1],h.data[w+2]=n[y+2],h.data[w+3]=n[y+3]}return r.putImageData(h,0,0),a},t}(jaws||{});"undefined"!=typeof module&&"exports"in module&&(module.exports=jaws);var jaws=function(t){function e(){h={}}function i(t){event=t?t:window.event;var e=l[event.keyCode];null!=e&&(e=e.split(" "),e.forEach(function(e){h[e]=!1,d[e]&&(d[e](e),t.preventDefault()),g[e]&&t.preventDefault()}))}function s(t){event=t?t:window.event;var e=l[event.keyCode];null!=e&&(e=e.split(" "),e.forEach(function(e){h[e]=!0,u[e]&&(u[e](e),t.preventDefault()),g[e]&&t.preventDefault()}))}function o(t){event=t?t:window.event;var e=f[event.button];"Microsoft Internet Explorer"==navigator.appName&&(e=p[event.button]),h[e]=!0,u[e]&&(u[e](e),t.preventDefault())}function n(t){event=t?t:window.event;var e=f[event.button];"Microsoft Internet Explorer"==navigator.appName&&(e=p[event.button]),h[e]=!1,d[e]&&(d[e](e),t.preventDefault())}function a(e){event=e?e:window.event,h.left_mouse_button=!0,t.mouse_x=e.touches[0].pageX-t.canvas.offsetLeft,t.mouse_y=e.touches[0].pageY-t.canvas.offsetTop}function r(e){event=e?e:window.event,h.left_mouse_button=!1,t.mouse_x=void 0,t.mouse_y=void 0}var h={},c={},l=[],u=[],d=[],f=[],p=[];t.setupInput=function(){var h=[];h[8]="backspace",h[9]="tab",h[13]="enter",h[16]="shift",h[17]="ctrl",h[18]="alt",h[19]="pause",h[20]="capslock",h[27]="esc",h[32]="space",h[33]="pageup",h[34]="pagedown",h[35]="end",h[36]="home",h[37]="left",h[38]="up",h[39]="right",h[40]="down",h[45]="insert",h[46]="delete",h[91]="left_window_key leftwindowkey",h[92]="right_window_key rightwindowkey",h[93]="select_key selectkey",h[106]="multiply *",h[107]="add plus +",h[109]="subtract minus -",h[110]="decimalpoint",h[111]="divide /",h[144]="numlock",h[145]="scrollock",h[186]="semicolon ;",h[187]="equalsign =",h[188]="comma ,",h[189]="dash -",h[190]="period .",h[191]="forwardslash /",h[192]="graveaccent `",h[219]="openbracket [",h[220]="backslash \\",h[221]="closebracket ]",h[222]="singlequote '";var c=[];c[0]="left_mouse_button",c[1]="center_mouse_button",c[2]="right_mouse_button";var u=[];u[1]="left_mouse_button",u[2]="right_mouse_button",u[4]="center_mouse_button",f=c,p=u;for(var d=["numpad0","numpad1","numpad2","numpad3","numpad4","numpad5","numpad6","numpad7","numpad8","numpad9"],g=["f1","f2","f3","f4","f5","f6","f7","f8","f9"],m=["0","1","2","3","4","5","6","7","8","9"],w=["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"],y=0;m[y];y++)h[48+y]=m[y];for(var y=0;w[y];y++)h[65+y]=w[y];for(var y=0;d[y];y++)h[96+y]=d[y];for(var y=0;g[y];y++)h[112+y]=g[y];l=h,window.addEventListener("keydown",s),window.addEventListener("keyup",i);var x=t.canvas||t.dom;x.addEventListener("mousedown",o,!1),x.addEventListener("mouseup",n,!1),x.addEventListener("touchstart",a,!1),x.addEventListener("touchend",r,!1),window.addEventListener("blur",e,!1),document.oncontextmenu=function(){return!1}};var g=[];return t.preventDefaultKeys=function(){var e=arguments;1==e.length&&t.isArray(e[0])&&(e=e[0]);for(var i=0;ithis.size){this.values.splice(0,1),this.value=0;for(var e=0;this.values[e];e++)this.value+=this.values[e];this.value=this.value/this.size}return this.values.push(t),this},this.get=function(){return parseInt(this.value)}}return window.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){window.setTimeout(t,16.666)}}(),t.GameLoop=function(i,s,o){if(!(this instanceof arguments.callee))return new arguments.callee(i,s);this.tick_duration=0,this.fps=0,this.ticks=0;var n,a=!1,r=!1,h=this,c=new e(20);this.runtime=function(){return this.last_tick-this.first_tick},this.start=function(){t.log.info("Game loop start",!0),this.first_tick=(new Date).getTime(),this.current_tick=(new Date).getTime(),this.last_tick=(new Date).getTime(),s.setup!==!1&&i.setup&&i.setup(o),step_delay=1e3/s.fps,60==s.fps?requestAnimFrame(this.loop):n=setInterval(this.loop,step_delay)},this.loop=function(){h.current_tick=(new Date).getTime(),h.tick_duration=h.current_tick-h.last_tick,h.fps=c.add(1e3/h.tick_duration).get(),r||a||(i.update&&i.update(),i.draw&&i.draw(),h.ticks++),60!=s.fps||r||requestAnimFrame(h.loop),h.last_tick=h.current_tick},this.pause=function(){a=!0},this.unpause=function(){a=!1},this.stop=function(){n&&clearInterval(n),r=!0}},t}(jaws||{}),jaws=function(t){var e=0;return t.Rect=function(t,i,s,o){return this instanceof arguments.callee?(this.x=t,this.y=i,this.width=s,this.height=o,this.right=t+s-e,void(this.bottom=i+o-e)):new arguments.callee(t,i,s,o)},t.Rect.prototype.getPosition=function(){return[this.x,this.y]},t.Rect.prototype.move=function(t,e){return this.x+=t,this.y+=e,this.right+=t,this.bottom+=e,this},t.Rect.prototype.moveTo=function(t,i){return this.x=t,this.y=i,this.right=this.x+this.width-e,this.bottom=this.y+this.height-e,this},t.Rect.prototype.resize=function(t,i){return this.width+=t,this.height+=i,this.right=this.x+this.width-e,this.bottom=this.y+this.height-e,this},t.Rect.prototype.clone=function(){return new t.Rect(this.x,this.y,this.width,this.height)},t.Rect.prototype.shrink=function(t,i){return this.x+=t,this.y+=i,this.width-=t+t,this.height-=i+i,this.right=this.x+this.width-e,this.bottom=this.y+this.height-e,this},t.Rect.prototype.resizeTo=function(t,i){return this.width=t,this.height=i,this.right=this.x+this.width-e,this.bottom=this.y+this.height-e,this},t.Rect.prototype.draw=function(){return t.context.strokeStyle="red",t.context.strokeRect(this.x-.5,this.y-.5,this.width,this.height),this},t.Rect.prototype.collidePoint=function(t,e){return t>=this.x&&t<=this.right&&e>=this.y&&e<=this.bottom},t.Rect.prototype.collideRect=function(t){return(this.x>=t.x&&this.x<=t.right||t.x>=this.x&&t.x<=this.right)&&(this.y>=t.y&&this.y<=t.bottom||t.y>=this.y&&t.y<=this.bottom)},t.Rect.prototype.toString=function(){return"[Rect "+this.x+", "+this.y+", "+this.width+", "+this.height+"]"},t}(jaws||{});"undefined"!=typeof module&&"exports"in module&&(module.exports=jaws.Rect);var jaws=function(jaws){return jaws.Sprite=function(t){return this instanceof arguments.callee?(this.set(t),void(this.context=t.context?t.context:jaws.context)):new arguments.callee(t)},jaws.Sprite.prototype.default_options={x:0,y:0,alpha:1,angle:0,flipped:!1,anchor_x:0,anchor_y:0,image:null,image_path:null,anchor:null,scale_image:null,damping:1,scale_x:1,scale_y:1,scale:1,color:"#ddd",width:16,height:16,_constructor:null,context:null,data:null},jaws.Sprite.prototype.set=function(t){if(jaws.isString(this.image)&&(this.image_path=this.image),jaws.parseOptions(this,t,this.default_options),this.scale&&(this.scale_x=this.scale_y=this.scale),this.image&&this.setImage(this.image),this.scale_image&&this.scaleImage(this.scale_image),this.anchor&&this.setAnchor(this.anchor),!this.image&&this.color&&this.width&&this.height){var e=document.createElement("canvas"),i=e.getContext("2d");e.width=this.width,e.height=this.height,i.fillStyle=this.color,i.fillRect(0,0,this.width,this.height),this.image=e}return this.cacheOffsets(),this},jaws.Sprite.prototype.clone=function(object){var constructor=this._constructor?eval(this._constructor):this.constructor,new_sprite=new constructor(this.attributes());return new_sprite._constructor=this._constructor||this.constructor.name,new_sprite},jaws.Sprite.prototype.setImage=function(t){var e=this;return jaws.isDrawable(t)?(this.image=t,this.cacheOffsets()):(jaws.assets.isLoaded(t)?(this.image=jaws.assets.get(t),this.cacheOffsets()):(jaws.log.warn("Image '"+t+"' not preloaded with jaws.assets.add(). Image and a working sprite.rect() will be delayed."),jaws.assets.load(t,{onload:function(){e.image=jaws.assets.get(t),e.cacheOffsets()}})),this)},jaws.Sprite.prototype.stepToWhile=function(t,e,i){var s=1,o=tthis.frame_duration&&(this.index+=this.frame_direction,this.sum_tick=0),(this.index>=this.frames.length||this.index<0)&&(this.bounce?(this.frame_direction=-this.frame_direction,this.index+=2*this.frame_direction):this.loop?this.index=this.frame_direction<0?this.frames.length-1:0:(this.index-=this.frame_direction,this.on_end&&(this.on_end(),this.on_end=null))),this},t.Animation.prototype.slice=function(e,i){var s={};return s.frame_duration=this.frame_duration,s.loop=this.loop,s.bounce=this.bounce,s.on_end=this.on_end,s.frame_direction=this.frame_direction,s.frames=this.frames.slice().slice(e,i),new t.Animation(s) -},t.Animation.prototype.next=function(){return this.update(),this.frames[this.index]},t.Animation.prototype.atLastFrame=function(){return this.index==this.frames.length-1},t.Animation.prototype.atFirstFrame=function(){return 0==this.index},t.Animation.prototype.currentFrame=function(){return this.frames[this.index]},t.Animation.prototype.toString=function(){return"[Animation, "+this.frames.length+" frames]"},t}(jaws||{});if("undefined"!=typeof require)var jaws=require("./core.js");var jaws=function(t){function e(t,e){for(var i=function(e){return void 0!==t.isSpriteList?t.at(e):t[e]},s=[],o=new Array(e),n=0;e>n;n++)o[n]=n;for(var n=e-1,a=t.length;n>=0;a=t.length){for(s.push(o.map(i));n>=0&&o[n]===a-1;)n--,a--;if(n>=0){o[n]+=1;for(var r=n+1;e>r;r++)o[r]=o[r-1]+1;n=e-1}}return s}return t.collideOneWithOne=function(e,i){return e.radius&&i.radius&&e!==i&&t.collideCircles(e,i)?!0:e.rect&&i.rect&&e!==i&&t.collideRects(e.rect(),i.rect())?!0:!1},t.collideOneWithMany=function(e,i,s){var o=[];if(s){for(var n=0;n=e.x&&t.x<=e.right||e.x>=t.x&&e.x<=t.right)&&(t.y>=e.y&&t.y<=e.bottom||e.y>=t.y&&e.y<=t.bottom)},t.distanceBetween=function(t,e){return Math.sqrt(Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2))},t.collide=function(e,i,s){if((e.rect||e.radius)&&i.forEach)return t.collideOneWithMany(e,i,s).length>0;if(e.forEach&&i.forEach)return t.collideManyWithMany(e,i,s).length>0;if(e.forEach&&(i.rect||i.radius))return t.collideOneWithMany(i,e,s).length>0;if(e.rect&&i.rect||e.radius&&i.radius){var o=t.collideOneWithOne(e,i);if(!s||!o)return o;s(e,i)}},t}(jaws||{}),jaws=function(t){return t.PixelMap=function(e){return this instanceof arguments.callee?(this.options=e,this.scale=e.scale||1,this.x=e.x||0,this.y=e.y||0,e.image?(this.setContext(e.image),e.scale_image&&this.setContext(t.retroScaleImage(this.context.canvas,e.scale_image)),this.width=this.context.canvas.width*this.scale,this.height=this.context.canvas.height*this.scale):t.log.warn("PixelMap needs an image to work with"),this.named_colors=[],void this.update()):new arguments.callee(e)},t.PixelMap.prototype.setContext=function(e){var e=t.isDrawable(e)?e:t.assets.get(e);this.context=t.imageToCanvasContext(e)},t.PixelMap.prototype.update=function(t,e,i,s){if((void 0===t||0>t)&&(t=0),(void 0===e||0>e)&&(e=0),(void 0===i||i>this.width)&&(i=this.width),(void 0===s||s>this.height)&&(s=this.height),0==arguments.length)this.data=this.context.getImageData(t,e,i,s).data;else for(var o=this.context.getImageData(t,e,i,s).data,n=0,a=4*this.width,r=e*this.width*4+4*t,h=4*i,c=0;s>c;c++){for(var l=0;h>l;l++)this.data[r+l]=o[n++];r+=a}},t.PixelMap.prototype.draw=function(){t.context.drawImage(this.context.canvas,this.x,this.y,this.width,this.height)},t.PixelMap.prototype.namedColorAtRect=function(t,e){for(var i=t.x,s=t.y;it.x;i--)if(this.namedColorAt(i,s)==e||void 0===e)return this.namedColorAt(i,s);for(;s>t.y;s--)if(this.namedColorAt(i,s)==e||void 0===e)return this.namedColorAt(i,s);return!1},t.PixelMap.prototype.at=function(t,e){t=parseInt(t),e=parseInt(e),0>e&&(e=0);var i=e*this.width*4+4*t,s=this.data[i],o=this.data[i+1],n=this.data[i+2],a=this.data[i+3];return[s,o,n,a]},t.PixelMap.prototype.namedColorAt=function(t,e){for(var i=this.at(t,e),s=0;s=0&&t.y+t.height>=0&&t.draw(),t.x=t.x+t.width,this.repeat_x););if(t.y=t.y+t.height,t.x=e,!this.repeat_y)break}},t.Parallax.prototype.addLayer=function(e){var i=new t.ParallaxLayer(e);i.scaleAll(this.scale),this.layers.push(i)},t.Parallax.prototype.toString=function(){return"[Parallax "+this.x+", "+this.y+". "+this.layers.length+" layers]"},t.ParallaxLayer=function(e){return this instanceof arguments.callee?(this.damping=e.damping||0,void t.Sprite.call(this,e)):new arguments.callee(e)},t.ParallaxLayer.prototype=t.Sprite.prototype,t}(jaws||{}),jaws=function(jaws){return jaws.Text=function(t){return this instanceof arguments.callee?(this.set(t),t.context&&(this.context=t.context),void(t.context||jaws.context&&(this.context=jaws.context))):new arguments.callee(t)},jaws.Text.prototype.default_options={x:0,y:0,alpha:1,angle:0,anchor_x:0,anchor_y:0,anchor:"top_left",damping:1,style:"normal",fontFace:"serif",fontSize:12,color:"black",textAlign:"start",textBaseline:"alphabetic",text:"",wordWrap:!1,width:function(){return jaws.width},height:function(){return jaws.height},shadowColor:null,shadowBlur:null,shadowOffsetX:null,shadowOffsetY:null,_constructor:null},jaws.Text.prototype.set=function(t){return jaws.parseOptions(this,t,this.default_options),this.anchor&&this.setAnchor(this.anchor),this.cacheOffsets(),this},jaws.Text.prototype.clone=function(){var constructor=this._constructor?eval(this._constructor):this.constructor,new_sprite=new constructor(this.attributes());return new_sprite._constructor=this._constructor||this.constructor.name,new_sprite},jaws.Text.prototype.rotate=function(t){return this.angle+=t,this},jaws.Text.prototype.rotateTo=function(t){return this.angle=t,this},jaws.Text.prototype.moveTo=function(t,e){return this.x=t,this.y=e,this},jaws.Text.prototype.move=function(t,e){return t&&(this.x+=t),e&&(this.y+=e),this},jaws.Text.prototype.setX=function(t){return this.x=t,this},jaws.Text.prototype.setY=function(t){return this.y=t,this},jaws.Text.prototype.setTop=function(t){return this.y=t+this.top_offset,this},jaws.Text.prototype.setBottom=function(t){return this.y=t-this.bottom_offset,this},jaws.Text.prototype.setLeft=function(t){return this.x=t+this.left_offset,this},jaws.Text.prototype.setRight=function(t){return this.x=t-this.right_offset,this},jaws.Text.prototype.setWidth=function(t){return this.width=t,this.cacheOffsets(),this},jaws.Text.prototype.setHeight=function(t){return this.height=t,this.cacheOffsets(),this},jaws.Text.prototype.resize=function(t,e){return this.width+=t,this.height+=e,this.cacheOffsets(),this},jaws.Text.prototype.resizeTo=function(t,e){return this.width=t,this.height=e,this.cacheOffsets(),this},jaws.Text.prototype.setAnchor=function(t){var e={top_left:[0,0],left_top:[0,0],center_left:[0,.5],left_center:[0,.5],bottom_left:[0,1],left_bottom:[0,1],top_center:[.5,0],center_top:[.5,0],center_center:[.5,.5],center:[.5,.5],bottom_center:[.5,1],center_bottom:[.5,1],top_right:[1,0],right_top:[1,0],center_right:[1,.5],right_center:[1,.5],bottom_right:[1,1],right_bottom:[1,1]};return e.hasOwnProperty(t)&&(this.anchor_x=e[t][0],this.anchor_y=e[t][1],this.cacheOffsets()),this},jaws.Text.prototype.cacheOffsets=function(){return this.left_offset=this.width*this.anchor_x,this.top_offset=this.height*this.anchor_y,this.right_offset=this.width*(1-this.anchor_x),this.bottom_offset=this.height*(1-this.anchor_y),this.cached_rect&&this.cached_rect.resizeTo(this.width,this.height),this},jaws.Text.prototype.rect=function(){return!this.cached_rect&&this.width&&(this.cached_rect=new jaws.Rect(this.x,this.y,this.width,this.height)),this.cached_rect&&this.cached_rect.moveTo(this.x-this.left_offset,this.y-this.top_offset),this.cached_rect},jaws.Text.prototype.draw=function(){this.context.save(),0!==this.angle&&this.context.rotate(this.angle*Math.PI/180),this.context.globalAlpha=this.alpha,this.context.translate(-this.left_offset,-this.top_offset),this.context.fillStyle=this.color,this.context.font=this.style+" "+this.fontSize+"px "+this.fontFace,this.context.textBaseline=this.textBaseline,this.context.textAlign=this.textAlign,this.shadowColor&&(this.context.shadowColor=this.shadowColor),this.shadowBlur&&(this.context.shadowBlur=this.shadowBlur),this.shadowOffsetX&&(this.context.shadowOffsetX=this.shadowOffsetX),this.shadowOffsetY&&(this.context.shadowOffsetY=this.shadowOffsetY);var t=this.y,e=this.x;if(this.wordWrap)for(var i=this.text.split(" "),s="",o=0;othis.width?(this.context.fillText(s,this.x,this.y),s=i[o]+" ",this.y+=this.fontSize):s=n,this.context.fillText(s,this.x,this.y))}else if(this.context.measureText(this.text).widththis.width?(this.context.fillText(n,this.x,this.y),n=o[a]+" ",this.y+=this.fontSize):n=r,this.context.fillText(n,this.x,this.y))}else if(this.context.measureText(this.text).widththis.width?(e.fillText(n,this.x,this.y),n=o[a]+" ",this.y+=this.fontSize):n=r,e.fillText(n,this.x,this.y))}else if(e.measureText(this.text).widths;return t.xi&&(o?e=0:n&&(e=3)),e},t.QuadTree.prototype.insert=function(t){if(t.hasOwnProperty("x")||t.hasOwnProperty("y")||t.hasOwnProperty("width")||t.hasOwnProperty("height")){if("undefined"!=typeof this.nodes[0]){var e=this.getIndex(t);if(-1!==e)return void this.nodes[e].insert(t)}this.objects.push(t),"undefined"==typeof this.nodes[0]&&this.split();for(var i=0;i":s.innerHTML=e),console.log&&t.log.use_console&&console.log("JawsJS: ",e))},t.log.on=!0,t.log.use_console=!1,t.log.use_log_element=!0,t.log.warn=function(e){console.warn&&t.log.use_console&&t.log.on?console.warn(e):t.log("[WARNING]: "+JSON.stringify(e),!0)},t.log.error=function(e){console.error&&t.log.use_console&&t.log.on?console.error(e):t.log("[ERROR]: "+JSON.stringify(e),!0)},t.log.info=function(e){console.info&&t.log.use_console&&t.log.on?console.info(e):t.log("[INFO]: "+JSON.stringify(e),!0)},t.log.debug=function(e){console.debug&&t.log.use_console&&t.log.on?console.debug(e):t.log("[DEBUG]: "+JSON.stringify(e),!0)},t.log.clear=function(){s&&(s.innerHTML=""),console.clear&&console.clear()},t.init=function(o){i=document.getElementsByTagName("title")[0],t.url_parameters=t.getUrlParameters(),t.canvas=document.getElementsByTagName("canvas")[0],t.canvas||(t.dom=document.getElementById("canvas")),t.canvas?t.context=t.canvas.getContext("2d"):t.dom?t.dom.style.position="relative":(t.canvas=document.createElement("canvas"),t.canvas.width=o.width,t.canvas.height=o.height,t.context=t.canvas.getContext("2d"),document.body.appendChild(t.canvas)),s=document.getElementById("jaws-log"),t.url_parameters.debug&&(s||(s=document.createElement("div"),s.id="jaws-log",s.style.cssText="overflow: auto; color: #aaaaaa; width: 300px; height: 150px; margin: 40px auto 0px auto; padding: 5px; border: #444444 1px solid; clear: both; font: 10px verdana; text-align: left;",document.body.appendChild(s))),t.url_parameters.bust_cache&&(t.log.info("Busting cache when loading assets"),t.assets.bust_cache=!0),t.context&&t.useCrispScaling(),t.width=t.canvas?t.canvas.width:t.dom.offsetWidth,t.height=t.canvas?t.canvas.height:t.dom.offsetHeight,t.mouse_x=0,t.mouse_y=0,window.addEventListener("mousemove",e)},t.useCrispScaling=function(){t.context.imageSmoothingEnabled=!1,t.context.webkitImageSmoothingEnabled=!1,t.context.mozImageSmoothingEnabled=!1},t.useSmoothScaling=function(){t.context.imageSmoothingEnabled=!0,t.context.webkitImageSmoothingEnabled=!0,t.context.mozImageSmoothingEnabled=!0},t.start=function(e,i,s){function o(e,s){t.log.info(s+"%: "+e,!0),i.loading_screen&&t.assets.displayProgress(s)}function n(e,i){t.log.info(i+"%: Error loading asset "+e,!0)}function a(){t.log.info("all assets loaded",!0),t.switchGameState(e||window,{fps:r},s)}i||(i={});var r=i.fps||60;return void 0===i.loading_screen&&(i.loading_screen=!0),i.width||(i.width=500),i.height||(i.height=300),t.init(i),t.isFunction(e)||t.isObject(e)?t.isObject(s)||void 0===s?(i.loading_screen&&t.assets.displayProgress(0),t.log.info("setupInput()",!0),t.setupInput(),t.log.info("assets.loadAll()",!0),void(t.assets.length()>0?t.assets.loadAll({onprogress:o,onerror:n,onload:a}):a())):void t.log.error("jaws.start: The setup options for the game state is not an object."):void t.log.error("jaws.start: Passed in GameState is niether function or object")},t.switchGameState=function(e,i,s){if(void 0===i&&(i={}),t.isFunction(e)&&(e=new e),!t.isObject(e))return void t.log.error("jaws.switchGameState: Passed in GameState should be a Function or an Object.");var o=i&&i.fps||t.game_loop&&t.game_loop.fps||60,n=i.setup;t.game_loop&&t.game_loop.stop(),t.clearKeyCallbacks(),t.previous_game_state=t.game_state,t.game_state=e,t.game_loop=new t.GameLoop(e,{fps:o,setup:n},s),t.game_loop.start()},t.imageToCanvas=function(e){if(t.isCanvas(e))return e;if(!t.isImage(e))return void t.log.error("jaws.imageToCanvas: Passed in object is not an Image.");var i=document.createElement("canvas");i.src=e.src,i.width=e.width,i.height=e.height;var s=i.getContext("2d");return s.drawImage(e,0,0,e.width,e.height),i},t.forceArray=function(t){return Array.isArray(t)?t:[t]},t.clear=function(){t.context.clearRect(0,0,t.width,t.height)},t.fill=function(e){t.context.fillStyle=e,t.context.fillRect(0,0,t.width,t.height)},t.draw=function(){var e=arguments;1==e.length&&t.isArray(e[0])&&(e=e[0]);for(var i=0;it.width||e.y>t.height:void 0},t.forceInsideCanvas=function(e){e.x&&e.y&&(e.x<0&&(e.x=0),e.x>t.width&&(e.x=t.width),e.y<0&&(e.y=0),e.y>t.height&&(e.y=t.height))},t.getUrlParameters=function(){for(var t,e=[],i=window.location.href.slice(window.location.href.indexOf("?")+1).split("&"),s=0;su;u+=1)for(var d=Math.floor(u/i),f=u*h.width,p=d*e.width,g=0;c>g;g+=1){var m=Math.floor(g/i),w=4*(f+g),x=4*(p+m);h.data[w]=n[x],h.data[w+1]=n[x+1],h.data[w+2]=n[x+2],h.data[w+3]=n[x+3]}return r.putImageData(h,0,0),a},t}(jaws||{});"undefined"!=typeof module&&"exports"in module&&(module.exports=jaws);var jaws=function(t){function e(){for(var t in h)delete h[t]}function i(t){var e=e=t.keyCode;h[e]=!1,d[e]?(d[e](e),t.preventDefault()):g[e]&&t.preventDefault()}function s(t){var e=e=t.keyCode;h[e]=!0,u[e]?(u[e](e),t.preventDefault()):g[e]&&t.preventDefault()}function o(t){var e=f[t.button];"Microsoft Internet Explorer"==navigator.appName&&(e=p[t.button]),h[e]=!0,u[e]&&(u[e](e),t.preventDefault())}function n(t){var e=f[t.button];"Microsoft Internet Explorer"==navigator.appName&&(e=p[t.button]),h[e]=!1,d[e]&&(d[e](e),t.preventDefault())}function a(e){h.left_mouse_button=!0,t.mouse_x=e.touches[0].pageX-t.canvas.offsetLeft,t.mouse_y=e.touches[0].pageY-t.canvas.offsetTop}function r(){h.left_mouse_button=!1,t.mouse_x=void 0,t.mouse_y=void 0}var h={},c={0:"48",1:"49",2:"50",3:"51",4:"52",5:"53",6:"54",7:"55",8:"56",9:"57",backspace:"8",tab:"9",enter:"13",shift:"16",ctrl:"17",alt:"18",pause:"19",caps_lock:"20",esc:"27",space:"32",page_up:"33",page_down:"34",end:"35",home:"36",left:"37",up:"38",right:"39",down:"40",insert:"45","delete":"46",a:"65",b:"66",c:"67",d:"68",e:"69",f:"70",g:"71",h:"72",i:"73",j:"74",k:"75",l:"76",m:"77",n:"78",o:"79",p:"80",q:"81",r:"82",s:"83",t:"84",u:"85",v:"86",w:"87",x:"88",y:"89",z:"90",windows_left:"91",windows_right:"92",select:"93",numpad0:"96",numpad1:"97",numpad2:"98",numpad3:"99",numpad4:"100",numpad5:"101",numpad6:"102",numpad7:"103",numpad8:"104",numpad9:"105",asterisk:"106",plus:"107",minus:"109",decimal_point:"110",divide:"111",f1:"112",f2:"113",f3:"114",f4:"115",f5:"116",f6:"117",f7:"118",f8:"119",f9:"120",numlock:"144",scrollock:"145",semicolon:"186",equals:"187",comma:"188",dash:"189",period:"190",slash:"191",grave_accent:"192",open_bracket:"219",backslash:"220",close_bracket:"221",single_quote:"222"},l={8:"backspace",9:"tab",13:"enter",16:"shift",17:"ctrl",18:"alt",19:"pause",20:"caps_lock",27:"esc",32:"space",33:"page_up",34:"page_down",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"insert",46:"delete",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",65:"a",66:"b",67:"c",68:"d",69:"e",70:"f",71:"g",72:"h",73:"i",74:"j",75:"k",76:"l",77:"m",78:"n",79:"o",80:"p",81:"q",82:"r",83:"s",84:"t",85:"u",86:"v",87:"w",88:"x",89:"y",90:"z",91:"windows_left",92:"windows_right",93:"select",96:"numpad0",97:"numpad1",98:"numpad2",99:"numpad3",100:"numpad4",101:"numpad5",102:"numpad6",103:"numpad7",104:"numpad8",105:"numpad9",106:"asterisk",107:"plus",109:"minus",110:"decimal_point",111:"divide",112:"f1",113:"f2",114:"f3",115:"f4",116:"f5",117:"f6",118:"f7",119:"f8",120:"f9",144:"numlock",145:"scrollock",186:"semicolon",187:"equals",188:"comma",189:"dash",190:"period",191:"slash",192:"grave_accent",219:"open_bracket",220:"backslash",221:"close_bracket",222:"single_quote"},u=[],d=[],f=[],p=[],g=[];return t.setupInput=function(){var h=[];h[0]="left_mouse_button",h[1]="center_mouse_button",h[2]="right_mouse_button";var c=[];c[1]="left_mouse_button",c[2]="right_mouse_button",c[4]="center_mouse_button",f=h,p=c,window.addEventListener("keydown",s),window.addEventListener("keyup",i);var l=t.canvas||t.dom;l.addEventListener("mousedown",o,!1),l.addEventListener("mouseup",n,!1),l.addEventListener("touchstart",a,!1),l.addEventListener("touchend",r,!1),window.addEventListener("blur",e,!1),document.oncontextmenu=function(){return!1}},t.preventDefaultKeys=function(){for(var t=arguments,e=0;ethis.size){this.values.splice(0,1),this.value=0;for(var e=0;this.values[e];e++)this.value+=this.values[e];this.value=this.value/this.size}return this.values.push(t),this},this.get=function(){return parseInt(this.value)}}return window.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){window.setTimeout(t,16.666)}}(),t.GameLoop=function(i,s,o){if(!(this instanceof arguments.callee))return new arguments.callee(i,s);this.tick_duration=0,this.fps=0,this.ticks=0;var n,a=!1,r=!1,h=this,c=new e(20);this.runtime=function(){return this.last_tick-this.first_tick},this.start=function(){t.log.info("Game loop start",!0),this.first_tick=(new Date).getTime(),this.current_tick=(new Date).getTime(),this.last_tick=(new Date).getTime(),s.setup!==!1&&i.setup&&i.setup(o),step_delay=1e3/s.fps,60==s.fps?requestAnimFrame(this.loop):n=setInterval(this.loop,step_delay)},this.loop=function(){h.current_tick=(new Date).getTime(),h.tick_duration=h.current_tick-h.last_tick,h.fps=c.add(1e3/h.tick_duration).get(),r||a||(i.update&&i.update(),i.draw&&i.draw(),h.ticks++),60!=s.fps||r||requestAnimFrame(h.loop),h.last_tick=h.current_tick},this.pause=function(){a=!0},this.unpause=function(){a=!1},this.stop=function(){n&&clearInterval(n),r=!0}},t}(jaws||{}),jaws=function(t){var e=0;return t.Rect=function(t,i,s,o){return this instanceof arguments.callee?(this.x=t,this.y=i,this.width=s,this.height=o,this.right=t+s-e,void(this.bottom=i+o-e)):new arguments.callee(t,i,s,o)},t.Rect.prototype.getPosition=function(){return[this.x,this.y]},t.Rect.prototype.move=function(t,e){return this.x+=t,this.y+=e,this.right+=t,this.bottom+=e,this},t.Rect.prototype.moveTo=function(t,i){return this.x=t,this.y=i,this.right=this.x+this.width-e,this.bottom=this.y+this.height-e,this},t.Rect.prototype.resize=function(t,i){return this.width+=t,this.height+=i,this.right=this.x+this.width-e,this.bottom=this.y+this.height-e,this},t.Rect.prototype.clone=function(){return new t.Rect(this.x,this.y,this.width,this.height)},t.Rect.prototype.shrink=function(t,i){return this.x+=t,this.y+=i,this.width-=t+t,this.height-=i+i,this.right=this.x+this.width-e,this.bottom=this.y+this.height-e,this},t.Rect.prototype.resizeTo=function(t,i){return this.width=t,this.height=i,this.right=this.x+this.width-e,this.bottom=this.y+this.height-e,this},t.Rect.prototype.draw=function(){return t.context.strokeStyle="red",t.context.strokeRect(this.x-.5,this.y-.5,this.width,this.height),this},t.Rect.prototype.collidePoint=function(t,e){return t>=this.x&&t<=this.right&&e>=this.y&&e<=this.bottom},t.Rect.prototype.collideRect=function(t){return(this.x>=t.x&&this.x<=t.right||t.x>=this.x&&t.x<=this.right)&&(this.y>=t.y&&this.y<=t.bottom||t.y>=this.y&&t.y<=this.bottom)},t.Rect.prototype.toString=function(){return"[Rect "+this.x+", "+this.y+", "+this.width+", "+this.height+"]"},t}(jaws||{});"undefined"!=typeof module&&"exports"in module&&(module.exports=jaws.Rect);var jaws=function(jaws){return jaws.Sprite=function(t){return this instanceof arguments.callee?(this.set(t),void(this.context=t.context?t.context:jaws.context)):new arguments.callee(t)},jaws.Sprite.prototype.default_options={x:0,y:0,alpha:1,angle:0,flipped:!1,anchor_x:0,anchor_y:0,image:null,image_path:null,anchor:null,scale_image:null,damping:1,scale_x:1,scale_y:1,scale:1,color:"#ddd",width:16,height:16,_constructor:null,context:null,data:null},jaws.Sprite.prototype.set=function(t){if(jaws.isString(this.image)&&(this.image_path=this.image),jaws.parseOptions(this,t,this.default_options),this.scale&&(this.scale_x=this.scale_y=this.scale),this.image&&this.setImage(this.image),this.scale_image&&this.scaleImage(this.scale_image),this.anchor&&this.setAnchor(this.anchor),!this.image&&this.color&&this.width&&this.height){var e=document.createElement("canvas"),i=e.getContext("2d");e.width=this.width,e.height=this.height,i.fillStyle=this.color,i.fillRect(0,0,this.width,this.height),this.image=e}return this.cacheOffsets(),this},jaws.Sprite.prototype.clone=function(object){var constructor=this._constructor?eval(this._constructor):this.constructor,new_sprite=new constructor(this.attributes());return new_sprite._constructor=this._constructor||this.constructor.name,new_sprite},jaws.Sprite.prototype.setImage=function(t){var e=this;return jaws.isDrawable(t)?(this.image=t,this.cacheOffsets()):(jaws.assets.isLoaded(t)?(this.image=jaws.assets.get(t),this.cacheOffsets()):(jaws.log.warn("Image '"+t+"' not preloaded with jaws.assets.add(). Image and a working sprite.rect() will be delayed."),jaws.assets.load(t,{onload:function(){e.image=jaws.assets.get(t),e.cacheOffsets()}})),this)},jaws.Sprite.prototype.stepToWhile=function(t,e,i){var s=1,o=tthis.frame_duration&&(this.index+=this.frame_direction,this.sum_tick=0),(this.index>=this.frames.length||this.index<0)&&(this.bounce?(this.frame_direction=-this.frame_direction,this.index+=2*this.frame_direction):this.loop?this.index=this.frame_direction<0?this.frames.length-1:0:(this.index-=this.frame_direction,this.on_end&&(this.on_end(),this.on_end=null))),this +},t.Animation.prototype.slice=function(e,i){var s={};return s.frame_duration=this.frame_duration,s.loop=this.loop,s.bounce=this.bounce,s.on_end=this.on_end,s.frame_direction=this.frame_direction,s.frames=this.frames.slice().slice(e,i),new t.Animation(s)},t.Animation.prototype.next=function(){return this.update(),this.frames[this.index]},t.Animation.prototype.atLastFrame=function(){return this.index==this.frames.length-1},t.Animation.prototype.atFirstFrame=function(){return 0==this.index},t.Animation.prototype.currentFrame=function(){return this.frames[this.index]},t.Animation.prototype.toString=function(){return"[Animation, "+this.frames.length+" frames]"},t}(jaws||{});if("undefined"!=typeof require)var jaws=require("./core.js");var jaws=function(t){function e(t,e){for(var i=function(e){return void 0!==t.isSpriteList?t.at(e):t[e]},s=[],o=new Array(e),n=0;e>n;n++)o[n]=n;for(var n=e-1,a=t.length;n>=0;a=t.length){for(s.push(o.map(i));n>=0&&o[n]===a-1;)n--,a--;if(n>=0){o[n]+=1;for(var r=n+1;e>r;r++)o[r]=o[r-1]+1;n=e-1}}return s}return t.collideOneWithOne=function(e,i){return e.radius&&i.radius&&e!==i&&t.collideCircles(e,i)?!0:e.rect&&i.rect&&e!==i&&t.collideRects(e.rect(),i.rect())?!0:!1},t.collideOneWithMany=function(e,i,s){var o=[];if(s){for(var n=0;n=e.x&&t.x<=e.right||e.x>=t.x&&e.x<=t.right)&&(t.y>=e.y&&t.y<=e.bottom||e.y>=t.y&&e.y<=t.bottom)},t.distanceBetween=function(t,e){return Math.sqrt(Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2))},t.collide=function(e,i,s){if((e.rect||e.radius)&&i.forEach)return t.collideOneWithMany(e,i,s).length>0;if(e.forEach&&i.forEach)return t.collideManyWithMany(e,i,s).length>0;if(e.forEach&&(i.rect||i.radius))return t.collideOneWithMany(i,e,s).length>0;if(e.rect&&i.rect||e.radius&&i.radius){var o=t.collideOneWithOne(e,i);if(!s||!o)return o;s(e,i)}},t}(jaws||{}),jaws=function(t){return t.PixelMap=function(e){return this instanceof arguments.callee?(this.options=e,this.scale=e.scale||1,this.x=e.x||0,this.y=e.y||0,e.image?(this.setContext(e.image),e.scale_image&&this.setContext(t.retroScaleImage(this.context.canvas,e.scale_image)),this.width=this.context.canvas.width*this.scale,this.height=this.context.canvas.height*this.scale):t.log.warn("PixelMap needs an image to work with"),this.named_colors=[],void this.update()):new arguments.callee(e)},t.PixelMap.prototype.setContext=function(e){var e=t.isDrawable(e)?e:t.assets.get(e);this.context=t.imageToCanvasContext(e)},t.PixelMap.prototype.update=function(t,e,i,s){if((void 0===t||0>t)&&(t=0),(void 0===e||0>e)&&(e=0),(void 0===i||i>this.width)&&(i=this.width),(void 0===s||s>this.height)&&(s=this.height),0==arguments.length)this.data=this.context.getImageData(t,e,i,s).data;else for(var o=this.context.getImageData(t,e,i,s).data,n=0,a=4*this.width,r=e*this.width*4+4*t,h=4*i,c=0;s>c;c++){for(var l=0;h>l;l++)this.data[r+l]=o[n++];r+=a}},t.PixelMap.prototype.draw=function(){t.context.drawImage(this.context.canvas,this.x,this.y,this.width,this.height)},t.PixelMap.prototype.namedColorAtRect=function(t,e){for(var i=t.x,s=t.y;it.x;i--)if(this.namedColorAt(i,s)==e||void 0===e)return this.namedColorAt(i,s);for(;s>t.y;s--)if(this.namedColorAt(i,s)==e||void 0===e)return this.namedColorAt(i,s);return!1},t.PixelMap.prototype.at=function(t,e){t=parseInt(t),e=parseInt(e),0>e&&(e=0);var i=e*this.width*4+4*t,s=this.data[i],o=this.data[i+1],n=this.data[i+2],a=this.data[i+3];return[s,o,n,a]},t.PixelMap.prototype.namedColorAt=function(t,e){for(var i=this.at(t,e),s=0;s=0&&t.y+t.height>=0&&t.draw(),t.x=t.x+t.width,this.repeat_x););if(t.y=t.y+t.height,t.x=e,!this.repeat_y)break}},t.Parallax.prototype.addLayer=function(e){var i=new t.ParallaxLayer(e);i.scaleAll(this.scale),this.layers.push(i)},t.Parallax.prototype.toString=function(){return"[Parallax "+this.x+", "+this.y+". "+this.layers.length+" layers]"},t.ParallaxLayer=function(e){return this instanceof arguments.callee?(this.damping=e.damping||0,void t.Sprite.call(this,e)):new arguments.callee(e)},t.ParallaxLayer.prototype=t.Sprite.prototype,t}(jaws||{}),jaws=function(jaws){return jaws.Text=function(t){return this instanceof arguments.callee?(this.set(t),t.context&&(this.context=t.context),void(t.context||jaws.context&&(this.context=jaws.context))):new arguments.callee(t)},jaws.Text.prototype.default_options={x:0,y:0,alpha:1,angle:0,anchor_x:0,anchor_y:0,anchor:"top_left",damping:1,style:"normal",fontFace:"serif",fontSize:12,color:"black",textAlign:"start",textBaseline:"alphabetic",text:"",wordWrap:!1,width:function(){return jaws.width},height:function(){return jaws.height},shadowColor:null,shadowBlur:null,shadowOffsetX:null,shadowOffsetY:null,_constructor:null},jaws.Text.prototype.set=function(t){return jaws.parseOptions(this,t,this.default_options),this.anchor&&this.setAnchor(this.anchor),this.cacheOffsets(),this},jaws.Text.prototype.clone=function(){var constructor=this._constructor?eval(this._constructor):this.constructor,new_sprite=new constructor(this.attributes());return new_sprite._constructor=this._constructor||this.constructor.name,new_sprite},jaws.Text.prototype.rotate=function(t){return this.angle+=t,this},jaws.Text.prototype.rotateTo=function(t){return this.angle=t,this},jaws.Text.prototype.moveTo=function(t,e){return this.x=t,this.y=e,this},jaws.Text.prototype.move=function(t,e){return t&&(this.x+=t),e&&(this.y+=e),this},jaws.Text.prototype.setX=function(t){return this.x=t,this},jaws.Text.prototype.setY=function(t){return this.y=t,this},jaws.Text.prototype.setTop=function(t){return this.y=t+this.top_offset,this},jaws.Text.prototype.setBottom=function(t){return this.y=t-this.bottom_offset,this},jaws.Text.prototype.setLeft=function(t){return this.x=t+this.left_offset,this},jaws.Text.prototype.setRight=function(t){return this.x=t-this.right_offset,this},jaws.Text.prototype.setWidth=function(t){return this.width=t,this.cacheOffsets(),this},jaws.Text.prototype.setHeight=function(t){return this.height=t,this.cacheOffsets(),this},jaws.Text.prototype.resize=function(t,e){return this.width+=t,this.height+=e,this.cacheOffsets(),this},jaws.Text.prototype.resizeTo=function(t,e){return this.width=t,this.height=e,this.cacheOffsets(),this},jaws.Text.prototype.setAnchor=function(t){var e={top_left:[0,0],left_top:[0,0],center_left:[0,.5],left_center:[0,.5],bottom_left:[0,1],left_bottom:[0,1],top_center:[.5,0],center_top:[.5,0],center_center:[.5,.5],center:[.5,.5],bottom_center:[.5,1],center_bottom:[.5,1],top_right:[1,0],right_top:[1,0],center_right:[1,.5],right_center:[1,.5],bottom_right:[1,1],right_bottom:[1,1]};return e.hasOwnProperty(t)&&(this.anchor_x=e[t][0],this.anchor_y=e[t][1],this.cacheOffsets()),this},jaws.Text.prototype.cacheOffsets=function(){return this.left_offset=this.width*this.anchor_x,this.top_offset=this.height*this.anchor_y,this.right_offset=this.width*(1-this.anchor_x),this.bottom_offset=this.height*(1-this.anchor_y),this.cached_rect&&this.cached_rect.resizeTo(this.width,this.height),this},jaws.Text.prototype.rect=function(){return!this.cached_rect&&this.width&&(this.cached_rect=new jaws.Rect(this.x,this.y,this.width,this.height)),this.cached_rect&&this.cached_rect.moveTo(this.x-this.left_offset,this.y-this.top_offset),this.cached_rect},jaws.Text.prototype.draw=function(){this.context.save(),0!==this.angle&&this.context.rotate(this.angle*Math.PI/180),this.context.globalAlpha=this.alpha,this.context.translate(-this.left_offset,-this.top_offset),this.context.fillStyle=this.color,this.context.font=this.style+" "+this.fontSize+"px "+this.fontFace,this.context.textBaseline=this.textBaseline,this.context.textAlign=this.textAlign,this.shadowColor&&(this.context.shadowColor=this.shadowColor),this.shadowBlur&&(this.context.shadowBlur=this.shadowBlur),this.shadowOffsetX&&(this.context.shadowOffsetX=this.shadowOffsetX),this.shadowOffsetY&&(this.context.shadowOffsetY=this.shadowOffsetY);var t=this.y,e=this.x;if(this.wordWrap)for(var i=this.text.split(" "),s="",o=0;othis.width?(this.context.fillText(s,this.x,this.y),s=i[o]+" ",this.y+=this.fontSize):s=n,this.context.fillText(s,this.x,this.y))}else if(this.context.measureText(this.text).widththis.width?(this.context.fillText(n,this.x,this.y),n=o[a]+" ",this.y+=this.fontSize):n=r,this.context.fillText(n,this.x,this.y))}else if(this.context.measureText(this.text).widththis.width?(e.fillText(n,this.x,this.y),n=o[a]+" ",this.y+=this.fontSize):n=r,e.fillText(n,this.x,this.y))}else if(e.measureText(this.text).widths;return t.xi&&(o?e=0:n&&(e=3)),e},t.QuadTree.prototype.insert=function(t){if(t.hasOwnProperty("x")||t.hasOwnProperty("y")||t.hasOwnProperty("width")||t.hasOwnProperty("height")){if("undefined"!=typeof this.nodes[0]){var e=this.getIndex(t);if(-1!==e)return void this.nodes[e].insert(t)}this.objects.push(t),"undefined"==typeof this.nodes[0]&&this.split();for(var i=0;i