-
Notifications
You must be signed in to change notification settings - Fork 1
/
Firmament.min.js
78 lines (75 loc) · 26.7 KB
/
Firmament.min.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/* Firmament HTML 5 Game Engine
Copyright (C) 2011 Jordan CM Wambaugh jordan@wambaugh.org http://firmament.wambaugh.org
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
any later version.
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 <http://www.gnu.org/licenses/>.
*/
var b2Vec2=Box2D.Common.Math.b2Vec2,b2BodyDef=Box2D.Dynamics.b2BodyDef,b2Body=Box2D.Dynamics.b2Body,b2FixtureDef=Box2D.Dynamics.b2FixtureDef,b2Fixture=Box2D.Dynamics.b2Fixture,b2World=Box2D.Dynamics.b2World,b2MassData=Box2D.Collision.Shapes.b2MassData,b2PolygonShape=Box2D.Collision.Shapes.b2PolygonShape,b2CircleShape=Box2D.Collision.Shapes.b2CircleShape,b2DebugDraw=Box2D.Dynamics.b2DebugDraw,Firmament={log:function(a,b){if(window.console&&(b!=true||this._logHistory.indexOf(a)==-1))this._logHistory.push(a),
window.console.log(a)},_logHistory:[],images:{},loadImage:function(a){var b=document.createElement("img");b.src=a;return this.images[a]=b},extend:function(){var a,b,c,d,f,e=arguments[0]||{},g=1,h=arguments.length,j=false;typeof e==="boolean"&&(j=e,e=arguments[1]||{},g=2);typeof e!=="object"&&!FHelper.isFunction(e)&&(e={});if(h===g)return e;for(;g<h;g++)if((a=arguments[g])!=null)for(b in a)c=e[b],d=a[b],e!==d&&(j&&d&&(Firmament.isPlainObject(d)||(f=Firmament.isArray(d)))?(f?(f=false,c=c&&Firmament.isArray(c)?
c:[]):c=c&&Firmament.isPlainObject(c)?c:{},e[b]=Firmament.FHelper.extend(j,c,d)):d!==void 0&&(e[b]=d));return e},isArray:function(a){return toString.call(a)=="[object Array]"?true:false},isPlainObject:function(a){if(!a)return false;if(a.constructor&&!hasOwn.call(a,"constructor")&&!hasOwn.call(a.constructor.prototype,"isPrototypeOf"))return false;for(var b in a);return b===void 0||hasOwn.call(a,b)},isFunction:function(a){return typeof a=="function"?true:false},isMobileSafari:function(){return navigator.userAgent.match(/(iPod|iPhone|iPad)/)},
getSoundManager:function(){if(this.soundManager==void 0)this.soundManager=new FSoundManager;return this.soundManager},loadSound:function(a,b){this.log(_BrowserDetect.browser);_BrowserDetect.browser=="Firefox"&&(a=a.replace(".mp3",".ogg"));return this.getSoundManager().loadSound(a,b)},getElementOffset:function(a){for(var b=0,c=0;a&&!isNaN(a.offsetLeft)&&!isNaN(a.offsetTop);)b+=a.offsetLeft,c+=a.offsetTop,a=a.offsetParent;return{y:c,x:b}}};
if(!Function.prototype.bind)Function.prototype.bind=function(a){if(typeof this!=="function")throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var b=[].slice,c=b.call(arguments,1),d=this,f=function(){},e=function(){return d.apply(this instanceof f?this:a||{},c.concat(b.call(arguments)))};e.prototype=this.prototype;return e};
if(!Object.create)Object.create=function(a){function b(){}if(arguments.length>1)throw Error("Object.create implementation only accepts the first parameter.");b.prototype=a;return new b};
var _BrowserDetect={init:function(){this.browser=this.searchString(this.dataBrowser)||"An unknown browser";this.version=this.searchVersion(navigator.userAgent)||this.searchVersion(navigator.appVersion)||"an unknown version";this.OS=this.searchString(this.dataOS)||"an unknown OS"},searchString:function(a){for(var b=0;b<a.length;b++){var c=a[b].string,d=a[b].prop;this.versionSearchString=a[b].versionSearch||a[b].identity;if(c){if(c.indexOf(a[b].subString)!=-1)return a[b].identity}else if(d)return a[b].identity}},
searchVersion:function(a){var b=a.indexOf(this.versionSearchString);return b==-1?void 0:parseFloat(a.substring(b+this.versionSearchString.length+1))},dataBrowser:[{string:navigator.userAgent,subString:"Chrome",identity:"Chrome"},{string:navigator.userAgent,subString:"OmniWeb",versionSearch:"OmniWeb/",identity:"OmniWeb"},{string:navigator.vendor,subString:"Apple",identity:"Safari",versionSearch:"Version"},{prop:window.opera,identity:"Opera",versionSearch:"Version"},{string:navigator.vendor,subString:"iCab",
identity:"iCab"},{string:navigator.vendor,subString:"KDE",identity:"Konqueror"},{string:navigator.userAgent,subString:"Firefox",identity:"Firefox"},{string:navigator.vendor,subString:"Camino",identity:"Camino"},{string:navigator.userAgent,subString:"Netscape",identity:"Netscape"},{string:navigator.userAgent,subString:"MSIE",identity:"Explorer",versionSearch:"MSIE"},{string:navigator.userAgent,subString:"Gecko",identity:"Mozilla",versionSearch:"rv"},{string:navigator.userAgent,subString:"Mozilla",
identity:"Netscape",versionSearch:"Mozilla"}],dataOS:[{string:navigator.platform,subString:"Win",identity:"Windows"},{string:navigator.platform,subString:"Mac",identity:"Mac"},{string:navigator.userAgent,subString:"iPhone",identity:"iPhone/iPod"},{string:navigator.platform,subString:"Linux",identity:"Linux"}]};_BrowserDetect.init();function FObservable(){}
FObservable.prototype.connect=function(a,b,c){if(this._connections==void 0)this._connections={};this._connections[a]==void 0&&(this._connections[a]=[]);c==void 0&&(c=this);this._connections[a].push({func:b,scope:c})};FObservable.prototype.disconnect=function(a,b){if(this._connections==void 0)this._connections={};if(b!=void 0){var c=this._connections[a];if(c!=void 0)for(var d=0;d<c.length;d++)c[d]==b&&c.splice(d,1)}else a!=void 0?this._connections[a]=[]:this._connections={}};
FObservable.prototype.emit=function(a,b){if(this._connections==void 0)this._connections={};var c=this._connections[a];b==void 0&&(b=[]);if(c!=void 0)for(var d=0;d<c.length;d++)c[d].func.apply(c[d].scope,b)};function FResourcePool(a){this.constructorFunc=a;this.availablePool=[];this.totalPool=[]}FResourcePool.prototype.get=function(){var a;this.availablePool.length>0?a=this.availablePool.pop():(a=new this.constructorFunc,this.totalPool.push(a));return a};FResourcePool.prototype.addBack=function(a){this.availablePool.push(a)};
function FVector(a,b){a==void 0&&(a=0);b==void 0&&(b=0);if(isNaN(a))throw"x IS NAN!!!!!!";this.x=a;this.y=b}FVector.prototype=new Box2D.Common.Math.b2Vec2;FWorldPositional.prototype=new FObservable;FWorldPositional.prototype.constuctor=FWorldPositional;FWorldPositional.prototype.parent=FObservable.prototype;function FWorldPositional(){this.position=new FVector(0,0);this.positionBase="w";this.angle=0}FWorldPositional.prototype.setPosition=function(a){this.position=a};
FWorldPositional.prototype.getPosition=function(){return this.position};FWorldPositional.prototype.getPositionX=function(){return this.getPosition().x};FWorldPositional.prototype.getPositionY=function(){return this.getPosition().y};FWorldPositional.prototype.getAngle=function(){return 0};FWorldPositional.prototype.setAngle=function(){};FRenderable.prototype=new FWorldPositional;FRenderable.prototype.constructor=FRenderable;
function FRenderable(){this.renderer=null;this.imageScale=100;this.zPosition=0;this.color="#000000"}FRenderable.prototype.getRelativeCameraPosition=function(){if(this.positionBase=="c")return this.position};FRenderable.prototype.getImageScale=function(){return this.imageScale};FRenderable.prototype.getShapes=function(){return[]};FRenderable.prototype.setRenderer=function(a){this.renderer=a};FRenderable.prototype.getRenderer=function(){return this.renderer};FRenderable.prototype.getCurrentImage=function(){return null};
FRenderable.prototype.getZPosition=function(){return this.zPosition};FRenderable.prototype.setZPosition=function(a){this.zPosition=a};FRenderable.prototype.setColor=function(a){this.color=a};FRenderable.prototype.getColor=function(){return this.color};FPhysicsEntity.prototype=new FRenderable;FPhysicsEntity.prototype.constructor=FPhysicsEntity;
function FPhysicsEntity(a,b){this.world=a;this.config=b;var c=new b2BodyDef,d=0;b.position?(c.position.x=b.position.x,c.position.y=b.position.y):(c.position.x=0,c.position.y=0);if(b.positionX!=void 0)c.position.x=b.positionX;if(b.positionY!=void 0)c.position.y=b.positionY;c.type=b.type=="static"?b2Body.b2_staticBody:Box2D.Dynamics.b2Body.b2_dynamicBody;if(b.angle)c.angle=b.angle;c.userData=this;this.body=this.world.b2world.CreateBody(c);for(c=0;c<b.shapes.length;c++){var f=new b2FixtureDef,e=b.shapes[c];
if(e.type=="box")e.width=e.width!=void 0?e.width:1,e.height=e.height!=void 0?e.height:1,f.shape=new b2PolygonShape,f.shape.SetAsBox(e.width/2,e.height/2),d=e.width;else if(e.type=="circle")d=e.radius*2,f.shape=new b2CircleShape(e.radius);f.density=e.density!=void 0?e.density:1;f.friction=e.friction!=void 0?e.friction:1;f.restitution=e.restitution!=void 0?e.restitution:0;this.body.CreateFixture(f)}this.body.ResetMassData();this.zPosition=0;b.maxLifeSeconds&&setTimeout(function(){this.destroy()}.bind(this),
b.maxLifeSeconds*1E3);b.color&&this.setColor(b.color);if(b.image){if(typeof b.image=="string")c=document.createElement("img"),c.src=b.image,b.image=c;this.currentImage=b.image;this.setRenderer(new FSpriteRenderer);if(b.imageScale)b.imageScale=="auto"?b.imageWidth?this.imageScale=b.imageWidth/d:(Firmament.log("Image width must be set for auto scale! Defaulting to 1:1"),this.imageScale=100):this.imageScale=b.imageScale}else this.setRenderer(new FWireframeRenderer)}
FPhysicsEntity.prototype.getShapes=function(){for(var a=[],b=this.body.GetFixtureList();b;)a.push(b.GetShape()),b=b.GetNext();return a};FPhysicsEntity.prototype.getPosition=function(){return this.body.GetPosition()};FPhysicsEntity.prototype.getAngle=function(){return this.body.GetAngle()};FPhysicsEntity.prototype.getCurrentImage=function(){return this.currentImage};FPhysicsEntity.prototype.setVelocity=function(a){this.body.SetLinearVelocity(a)};
FPhysicsEntity.prototype.destroy=function(){this.world.b2world.DestroyBody(this.body);this.world.destroyEntity(this)};FPhysicsEntity.prototype.deleteLater=FPhysicsEntity.prototype.destroy;function FWorld(){}FWorld.prototype={entities:[]};FWorld.prototype.step=function(){};FWorld.prototype.addEntity=function(a){this.entities.push(a)};FWorld.prototype.destroyEntity=function(a){this.entities.splice(this.entities.indexOf(a),1)};FWorld.prototype.getAllEntities=function(){return this.entities};
FPhysicsWorld.prototype.getEntitiesInBox=function(){Firmament.log("getEntitiesInBox Not Implemented!")};function FPhysicsWorld(a){this.collisions=[];this.b2world=new b2World(new b2Vec2(a.x,a.y),true);this.b2world.SetContactListener({BeginContact:function(a){this.collisions.push(a)}.bind(this),EndContact:function(){},PreSolve:function(){},PostSolve:function(){}})}FPhysicsWorld.prototype=new FWorld;
FPhysicsWorld.prototype.step=function(a){this.collisions=[];this.b2world.Step(1/a,10,10);for(a=0;a<this.collisions.length;a++){var b=this.collisions[a],c=b.m_fixtureA.m_body.m_userData,d=b.m_fixtureB.m_body.m_userData;c.emit("collide",[d,b]);d.emit("collide",[c,b])}this.b2world.ClearForces()};FPhysicsWorld.prototype.setGravity=function(a){this.b2world.SetGravity(a)};FPhysicsWorld.prototype.createEntity=function(a){var b=new FPhysicsEntity(this,a);this.addEntity(b);a.init&&a.init.apply(b,[]);return b};
FPhysicsWorld.prototype.getEntitiesInBox=function(a,b,c,d){var f=[],e=new Box2D.Collision.b2AABB;e.upperBound.Set(c,d);e.lowerBound.Set(a,b);this.b2world.QueryAABB(function(a){f.push(a.GetBody().GetUserData());return true},e);return f};function FRenderer(){}FRenderer.prototype.render=function(){};function FWireframeRenderer(){}FWireframeRenderer.prototype=new FRenderer;
FWireframeRenderer.prototype.render=function(a,b,c){var d=b.getShapes();a.fillStyle=b.getColor();a.strokeStyle=b.getColor();for(var f=b.getAngle(),e=0;e<d.length;e++){var g=d[e],h=b.getPosition();g.m_vertices?this.renderPolygon(a,g,h,f):this.renderCircle(a,g,h,c)}};FWireframeRenderer.prototype.renderCircle=function(a,b,c,d){var f=d.getTopLeftPosition();a.beginPath();a.arc((c.x-f.x)*d.getZoom(),(c.y-f.y)*d.getZoom(),b.m_radius*d.getZoom(),0,Math.PI*2,true);a.closePath();a.fill()};
FWireframeRenderer.prototype.renderPolygon=function(a,b,c){a.beginPath();for(var b=b.GetVertices(),d=0;d<b.length;d++){a.moveTo((b[d].x+c.x)*100,(b[d].y+c.y)*100);var f=d+1;f>=b.length&&(f=0);a.lineTo((b[f].x+c.x)*100,(b[f].y+c.y)*100)}a.closePath();a.stroke()};function FSpriteRenderer(){}FSpriteRenderer.prototype=new FRenderer;
FSpriteRenderer.prototype.render=function(a,b,c){var d=c.getTopLeftPosition(),f=b.getPosition(),e=b.getAngle(),g=b.getCurrentImage(),b=c.getZoom()/b.getImageScale();a.save();var h=(f.x-d.x)*c.getZoom(),d=(f.y-d.y)*c.getZoom();a.translate(h,d);b!=1&&a.scale(b,b);c.getZoom();e!=0&&a.rotate(e);a.drawImage(g,0-g.width/2,0-g.height/2);a.restore()};
function FGame(){window.setInterval(this._frameCount.bind(this),1E3);this.fpsGoal=30;this.instep=this.frames=0;this.cameras=[];this.worlds=[];this.fps=0;this.stepInterval=null}FGame.prototype=new FObservable;FGame.prototype.startSimulation=function(){this.stepInterval=window.setInterval(this._step.bind(this),1E3/this.fpsGoal)};FGame.prototype.stopSimulation=function(){window.clearInterval(this.stepInterval)};FGame.prototype.addCamera=function(a){a.setGame(this);this.cameras.push(a)};
FGame.prototype.addCanvas=function(a){a=new FCamera(a);this.addCamera(a);return a};FGame.prototype.addWorld=function(a){this.worlds.push(a)};FGame.prototype._step=function(){if(!this.instep){this.instep=true;this.emit("beginStep");for(var a=0;a<this.worlds.length;a++)this.worlds[a].step(this.fpsGoal);this.emit("endStep");this.emit("endRender");for(a=0;a<this.cameras.length;a++)this.cameras[a].render(this.worlds);this.emit("endRender");this.frames++;this.instep=false}};
FGame.prototype._frameCount=function(){this.fps=this.frames;this.emit("fpsUpdate",[this.fps]);this.frames=0};function FCamera(a){this.canvas=a;if(!Firmament.isMobileSafari())window.onresize=this.canvasResized.bind(this);this.game=null;this.zoom=100;this.topLeftPosition=new FVector;this.setPosition(new FVector(0,0));this.canvasResized()}FCamera.prototype=new FWorldPositional;
FCamera.prototype.render=function(a){var b=this.getCanvas().getContext("2d");b.clearRect(0,0,this.width,this.height);this.emit("beginRender",[b]);for(var c=[],d=0;d<a.length;d++)var f=a[d].getEntitiesInBox(this.position.x-this.width/2/this.zoom,this.position.y-this.height/2/this.zoom,this.position.x+this.width/2/this.zoom,this.position.y+this.height/2/this.zoom),c=c.concat(f);c.sort(function(a,b){return a.getZPosition()-b.getZPosition()});for(a=0;a<c.length;a++)d=c[a],d.getRenderer().render(b,d,this);
this.emit("endRender",[b])};FCamera.prototype.getCanvas=function(){return this.canvas};FCamera.prototype.setGame=function(a){this.game=a};FCamera.prototype.setWidth=function(a){this.width=a;this.calculateTopLeftPosition()};FCamera.prototype.getWidth=function(){return this.width};FCamera.prototype.setHeight=function(a){this.height=a;this.calculateTopLeftPosition()};FCamera.prototype.getHeight=function(){return this.height};FCamera.prototype.getZoom=function(){return this.zoom};
FCamera.prototype.setZoom=function(a){this.zoom=a;this.calculateTopLeftPosition()};FCamera.prototype.setPosition=function(a){this.position=a;this.calculateTopLeftPosition()};FCamera.prototype.getTopLeftPosition=function(){return this.topLeftPosition};FCamera.prototype.calculateTopLeftPosition=function(){this.topLeftPosition.x=this.position.x-this.width/this.zoom/2;this.topLeftPosition.y=this.position.y-this.height/this.zoom/2};
FCamera.prototype.canvasResized=function(){this.width=this.canvas.clientWidth;this.height=this.canvas.clientHeight;this.canvas.width=this.width;this.canvas.height=this.height;this.calculateTopLeftPosition()};
function FInput(a){a==void 0&&(a=document);this.listenElement=a;this.keysPressed={};a.onkeyup=this._keyup.bind(this);a.onkeydown=this._keydown.bind(this);a.ontouchstart=this._mouseDown.bind(this);a.ontouchend=this._mouseUp.bind(this);a.ontouchmove=this._mouseMove.bind(this);a.onmousedown=this._mouseDown.bind(this);a.onmouseup=this._mouseUp.bind(this);a.onmousemove=this._mouseMove.bind(this);a.selectstart=function(){return false};this.mouseY=this.mouseX=0;this.rightMouseDown=this.leftMouseDown=false}
FInput.prototype=new FObservable;FInput.prototype._mouseDown=function(a){this._updateMousePos(a);this.leftMouseDown=true;this.emit("mouseDown",[a])};FInput.prototype._mouseUp=function(a){this.leftMouseDown=false;this._updateMousePos(a);this.emit("mouseUp",[a])};FInput.prototype._mouseMove=function(a){this._updateMousePos(a);this.leftMouseDown&&this.emit("mouseDrag",[a]);this.emit("mouseMove",[a])};FInput.prototype.getMouseScreenPos=function(){return new FVector(this.mouseX,this.mouseY)};
FInput.prototype.getMouseWorldPos=function(a){var b=Firmament.getElementOffset(a.getCanvas()),c=this.mouseX-b.x,b=this.mouseY-b.y,b=a.getTopLeftPosition(),a=a.getZoom(),c=this.mouseX/a+b.x,b=this.mouseY/a+b.y;return new FVector(c,b)};FInput.prototype._updateMousePos=function(a){if(a.x!==void 0)this.mouseX=a.x,this.mouseY=a.y;else if(a.clientX!==void 0)this.mouseX=a.clientX,this.mouseY=a.clientY;else if(a.pageX!==void 0)this.mouseX=a.pageX,this.mouseY=a.pageY};
FInput.prototype._keyup=function(a){var b=this._getKeyCode(a);this.keysPressed[b]=false;this.emit("keyUp",[b,a])};FInput.prototype._keydown=function(a){var b=this._getKeyCode(a);this.keysPressed[b]=true;this.emit("keyDown",[b,a])};FInput.prototype._getKeyCode=function(a){var b;if(window.event)b=a.keyCode;else if(a.which)b=a.which;return b};FInput.prototype.isKeyPressed=function(a){return this.keysPressed[a]?true:false};FInput.prototype.isMousePressed=function(a){switch(a){case "left":return this.leftMouseDown}};
var FTriangulator={EPSILON:1.0E-10,area:function(a){for(var b=a.length,c=0,d=b-1,f=0;f<b;d=f++)c+=a[d].x*a[f].y-a[f].x*a[d].y;return c*0.5},insideTriangle:function(a,b,c,d,f,e,g,h){return(f-c)*(h-d)-(e-d)*(g-c)>=0&&(a-f)*(h-e)-(b-e)*(g-f)>=0&&(c-a)*(h-b)-(d-b)*(g-a)>=0},snip:function(a,b,c,d,f,e){var g,h,j,k,l,m,n,o,p;h=a[e[b]].x;j=a[e[b]].y;k=a[e[c]].x;l=a[e[c]].y;m=a[e[d]].x;n=a[e[d]].y;if(this.EPSILON>(k-h)*(n-j)-(l-j)*(m-h))return false;for(g=0;g<f;g++)if(!(g==b||g==c||g==d))if(o=a[e[g]].x,p=
a[e[g]].y,this.insideTriangle(h,j,k,l,m,n,o,p))return false;return true},process:function(a,b){var c=a.length;if(c<3)return false;var d=[];if(0<this.area(a))for(var f=0;f<c;f++)d[f]=f;else for(f=0;f<c;f++)d[f]=c-1-f;for(var e=2*c,g=0,f=c-1;c>2;){if(0>=e--)return false;var h=f;c<=h&&(h=0);f=h+1;c<=f&&(f=0);var j=f+1;c<=j&&(j=0);if(this.snip(a,h,f,j,c,d)){e=d[h];h=d[f];j=d[j];b.push(a[e]);b.push(a[h]);b.push(a[j]);g++;for(j=f,e=f+1;e<c;j++,e++)d[j]=d[e];c--;e=2*c}}return true},getTriangles:function(a){var b=
[],c=[];if(!this.process(a,b))return false;for(var a=b.length/3,d=0;d<a;d++)c.push([b[d*3],b[d*3+1],b[d*3+2]]);return c}};function FSound(a,b){this.fileName=a;this.duration=b}FSound.prototype=new FObservable;FSound.prototype.play=function(){return Firmament.getSoundManager().play(this)};function FSoundPlayer(a){a!=void 0?(this.audioObj=new Audio(a.fileName),this.setSound(a)):this.audioObj=new Audio}FSoundPlayer.prototype=new FObservable;
FSoundPlayer.prototype.setSound=function(a){this.soundObj=a;this.audioObj.src=a.fileName;this.audioObj.load()};FSoundPlayer.prototype.play=function(){this.audioObj.play();var a=5;if((!this.audioObj.duration||isNaN(this.audioObj.duration))&&this.soundObj.duration!=void 0)a=this.soundObj.duration;setTimeout(function(){this.emit("canCleanUp",[this])}.bind(this),(a+1)*1E3)};function FSoundManager(){this.cache={};this.playerPool=new FResourcePool(FSoundPlayer)}FSoundManager.prototype=new FObservable;
FSoundManager.prototype.loadSound=function(a,b){this.cache[a]={};this.cache[a].sound=new FSound(a,b);this.cache[a].player=new FSoundPlayer(this.cache[a].sound);return this.cache[a].sound};FSoundManager.prototype.getSoundPlayer=function(a){var b=this.playerPool.get();b.disconnect();b.setSound(a);b.connect("canCleanUp",function(a){this.playerPool.addBack(a)}.bind(this));return b};FSoundManager.prototype.play=function(a){a=this.getSoundPlayer(a);a.play();return a};
var FHelper={centerCameraOnEntity:function(a){fgame.getMainCamera().setPosition({x:a.getPositionX(),y:a.getPositionY()})},shootBulletFromEntityToMouse:function(a,b,c,d,f){a=a.getMouseWorldPos(b);d=d.getPosition();a=Math.atan2(a.y-d.y,a.x-d.x);f.positionX=d.x+Math.cos(a)*1.1;f.positionY=d.y+Math.sin(a)*1.1;c.createEntity(f).setVelocity({x:Math.cos(a)*10,y:Math.sin(a)*10})},moveEntityAtAngle:function(a,b,c){a.setVelocity(a.getVelocityX()+Math.cos(b)*c,a.getVelocityY()+Math.sin(b)*c)},pointEntityTowardsPoint:function(a,
b,c){b-=a.getPositionX();c-=a.getPositionY();c=Math.atan2(c,b);a.setAngle(c)}};FHelper.pointEntityTowardsMouse=function(a){FHelper.pointEntityTowardsPoint(a,this.getMouseWorldX(),this.getMouseWorldY())};FHelper.getMouseWorldX=function(){var a=fgame.getMainCamera();return fgame.getMouseX()/a.getZoom()+(a.getPositionX()-a.getWidth()/a.getZoom()/2)};FHelper.getMouseWorldY=function(){var a=fgame.getMainCamera();return fgame.getMouseY()/a.getZoom()+(a.getPositionY()-a.getHeight()/a.getZoom()/2)};
FHelper.shootBulletFromEntity=function(a,b){b.positionX=a.getPositionX()+Math.cos(a.getAngle())*1.1;b.positionY=a.getPositionY()+Math.sin(a.getAngle())*1.1;fgame.createEntity(b).setVelocity({x:Math.cos(a.getAngle())*10,y:Math.sin(a.getAngle())*10})};
FHelper.getImageScale=function(a){if(typeof a!="object")throw"Param is not an object";if(a.imageWidth&&a.entityWidth)return a.imageWidth/a.entityWidth;else if(a.imageWidth&&a.entityRadius)return a.imageWidth/(a.entityRadius*2);else throw"required parameters imageWidth and either entityRadius or entityWidth missing.";};
FHelper.css=function(a){if(typeof a!="object")return"";var b="";for(key in a){for(var c=key,d=/[A-Z]/.exec(c);d&&typeof d[0]!="undefined";)c=c.split(d[0]).join("-"+d[0].toLowerCase()),d=/[A-Z]/.exec(c);b+=c+":";b+=a[key]+";"}return b};FHelper.debug=function(a,b){b||(b=0);var c="";for(i in a){c+="\n";for(var d=0;d<b;d++)c+=" ";c=typeof a[i]=="object"?c+i+"->"+FHelper.debug(a[i],b+5):c+i+"->"+a[i]}return c};
FHelper.extend=function(){var a,b,c,d,f,e=arguments[0]||{},g=1,h=arguments.length,j=false;typeof e==="boolean"&&(j=e,e=arguments[1]||{},g=2);typeof e!=="object"&&!FHelper.isFunction(e)&&(e={});if(h===g)return e;for(;g<h;g++)if((a=arguments[g])!=null)for(b in a)c=e[b],d=a[b],e!==d&&(j&&d&&(FHelper.isPlainObject(d)||(f=FHelper.isArray(d)))?(f?(f=false,c=c&&FHelper.isArray(c)?c:[]):c=c&&FHelper.isPlainObject(c)?c:{},e[b]=FHelper.extend(j,c,d)):d!==void 0&&(e[b]=d));return e};
FHelper.isArray=function(a){return toString.call(a)=="[object Array]"?true:false};FHelper.isPlainObject=function(a){if(!a)return false;if(a.constructor&&!hasOwn.call(a,"constructor")&&!hasOwn.call(a.constructor.prototype,"isPrototypeOf"))return false;for(var b in a);return b===void 0||hasOwn.call(a,b)};FHelper.isFunction=function(a){return typeof a=="function"?true:false};FHelper.dec2hex=function(a){return a.toString(16)};FHelper.getGlobalObject=function(){return function(){return this}.call(null)};
FHelper.pi=3.14159265358979;FHelper.oneEightyDevPi=180/FHelper.pi;FHelper.piDevOneEighty=FHelper.pi/180;FHelper.rad2Deg=function(a){return a*this.pi180};FHelper.deg2Rad=function(a){return this.piDevOneEighty*a};FHelper.polyShape=function(a,b){shapes=FGame.triangulateShape(a);var c=[];for(x=0;x<shapes.length;x++)c[x]=FHelper.extend({},b,{type:"polygon",vectors:shapes[x]});return c};
FHelper.breakEntity=function(a,b){for(var c=0;c<a.shapes.length;c++){var d=a.shapes[c];d.type=="polygon"&&FGame.createEntity(FHelper.extend({},b,{positionX:a.getPositionX(),positionY:a.getPositionY(),angle:a.getAngle(),shapes:FHelper.polyShape(d.vectors,{})}))}a.deleteLater()};
FHelper.explodeEntity=function(a,b,c){for(var d=0;d<a.shapes.length;d++){var f=a.shapes[d];if(f.type=="polygon"){for(var f=f.vectors,e=0;e<c;e++)f=FGame.subdivideShape(f);f=FGame.triangulateShape(f);for(e=0;e<f.length;e++)FGame.createEntity(FHelper.extend({},b,{positionX:a.getPositionX(),positionY:a.getPositionY(),angle:a.getAngle(),shapes:FHelper.polyShape(f[e],{})}))}}a.deleteLater()};FHelper.vectorDistance=function(a,b){return Math.sqrt(Math.pow(b.x-a.x,2)+Math.pow(b.y-a.y,2))};
FHelper.includeDirectory=function(a,b){b||(b="*.js");for(var c=FGame.getDirectoryContents(a,b),d=0;d<c.length;d++)include(a+"/"+c[d])};FHelper.isInt=function(a){var b=parseInt(a);return isNaN(b)?false:a==b&&a.toString()==b.toString()};
FHelper.keyboard={keyNames:{8:"backspace",9:"tab",13:"enter",16:"shift",17:"ctrl",18:"alt",19:"pause",20:"caps-lock",27:"esc",32:"space",33:"pg-up",34:"pg-down",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",16777222:"insert",16777223:"delete",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",61:"equals",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",93:"context",96:"num-0",97:"num-1",98:"num-2",99:"num-3",100:"num-4",101:"num-5",102:"num-6",103:"num-7",104:"num-8",105:"num-9",106:"num-multiply",107:"num-plus",109:"num-minus",110:"num-period",111:"num-division",112:"f1",113:"f2",114:"f3",115:"f4",116:"f5",117:"f6",118:"f7",119:"f8",120:"f9",121:"f10",122:"f11",123:"f12",187:"equals",188:",",190:".",191:"/",220:"\\",224:"win"}};
FHelper.findEntities=function(a,b){for(var c=fg.getAllEntities(),d=[],f=0;f<c.length;f++)c[f][a]==b&&d.push(c[f]);return d};FHelper.getKeyCode=function(a){if(!FHelper.keyboard.keyMap){var b={},c;for(c in FHelper.keyboard.keyNames)b[FHelper.keyboard.keyNames[c]]=c;FHelper.keyboard.keyMap=b}return FHelper.keyboard.keyMap[a]};FHelper.isKeyPressed=function(a){return FGame.isKeyPressed({key:FHelper.getKeyCode(a)})};String.prototype.trim=function(){return this.replace(/^\s+|\s+$/,"")};
String.prototype.replaceAll=function(a,b){for(var c="",d=this.toString();;)if(c=d.replace(a,b),c==d)break;else d=c;return c};
var FEntityRepo={elements:{},addEntityType:function(a,b){for(var c=[],d=0;d<b.shapes.length;d++){var f=b.shapes[d];if(f.type=="polygon"){var e=FTriangulator.getTriangles(f.vectors);if(e!==false)for(var g=0;g<e.length;g++){var h=this.clone(f);h.vectors=e[g];h.type="triangle";c.push(h)}}else c.push(f)}b.shapes=c;this.elements[a]=b},getEntityType:function(a){var b=this.clone(this.elements[a]);b._entityTypeName=a;return b},createEntity:function(a){return FGame.createEntity(this.getEntityType(a))},clone:function(a){return new function(a){for(var c in a)this[c]=
a[c]}(a)}};
function FStateMachine(a){this.states=a;this.currentStateId=this.currentState=null;this.setState=function(a){if(a!=this.currentStateId)if(this.currentState!=null&&typeof this.stopState=="function"&&this.currentState.stopState.call(this),this.states[a])this.currentState=this.states[a],this.currentStateId=a,typeof this.currentState.initState=="function"&&this.currentState.initState.call(this);else throw"State of type "+a+" Is not a valid state object";};this.getState=function(){return this.currentState};this.callState=
function(a,c){this.currentState[a].apply(this,c)}};