From d1e2bc7e4f11fd932db18041e73d68feac6e0947 Mon Sep 17 00:00:00 2001 From: ippa Date: Fri, 21 Jun 2013 00:24:33 +0200 Subject: [PATCH] build --- jaws-min.js | 52 +-- jaws.js | 885 ++++++++++++++++++++++++++-------------------------- 2 files changed, 474 insertions(+), 463 deletions(-) diff --git a/jaws-min.js b/jaws-min.js index 1e003b0..a7fb245 100644 --- a/jaws-min.js +++ b/jaws-min.js @@ -1,4 +1,4 @@ -/* Built at 2013-06-09 18:54:12 +0200 */ +/* Built at 2013-06-21 00:23:18 +0200 */ var jaws=function(c){function b(b){c.mouse_x=b.pageX||b.clientX;c.mouse_y=b.pageY||b.clientY;b=c.canvas?c.canvas:c.dom;c.mouse_x-=b.offsetLeft;c.mouse_y-=b.offsetTop}var d,e;c.title=function(b){return b?d.innerHTML=b:d.innerHTML};c.unpack=function(){"Sprite SpriteList Animation Viewport SpriteSheet Parallax TileMap Rect pressed".split(" ").forEach(function(b){window[b]?c.log(b+"already exists in global namespace"):window[b]=c[b]})};c.log=function(b,c){e&&(b+="
",e.innerHTML=c?e.innerHTML.toString()+ b:b)};c.init=function(f){d=document.getElementsByTagName("title")[0];c.url_parameters=c.getUrlParameters();e=document.getElementById("jaws-log");c.url_parameters.debug&&!e&&(e=document.createElement("div"),e.id="jaws-log",e.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(e));c.canvas=document.getElementsByTagName("canvas")[0]; c.canvas||(c.dom=document.getElementById("canvas"));c.canvas?c.context=c.canvas.getContext("2d"):c.dom?c.dom.style.position="relative":(c.canvas=document.createElement("canvas"),c.canvas.width=f.width,c.canvas.height=f.height,c.context=c.canvas.getContext("2d"),document.body.appendChild(c.canvas));c.context&&c.useCrispScaling();c.width=c.canvas?c.canvas.width:c.dom.offsetWidth;c.height=c.canvas?c.canvas.height:c.dom.offsetHeight;c.mouse_x=0;c.mouse_y=0;window.addEventListener("mousemove",b)};c.useCrispScaling= @@ -7,28 +7,28 @@ d||(d={});var p=d.fps||60;void 0===d.loading_screen&&(d.loading_screen=!0);d.wid c.game_state;c.game_state=b;c.game_loop=new c.GameLoop(b,{fps:d},e);c.game_loop.start()};c.imageToCanvas=function(b){var c=document.createElement("canvas");c.src=b.src;c.width=b.width;c.height=b.height;c.getContext("2d").drawImage(b,0,0,b.width,b.height);return c};c.forceArray=function(b){return Array.isArray(b)?b:[b]};c.clear=function(){c.context.clearRect(0,0,c.width,c.height)};c.isImage=function(b){return"[object HTMLImageElement]"===Object.prototype.toString.call(b)};c.isCanvas=function(b){return"[object HTMLCanvasElement]"=== Object.prototype.toString.call(b)};c.isDrawable=function(b){return c.isImage(b)||c.isCanvas(b)};c.isString=function(b){return"string"==typeof b};c.isArray=function(b){return void 0===b?!1:-1!=b.constructor.toString().indexOf("Array")};c.isFunction=function(b){return"[object Function]"===Object.prototype.toString.call(b)};c.isOutsideCanvas=function(b){return 0>b.x||0>b.y||b.x>c.width||b.y>c.height};c.forceInsideCanvas=function(b){0>b.x&&(b.x=0);b.x>c.width&&(b.x=c.width);0>b.y&&(b.y=0);b.y>c.height&& (b.y=c.height)};c.getUrlParameters=function(){for(var b=[],c,d=window.location.href.slice(window.location.href.indexOf("?")+1).split("&"),e=0;ethis.size){this.values.splice(0,1);for(var c=this.value=0;this.values[c];c++)this.value+=this.values[c];this.value/=this.size}this.values.push(b);return this};this.get=function(){return parseInt(this.value)}}window.requestAnimFrame=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame|| -function(b){window.setTimeout(b,16.666)};c.GameLoop=function(d,e,f){if(!(this instanceof arguments.callee))return new arguments.callee(d,e);this.ticks=this.fps=this.tick_duration=0;var k,l=!1,h=!1,j=this,r=new b(20);this.runtime=function(){return this.last_tick-this.first_tick};this.start=function(){c.log("game loop start",!0);this.first_tick=(new Date).getTime();this.current_tick=(new Date).getTime();this.last_tick=(new Date).getTime();d.setup&&d.setup(f);step_delay=1E3/e.fps;60==e.fps?requestAnimFrame(this.loop): -k=setInterval(this.loop,step_delay);c.log("game loop loop",!0)};this.loop=function(){j.current_tick=(new Date).getTime();j.tick_duration=j.current_tick-j.last_tick;j.fps=r.add(1E3/j.tick_duration).get();!h&&!l&&(d.update&&d.update(),d.draw&&d.draw(),j.ticks++);60==e.fps&&!h&&requestAnimFrame(j.loop);j.last_tick=j.current_tick};this.pause=function(){l=!0};this.unpause=function(){l=!1};this.stop=function(){k&&clearInterval(k);h=!0}};return c}(jaws||{}),jaws=function(c){c.Rect=function(b,c,e,f){if(!(this instanceof -arguments.callee))return new arguments.callee(b,c,e,f);this.x=b;this.y=c;this.width=e;this.height=f;this.right=b+e;this.bottom=c+f};c.Rect.prototype.getPosition=function(){return[this.x,this.y]};c.Rect.prototype.move=function(b,c){this.x+=b;this.y+=c;this.right+=b;this.bottom+=c;return this};c.Rect.prototype.moveTo=function(b,c){this.x=b;this.y=c;this.right=this.x+this.width;this.bottom=this.y+this.height;return this};c.Rect.prototype.resize=function(b,c){this.width+=b;this.height+=c;this.right=this.x+ -this.width;this.bottom=this.y+this.height;return this};c.Rect.prototype.resizeTo=function(b,c){this.width=b;this.height=c;this.right=this.x+this.width;this.bottom=this.y+this.height;return this};c.Rect.prototype.draw=function(){c.context.strokeStyle="red";c.context.strokeRect(this.x,this.y,this.width,this.height);return this};c.Rect.prototype.collidePoint=function(b,c){return b>=this.x&&b<=this.right&&c>=this.y&&c<=this.bottom};c.Rect.prototype.collideRect=function(b){return(this.x>=b.x&&this.x<= -b.right||b.x>=this.x&&b.x<=this.right)&&(this.y>=b.y&&this.y<=b.bottom||b.y>=this.y&&b.y<=this.bottom)};c.Rect.prototype.toString=function(){return"[Rect "+this.x+", "+this.y+", "+this.width+", "+this.height+"]"};return c}(jaws||{});"undefined"!==typeof module&&"exports"in module&&(module.exports=jaws.Rect); -jaws=function(c){c.Sprite=function(b){if(!(this instanceof arguments.callee))return new arguments.callee(b);this.set(b);b.context?this.context=b.context:b.dom&&(this.dom=b.dom,this.createDiv());!b.context&&!b.dom&&(c.context?this.context=c.context:(this.dom=c.dom,this.createDiv()))};c.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,width:null,height:null,_constructor:null, -dom:null,context:null};c.Sprite.prototype.set=function(b){c.parseOptions(this,b,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)&&(b=document.createElement("canvas").getContext("2d"),b.fillStyle=this.color,b.fillRect(0,0,this.width,this.height),this.image=b.getImageData(0,0,this.width,this.height)); -this.cacheOffsets();return this};c.Sprite.prototype.clone=function(){var b=new (this._constructor?eval(this._constructor):this.constructor)(this.attributes());b._constructor=this._constructor||this.constructor.name;return b};c.Sprite.prototype.setImage=function(b){var d=this;if(c.isDrawable(b))return this.image=b,this.cacheOffsets();c.assets.isLoaded(b)?(this.image=c.assets.get(b),this.cacheOffsets()):(console.log("WARNING: Image '"+b+"' not preloaded with jaws.assets.add(). Image and a working sprite.rect() will be delayed."), +r[event.keyCode].split(" ").forEach(function(c){j[c]=!1;s[c]&&(s[c](c),b.preventDefault());m[c]&&b.preventDefault()})}function e(b){event=b?b:window.event;r[event.keyCode].split(" ").forEach(function(c){j[c]=!0;p[c]&&(p[c](c),b.preventDefault());m[c]&&b.preventDefault()})}function f(b){event=b?b:window.event;var c=q[event.button];"Microsoft Internet Explorer"==navigator.appName&&(c=n[event.button]);j[c]=!0;p[c]&&(p[c](c),b.preventDefault())}function k(b){event=b?b:window.event;var c=q[event.button]; +"Microsoft Internet Explorer"==navigator.appName&&(c=n[event.button]);j[c]=!1;s[c]&&(s[c](c),b.preventDefault())}function l(b){event=b?b:window.event;j.left_mouse_button=!0;c.mouse_x=b.touches[0].pageX-c.canvas.offsetLeft;c.mouse_y=b.touches[0].pageY-c.canvas.offsetTop}function h(b){event=b?b:window.event;j.left_mouse_button=!1;c.mouse_x=void 0;c.mouse_y=void 0}var j={},r=[],p=[],s=[],q=[],n=[];c.setupInput=function(){var g=[];g[8]="backspace";g[9]="tab";g[13]="enter";g[16]="shift";g[17]="ctrl";g[18]= +"alt";g[19]="pause";g[20]="capslock";g[27]="esc";g[32]="space";g[33]="pageup";g[34]="pagedown";g[35]="end";g[36]="home";g[37]="left";g[38]="up";g[39]="right";g[40]="down";g[45]="insert";g[46]="delete";g[91]="left_window_key leftwindowkey";g[92]="right_window_key rightwindowkey";g[93]="select_key selectkey";g[106]="multiply *";g[107]="add plus +";g[109]="subtract minus -";g[110]="decimalpoint";g[111]="divide /";g[144]="numlock";g[145]="scrollock";g[186]="semicolon ;";g[187]="equalsign =";g[188]="comma ,"; +g[189]="dash -";g[190]="period .";g[191]="forwardslash /";g[192]="graveaccent `";g[219]="openbracket [";g[220]="backslash \\";g[221]="closebracket ]";g[222]="singlequote '";q=["left_mouse_button","center_mouse_button","right_mouse_button"];n=[,"left_mouse_button","right_mouse_button",,"center_mouse_button"];for(var j="numpad0 numpad1 numpad2 numpad3 numpad4 numpad5 numpad6 numpad7 numpad8 numpad9".split(" "),m="f1 f2 f3 f4 f5 f6 f7 f8 f9".split(" "),p="0123456789".split(""),s="abcdefghijklmnopqrstuvwxyz".split(""), +t=0;p[t];t++)g[48+t]=p[t];for(t=0;s[t];t++)g[65+t]=s[t];for(t=0;j[t];t++)g[96+t]=j[t];for(t=0;m[t];t++)g[112+t]=m[t];r=g;window.addEventListener("keydown",e);window.addEventListener("keyup",d);g=c.canvas||c.dom;g.addEventListener("mousedown",f,!1);g.addEventListener("mouseup",k,!1);g.addEventListener("touchstart",l,!1);g.addEventListener("touchend",h,!1);window.addEventListener("blur",b,!1);document.oncontextmenu=function(){return!1}};var m=[];c.preventDefaultKeys=function(b){b.forEach(function(b){m[b]= +!0})};c.pressed=function(b,d){c.isString(b)&&(b=b.split(" "));return d?b.every(function(b){return j[b]}):b.some(function(b){return j[b]})};c.on_keydown=function(b,d){if(c.isArray(b))for(var e=0;b[e];e++)p[b[e]]=d;else p[b]=d};c.on_keyup=function(b,d){if(c.isArray(b))for(var e=0;b[e];e++)s[b[e]]=d;else s[b]=d};c.clearKeyCallbacks=function(){s=[];p=[]};return c}(jaws||{}),jaws=function(c){c.Assets=function(){if(!(this instanceof arguments.callee))return new arguments.callee;this.loaded=[];this.loading= +[];this.src_list=[];this.data=[];this.bust_cache=!1;this.fuchia_to_transparent=this.image_to_canvas=!0;this.root="";this.file_type={};this.file_type.json="json";this.file_type.wav="audio";this.file_type.mp3="audio";this.file_type.ogg="audio";this.file_type.png="image";this.file_type.jpg="image";this.file_type.jpeg="image";this.file_type.gif="image";this.file_type.bmp="image";this.file_type.tiff="image";var b=this;this.length=function(){return this.src_list.length};this.get=function(d){if(c.isArray(d))return d.map(function(c){return b.data[c]}); +if(this.loaded[d])return this.data[d];c.log("No such asset: "+d,!0)};this.isLoading=function(b){return this.loading[b]};this.isLoaded=function(b){return this.loaded[b]};this.getPostfix=function(b){postfix_regexp=/\.([a-zA-Z0-9]+)/;return postfix_regexp.exec(b)[1]};this.getType=function(b){b=this.getPostfix(b);return this.file_type[b]?this.file_type[b]:b};this.add=function(b){if(c.isArray(b))for(var e=0;b[e];e++)this.add(b[e]);else this.src_list.push(b);return this};this.loadAll=function(b){this.error_count= +this.load_count=0;this.onload=b.onload;this.onerror=b.onerror;this.onfinish=b.onfinish;for(i=0;this.src_list[i];i++)this.load(this.src_list[i])};this.getOrLoad=function(b,c,f){this.data[b]?c():this.load(b,c,f)};this.load=function(b,c,f){var k={};k.src=b;k.onload=c;k.onerror=f;this.loading[b]=!0;b=this.root+k.src;this.bust_cache&&(b+="?"+parseInt(1E7*Math.random()));switch(this.getType(k.src)){case "image":k.image=new Image;k.image.asset=k;k.image.onload=this.assetLoaded;k.image.onerror=this.assetError; +k.image.src=b;break;case "audio":k.audio=new Audio(b);k.audio.asset=k;this.data[k.src]=k.audio;k.audio.addEventListener("canplay",this.assetLoaded,!1);k.audio.addEventListener("error",this.assetError,!1);k.audio.load();break;default:c=new XMLHttpRequest,c.asset=k,c.onreadystatechange=this.assetLoaded,c.open("GET",b,!0),c.send(null)}};this.assetLoaded=function(){var d=this.asset,e=d.src,f=b.getType(d.src);b.loaded[e]=!0;b.loading[e]=!1;if("json"==f){if(4!=this.readyState)return;b.data[d.src]=JSON.parse(this.responseText)}else if("image"== +f){e=b.image_to_canvas?c.imageToCanvas(d.image):d.image;if(b.fuchia_to_transparent&&"bmp"==b.getPostfix(d.src)){canvas=c.isImage(e)?c.imageToCanvas(e):e;for(var e=canvas.getContext("2d"),f=e.getImageData(0,0,canvas.width,canvas.height),k=f.data,l=0;lthis.size){this.values.splice(0,1);for(var c=this.value=0;this.values[c];c++)this.value+=this.values[c];this.value/=this.size}this.values.push(b);return this};this.get=function(){return parseInt(this.value)}}window.requestAnimFrame=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame|| +window.msRequestAnimationFrame||function(b){window.setTimeout(b,16.666)};c.GameLoop=function(d,e,f){if(!(this instanceof arguments.callee))return new arguments.callee(d,e);this.ticks=this.fps=this.tick_duration=0;var k,l=!1,h=!1,j=this,r=new b(20);this.runtime=function(){return this.last_tick-this.first_tick};this.start=function(){c.log("game loop start",!0);this.first_tick=(new Date).getTime();this.current_tick=(new Date).getTime();this.last_tick=(new Date).getTime();d.setup&&d.setup(f);step_delay= +1E3/e.fps;60==e.fps?requestAnimFrame(this.loop):k=setInterval(this.loop,step_delay);c.log("game loop loop",!0)};this.loop=function(){j.current_tick=(new Date).getTime();j.tick_duration=j.current_tick-j.last_tick;j.fps=r.add(1E3/j.tick_duration).get();!h&&!l&&(d.update&&d.update(),d.draw&&d.draw(),j.ticks++);60==e.fps&&!h&&requestAnimFrame(j.loop);j.last_tick=j.current_tick};this.pause=function(){l=!0};this.unpause=function(){l=!1};this.stop=function(){k&&clearInterval(k);h=!0}};return c}(jaws||{}), +jaws=function(c){c.Rect=function(b,c,e,f){if(!(this instanceof arguments.callee))return new arguments.callee(b,c,e,f);this.x=b;this.y=c;this.width=e;this.height=f;this.right=b+e;this.bottom=c+f};c.Rect.prototype.getPosition=function(){return[this.x,this.y]};c.Rect.prototype.move=function(b,c){this.x+=b;this.y+=c;this.right+=b;this.bottom+=c;return this};c.Rect.prototype.moveTo=function(b,c){this.x=b;this.y=c;this.right=this.x+this.width;this.bottom=this.y+this.height;return this};c.Rect.prototype.resize= +function(b,c){this.width+=b;this.height+=c;this.right=this.x+this.width;this.bottom=this.y+this.height;return this};c.Rect.prototype.resizeTo=function(b,c){this.width=b;this.height=c;this.right=this.x+this.width;this.bottom=this.y+this.height;return this};c.Rect.prototype.draw=function(){c.context.strokeStyle="red";c.context.strokeRect(this.x,this.y,this.width,this.height);return this};c.Rect.prototype.collidePoint=function(b,c){return b>=this.x&&b<=this.right&&c>=this.y&&c<=this.bottom};c.Rect.prototype.collideRect= +function(b){return(this.x>=b.x&&this.x<=b.right||b.x>=this.x&&b.x<=this.right)&&(this.y>=b.y&&this.y<=b.bottom||b.y>=this.y&&b.y<=this.bottom)};c.Rect.prototype.toString=function(){return"[Rect "+this.x+", "+this.y+", "+this.width+", "+this.height+"]"};return c}(jaws||{});"undefined"!==typeof module&&"exports"in module&&(module.exports=jaws.Rect); +jaws=function(c){c.Sprite=function(b){if(!(this instanceof arguments.callee))return new arguments.callee(b);this.set(b);b.context?this.context=b.context:b.dom&&(this.dom=b.dom,this.createDiv());!b.context&&!b.dom&&(c.context?this.context=c.context:(this.dom=c.dom,this.createDiv()))};c.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:null,width:null,height:null, +_constructor:null,dom:null,context:null};c.Sprite.prototype.set=function(b){c.parseOptions(this,b,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)&&(b=document.createElement("canvas").getContext("2d"),b.fillStyle=this.color,b.fillRect(0,0,this.width,this.height),this.image=b.getImageData(0,0,this.width, +this.height));this.cacheOffsets();return this};c.Sprite.prototype.clone=function(){var b=new (this._constructor?eval(this._constructor):this.constructor)(this.attributes());b._constructor=this._constructor||this.constructor.name;return b};c.Sprite.prototype.setImage=function(b){var d=this;if(c.isDrawable(b))return this.image=b,this.cacheOffsets();c.assets.isLoaded(b)?(this.image=c.assets.get(b),this.cacheOffsets()):(console.log("WARNING: Image '"+b+"' not preloaded with jaws.assets.add(). Image and a working sprite.rect() will be delayed."), c.assets.load(b,function(){d.image=c.assets.get(b);d.cacheOffsets()}));return this};c.Sprite.prototype.flip=function(){this.flipped=this.flipped?!1:!0;return this};c.Sprite.prototype.flipTo=function(b){this.flipped=b;return this};c.Sprite.prototype.rotate=function(b){this.angle+=b;return this};c.Sprite.prototype.rotateTo=function(b){this.angle=b;return this};c.Sprite.prototype.moveTo=function(b,c){this.x=b;this.y=c;return this};c.Sprite.prototype.move=function(b,c){b&&(this.x+=b);c&&(this.y+=c);return this}; c.Sprite.prototype.scaleAll=function(b){this.scale_x*=b;this.scale_y*=b;return this.cacheOffsets()};c.Sprite.prototype.scaleTo=function(b){this.scale_x=this.scale_y=b;return this.cacheOffsets()};c.Sprite.prototype.scaleWidth=function(b){this.scale_x*=b;return this.cacheOffsets()};c.Sprite.prototype.scaleHeight=function(b){this.scale_y*=b;return this.cacheOffsets()};c.Sprite.prototype.setX=function(b){this.x=b;return this};c.Sprite.prototype.setY=function(b){this.y=b;return this};c.Sprite.prototype.setTop= function(b){this.y=b+this.top_offset;return this};c.Sprite.prototype.setBottom=function(b){this.y=b-this.bottom_offset;return this};c.Sprite.prototype.setLeft=function(b){this.x=b+this.left_offset;return this};c.Sprite.prototype.setRight=function(b){this.x=b-this.right_offset;return this};c.Sprite.prototype.setWidth=function(b){this.scale_x=b/this.image.width;return this.cacheOffsets()};c.Sprite.prototype.setHeight=function(b){this.scale_y=b/this.image.height;return this.cacheOffsets()};c.Sprite.prototype.resize= @@ -50,9 +50,9 @@ c.SpriteList.prototype.updateIf=function(b){this.forEach(function(c){b(c)&&c.upd jaws=function(c){function b(b,c,f,k,l){var h=document.createElement("canvas");h.width=k;h.height=l;h.getContext("2d").drawImage(b,c,f,k,l,0,0,h.width,h.height);return h}c.SpriteSheet=function(d){if(!(this instanceof arguments.callee))return new arguments.callee(d);c.parseOptions(this,d,this.default_options);if(c.isString(this.image)&&!d.frame_size){var e=RegExp("_(\\d+)x(\\d+)","g").exec(this.image);this.frame_size=[];this.frame_size[0]=parseInt(e[1]);this.frame_size[1]=parseInt(e[2])}this.image= c.isDrawable(this.image)?this.image:c.assets.data[this.image];this.scale_image&&(e=c.isDrawable(this.image)?this.image:c.assets.get(this.image),this.frame_size[0]*=this.scale_image,this.frame_size[1]*=this.scale_image,this.image=c.gfx.retroScaleImage(e,this.scale_image));this.frames=[];if("down"==this.orientation)for(e=this.offset;ethis.frame_duration&&(this.index+=this.frame_direction,this.sum_tick=0);if(this.index>=this.frames.length||0>this.index)this.bounce?(this.frame_direction=-this.frame_direction,this.index+=2*this.frame_direction):this.loop?this.index= diff --git a/jaws.js b/jaws.js index c1bd1f4..b10bd1e 100644 --- a/jaws.js +++ b/jaws.js @@ -1,4 +1,4 @@ -/* Built at 2013-06-09 18:54:11 +0200 */ +/* Built at 2013-06-21 00:23:18 +0200 */ /** * @namespace JawsJS core functions. "Field Summary" contains readable properties on the main jaws-object. * @@ -413,28 +413,28 @@ jaws.setupInput = function() { k[45] = "insert" k[46] = "delete" - k[91] = "leftwindowkey" - k[92] = "rightwindowkey" - k[93] = "selectkey" - k[106] = "multiply" - k[107] = "add" - k[109] = "subtract" + k[91] = "left_window_key leftwindowkey" + k[92] = "right_window_key rightwindowkey" + k[93] = "select_key selectkey" + k[106] = "multiply *" + k[107] = "add plus +" + k[109] = "subtract minus -" k[110] = "decimalpoint" - k[111] = "divide" + k[111] = "divide /" k[144] = "numlock" k[145] = "scrollock" - k[186] = "semicolon" - k[187] = "equalsign" - k[188] = "comma" - k[189] = "dash" - k[190] = "period" - k[191] = "forwardslash" - k[192] = "graveaccent" - k[219] = "openbracket" - k[220] = "backslash" - k[221] = "closebracket" - k[222] = "singlequote" + k[186] = "semicolon ;" + k[187] = "equalsign =" + k[188] = "comma ," + k[189] = "dash -" + k[190] = "period ." + k[191] = "forwardslash /" + k[192] = "graveaccent `" + k[219] = "openbracket [" + k[220] = "backslash \\" + k[221] = "closebracket ]" + k[222] = "singlequote '" var m = [] @@ -489,13 +489,15 @@ function resetPressedKeys(e) { */ function handleKeyUp(e) { event = (e) ? e : window.event - var human_name = keycode_to_string[event.keyCode] - pressed_keys[human_name] = false - if(on_keyup_callbacks[human_name]) { - on_keyup_callbacks[human_name](human_name) - e.preventDefault() - } - if(prevent_default_keys[human_name]) { e.preventDefault() } + var human_names = keycode_to_string[event.keyCode].split(" ") + human_names.forEach( function(human_name) { + pressed_keys[human_name] = false + if(on_keyup_callbacks[human_name]) { + on_keyup_callbacks[human_name](human_name) + e.preventDefault() + } + if(prevent_default_keys[human_name]) { e.preventDefault() } + }); } /** @private @@ -503,13 +505,15 @@ function handleKeyUp(e) { */ function handleKeyDown(e) { event = (e) ? e : window.event - var human_name = keycode_to_string[event.keyCode] - pressed_keys[human_name] = true - if(on_keydown_callbacks[human_name]) { - on_keydown_callbacks[human_name](human_name) - e.preventDefault() - } - if(prevent_default_keys[human_name]) { e.preventDefault() } + var human_names = keycode_to_string[event.keyCode].split(" ") + human_names.forEach( function(human_name) { + pressed_keys[human_name] = true + if(on_keydown_callbacks[human_name]) { + on_keydown_callbacks[human_name](human_name) + e.preventDefault() + } + if(prevent_default_keys[human_name]) { e.preventDefault() } + }); } /** @private * handle event "onmousedown" by remembering what button was pressed @@ -1155,408 +1159,409 @@ return jaws; // Support CommonJS require() if(typeof module !== "undefined" && ('exports' in module)) { module.exports = jaws.Rect } -var jaws = (function(jaws) { - -/** -* @class A basic but powerfull sprite for all your onscreen-game objects. "Field Summary" contains options for the Sprite()-constructor. -* @constructor -* -* @property {int} x Horizontal position (0 = furthest left) -* @property {int} y Vertical position (0 = top) -* @property {image} image Image/canvas or string pointing to an asset ("player.png") -* @property {int} alpha Transparency 0=fully transparent, 1=no transperency -* @property {int} angle Angle in degrees (0-360) -* @property {bool} flipped Flip sprite horizontally, usefull for sidescrollers -* @property {string} anchor String stating how to anchor the sprite to canvas, @see Sprite#anchor ("top_left", "center" etc) -* @property {int} scale_image Scale the sprite by this factor -* @property {string,gradient} color If set, draws a rectangle of dimensions rect() with specified color or gradient (linear or radial) -* -* @example -* // create new sprite at top left of the screen, will use jaws.assets.get("foo.png") -* new Sprite({image: "foo.png", x: 0, y: 0}) -* -* // sets anchor to "center" on creation -* new Sprite({image: "topdownspaceship.png", anchor: "center"}) -* -*/ -jaws.Sprite = function Sprite(options) { - if( !(this instanceof arguments.callee) ) return new arguments.callee( options ); - - this.set(options) - - if(options.context) { - this.context = options.context - } - else if(options.dom) { // No canvas context? Switch to DOM-based spritemode - this.dom = options.dom - this.createDiv() - } - if(!options.context && !options.dom) { // Defaults to jaws.context or jaws.dom - if(jaws.context) this.context = jaws.context; - else { - this.dom = jaws.dom; - this.createDiv() - } - } -} - -jaws.Sprite.prototype.default_options = { - x: 0, - y: 0, - alpha: 1, - angle: 0, - flipped: false, - 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, - width: null, - height: null, - _constructor: null, - dom: null, - context: null -} - -/** - * @private - * Call setters from JSON object. Used to parse options. - */ -jaws.Sprite.prototype.set = function(options) { - jaws.parseOptions(this, options, this.default_options); - - if(this.scale) this.scale_x = this.scale_y = this.scale; - if(this.image) this.setImage(this.image); - if(this.scale_image) this.scaleImage(this.scale_image); - if(this.anchor) this.setAnchor(this.anchor); - - if(!this.image && this.color && this.width && this.height) { - var canvas = document.createElement('canvas'); - var context = canvas.getContext('2d'); - context.fillStyle = this.color; - context.fillRect(0, 0, this.width, this.height); - this.image = context.getImageData(0, 0, this.width, this.height); - } - - this.cacheOffsets() - - return this -} - -/** - * @private - * - * Creates a new sprite from current sprites attributes() - * Checks JawsJS magic property '_constructor' when deciding with which constructor to create it - * - */ -jaws.Sprite.prototype.clone = function(object) { - var constructor = this._constructor ? eval(this._constructor) : this.constructor - var new_sprite = new constructor( this.attributes() ); - new_sprite._constructor = this._constructor || this.constructor.name - return new_sprite -} - - -/** - * Sets image from image/canvas or asset-string ("foo.png") - * If asset isn't previously loaded setImage() will try to load it. - */ -jaws.Sprite.prototype.setImage = function(value) { - var that = this - - // An image, great, set this.image and return - if(jaws.isDrawable(value)) { - this.image = value - return this.cacheOffsets() - } - // Not an image, therefore an asset string, i.e. "ship.bmp" - else { - // Assets already loaded? Set this.image - if(jaws.assets.isLoaded(value)) { this.image = jaws.assets.get(value); this.cacheOffsets(); } - - // Not loaded? Load it with callback to set image. - else { - console.log("WARNING: Image '" + value + "' not preloaded with jaws.assets.add(). Image and a working sprite.rect() will be delayed.") - jaws.assets.load(value, function() { that.image = jaws.assets.get(value); that.cacheOffsets(); }) - } - } - return this -} - -/** Flips image vertically, usefull for sidescrollers when player is walking left/right */ -jaws.Sprite.prototype.flip = function() { this.flipped = this.flipped ? false : true; return this } -jaws.Sprite.prototype.flipTo = function(value) { this.flipped = value; return this } -/** Rotate sprite by value degrees */ -jaws.Sprite.prototype.rotate = function(value) { this.angle += value; return this } -/** Force an rotation-angle on sprite */ -jaws.Sprite.prototype.rotateTo = function(value) { this.angle = value; return this } -/** Set x/y */ -jaws.Sprite.prototype.moveTo = function(x,y) { this.x = x; this.y = y; return this } -/** Modify x/y */ -jaws.Sprite.prototype.move = function(x,y) { if(x) this.x += x; if(y) this.y += y; return this } -/** -* scale sprite by given factor. 1=don't scale. <1 = scale down. 1>: scale up. -* Modifies width/height. -**/ -jaws.Sprite.prototype.scaleAll = function(value) { this.scale_x *= value; this.scale_y *= value; return this.cacheOffsets() } -/** set scale factor. ie. 2 means a doubling if sprite in both directions. */ -jaws.Sprite.prototype.scaleTo = function(value) { this.scale_x = this.scale_y = value; return this.cacheOffsets() } -/** scale sprite horizontally by scale_factor. Modifies width. */ -jaws.Sprite.prototype.scaleWidth = function(value) { this.scale_x *= value; return this.cacheOffsets() } -/** scale sprite vertically by scale_factor. Modifies height. */ -jaws.Sprite.prototype.scaleHeight = function(value) { this.scale_y *= value; return this.cacheOffsets() } - -/** Sets x */ -jaws.Sprite.prototype.setX = function(value) { this.x = value; return this } -/** Sets y */ -jaws.Sprite.prototype.setY = function(value) { this.y = value; return this } - -/** Position sprites top on the y-axis */ -jaws.Sprite.prototype.setTop = function(value) { this.y = value + this.top_offset; return this } -/** Position sprites bottom on the y-axis */ -jaws.Sprite.prototype.setBottom = function(value) { this.y = value - this.bottom_offset; return this } -/** Position sprites left side on the x-axis */ -jaws.Sprite.prototype.setLeft = function(value) { this.x = value + this.left_offset; return this } -/** Position sprites right side on the x-axis */ -jaws.Sprite.prototype.setRight = function(value) { this.x = value - this.right_offset; return this } - -/** Set new width. Scales sprite. */ -jaws.Sprite.prototype.setWidth = function(value) { this.scale_x = value/this.image.width; return this.cacheOffsets() } -/** Set new height. Scales sprite. */ -jaws.Sprite.prototype.setHeight = function(value) { this.scale_y = value/this.image.height; return this.cacheOffsets() } -/** Resize sprite by adding width */ -jaws.Sprite.prototype.resize = function(width, height) { - this.scale_x = (this.width + width) / this.image.width - this.scale_y = (this.height + height) / this.image.height - return this.cacheOffsets() -} -/** - * Resize sprite to exact width/height - */ -jaws.Sprite.prototype.resizeTo = function(width, height) { - this.scale_x = width / this.image.width - this.scale_y = height / this.image.height - return this.cacheOffsets() -} - -/** -* The sprites anchor could be describe as "the part of the sprite will be placed at x/y" -* or "when rotating, what point of the of the sprite will it rotate round" -* -* @example -* For example, a topdown shooter could use setAnchor("center") --> Place middle of the ship on x/y -* .. and a sidescroller would probably use setAnchor("center_bottom") --> Place "feet" at x/y -*/ -jaws.Sprite.prototype.setAnchor = function(value) { - var anchors = { - top_left: [0,0], - left_top: [0,0], - center_left: [0,0.5], - left_center: [0,0.5], - bottom_left: [0,1], - left_bottom: [0,1], - top_center: [0.5,0], - center_top: [0.5,0], - center_center: [0.5,0.5], - center: [0.5,0.5], - bottom_center: [0.5,1], - center_bottom: [0.5,1], - top_right: [1,0], - right_top: [1,0], - center_right: [1,0.5], - right_center: [1,0.5], - bottom_right: [1,1], - right_bottom: [1,1] - } - - if(a = anchors[value]) { - this.anchor_x = a[0] - this.anchor_y = a[1] - if(this.image) this.cacheOffsets(); - } - return this -} - -/** @private */ -jaws.Sprite.prototype.cacheOffsets = function() { - if(!this.image) { return } - - this.width = this.image.width * this.scale_x - this.height = this.image.height * this.scale_y - this.left_offset = this.width * this.anchor_x - this.top_offset = this.height * this.anchor_y - this.right_offset = this.width * (1.0 - this.anchor_x) - this.bottom_offset = this.height * (1.0 - this.anchor_y) - - if(this.cached_rect) this.cached_rect.resizeTo(this.width, this.height); - return this -} - -/** Returns a jaws.Rect() perfectly surrouning sprite. Also cache rect in this.cached_rect. */ -jaws.Sprite.prototype.rect = function() { - if(!this.cached_rect && this.width) this.cached_rect = new jaws.Rect(this.x, this.y, this.width, this.height); - if(this.cached_rect) this.cached_rect.moveTo(this.x - this.left_offset, this.y - this.top_offset); - return this.cached_rect -} - -/** - * Make this sprite a DOM-based
sprite - * @private - */ -jaws.Sprite.prototype.createDiv = function() { - this.div = document.createElement("div") - this.div.style.position = "absolute" - if(this.image) { - this.div.style.width = this.image.width + "px" - this.div.style.height = this.image.height + "px" - if(this.image.toDataURL) { this.div.style.backgroundImage = "url(" + this.image.toDataURL() + ")" } - else { this.div.style.backgroundImage = "url(" + this.image.src + ")" } - } - if(this.dom) { this.dom.appendChild(this.div) } - this.updateDiv() -} - -/** - * @private - * Update properties for DOM-based sprite - */ -jaws.Sprite.prototype.updateDiv = function() { - this.div.style.left = this.x + "px" - this.div.style.top = this.y + "px" - - var transform = "" - transform += "rotate(" + this.angle + "deg) " - if(this.flipped) { transform += "scale(-" + this.scale_x + "," + this.scale_y + ")"; } - else { transform += "scale(" + this.scale_x + "," + this.scale_y + ")"; } - - this.div.style.MozTransform = transform - this.div.style.WebkitTransform = transform - this.div.style.OTransform = transform - this.div.style.msTransform = transform - this.div.style.transform = transform - - return this -} - -/** Draw sprite on active canvas or update it's DOM-properties */ -jaws.Sprite.prototype.draw = function() { - if(!this.image) { return this } - if(this.dom) { return this.updateDiv() } - - this.context.save() - this.context.translate(this.x, this.y) - if(this.angle!=0) { jaws.context.rotate(this.angle * Math.PI / 180) } - this.flipped && this.context.scale(-1, 1) - this.context.globalAlpha = this.alpha - this.context.translate(-this.left_offset, -this.top_offset) // Needs to be separate from above translate call cause of flipped - this.context.drawImage(this.image, 0, 0, this.width, this.height) - this.context.restore() - return this -} - -/** - * Scales image using hard block borders. Useful for that cute, blocky retro-feeling. - * Depends on gfx.js beeing loaded. - */ -jaws.Sprite.prototype.scaleImage = function(factor) { - if(!this.image) return; - this.setImage( jaws.gfx.retroScaleImage(this.image, factor) ) - return this -} - -/** - * Returns sprite as a canvas context. - * For certain browsers, a canvas context is faster to work with then a pure image. - */ -jaws.Sprite.prototype.asCanvasContext = function() { - var canvas = document.createElement("canvas") - canvas.width = this.width - canvas.height = this.height - - var context = canvas.getContext("2d") - context.mozImageSmoothingEnabled = jaws.context.mozImageSmoothingEnabled - - context.drawImage(this.image, 0, 0, this.width, this.height) - return context -} - -/** - * Returns sprite as a canvas - */ -jaws.Sprite.prototype.asCanvas = function() { - var canvas = document.createElement("canvas") - canvas.width = this.width - canvas.height = this.height - - var context = canvas.getContext("2d") - context.mozImageSmoothingEnabled = jaws.context.mozImageSmoothingEnabled - - context.drawImage(this.image, 0, 0, this.width, this.height) - return canvas -} - -jaws.Sprite.prototype.toString = function() { return "[Sprite " + this.x.toFixed(2) + ", " + this.y.toFixed(2) + ", " + this.width + ", " + this.height + "]" } - -/** returns Sprites state/properties as a pure object */ -jaws.Sprite.prototype.attributes = function() { - var object = this.options // Start with all creation time properties - object["_constructor"] = this._constructor || "jaws.Sprite" - object["x"] = parseFloat(this.x.toFixed(2)) - object["y"] = parseFloat(this.y.toFixed(2)) - object["image"] = this.image_path - object["alpha"] = this.alpha - object["flipped"] = this.flipped - object["angle"] = parseFloat(this.angle.toFixed(2)) - object["scale_x"] = this.scale_x; - object["scale_y"] = this.scale_y; - object["anchor_x"] = this.anchor_x - object["anchor_y"] = this.anchor_y - - return object -} - -/** - * returns a JSON-string representing the state of the Sprite. - * - * Use this to serialize your sprites / game objects, maybe to save in local storage or on a server - * - * jaws.game_states.Edit uses this to export all edited objects. - * - */ -jaws.Sprite.prototype.toJSON = function() { - return JSON.stringify(this.attributes()) -} - -return jaws; -})(jaws || {}); - -// Support CommonJS require() -if(typeof module !== "undefined" && ('exports' in module)) { module.exports = jaws.Sprite } - -/* -// Chainable setters under consideration: -jaws.Sprite.prototype.setFlipped = function(value) { this.flipped = value; return this } -jaws.Sprite.prototype.setAlpha = function(value) { this.alpha = value; return this } -jaws.Sprite.prototype.setAnchorX = function(value) { this.anchor_x = value; this.cacheOffsets(); return this } -jaws.Sprite.prototype.setAnchorY = function(value) { this.anchor_y = value; this.cacheOffsets(); return this } -jaws.Sprite.prototype.setAngle = function(value) { this.angle = value; return this } -jaws.Sprite.prototype.setScale = function(value) { this.scale_x = this.scale_y = value; this.cacheOffsets(); return this } -jaws.Sprite.prototype.setScaleX = function(value) { this.scale_x = value; this.cacheOffsets(); return this } -jaws.Sprite.prototype.setScaleY = function(value) { this.scale_y = value; this.cacheOffsets(); return this } -jaws.Sprite.prototype.moveX = function(x) { this.x += x; return this } -jaws.Sprite.prototype.moveXTo = function(x) { this.x = x; return this } -jaws.Sprite.prototype.moveY = function(y) { this.y += y; return this } -jaws.Sprite.prototype.moveYTo = function(y) { this.y = y; return this } -jaws.Sprite.prototype.scaleWidthTo = function(value) { this.scale_x = value; return this.cacheOffsets() } -jaws.Sprite.prototype.scaleHeightTo = function(value) { this.scale_y = value; return this.cachOfffsets() } -*/ - +var jaws = (function(jaws) { + +/** +* @class A basic but powerfull sprite for all your onscreen-game objects. "Field Summary" contains options for the Sprite()-constructor. +* @constructor +* +* @property {int} x Horizontal position (0 = furthest left) +* @property {int} y Vertical position (0 = top) +* @property {image} image Image/canvas or string pointing to an asset ("player.png") +* @property {int} alpha Transparency 0=fully transparent, 1=no transperency +* @property {int} angle Angle in degrees (0-360) +* @property {bool} flipped Flip sprite horizontally, usefull for sidescrollers +* @property {string} anchor String stating how to anchor the sprite to canvas, @see Sprite#anchor ("top_left", "center" etc) +* @property {int} scale_image Scale the sprite by this factor +* @property {string,gradient} color If set, draws a rectangle of dimensions rect() with specified color or gradient (linear or radial) +* +* @example +* // create new sprite at top left of the screen, will use jaws.assets.get("foo.png") +* new Sprite({image: "foo.png", x: 0, y: 0}) +* +* // sets anchor to "center" on creation +* new Sprite({image: "topdownspaceship.png", anchor: "center"}) +* +*/ +jaws.Sprite = function Sprite(options) { + if( !(this instanceof arguments.callee) ) return new arguments.callee( options ); + + this.set(options) + + if(options.context) { + this.context = options.context + } + else if(options.dom) { // No canvas context? Switch to DOM-based spritemode + this.dom = options.dom + this.createDiv() + } + if(!options.context && !options.dom) { // Defaults to jaws.context or jaws.dom + if(jaws.context) this.context = jaws.context; + else { + this.dom = jaws.dom; + this.createDiv() + } + } +} + +jaws.Sprite.prototype.default_options = { + x: 0, + y: 0, + alpha: 1, + angle: 0, + flipped: false, + 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: null, + width: null, + height: null, + _constructor: null, + dom: null, + context: null +} + +/** + * @private + * Call setters from JSON object. Used to parse options. + */ +jaws.Sprite.prototype.set = function(options) { + jaws.parseOptions(this, options, this.default_options); + + if(this.scale) this.scale_x = this.scale_y = this.scale; + if(this.image) this.setImage(this.image); + if(this.scale_image) this.scaleImage(this.scale_image); + if(this.anchor) this.setAnchor(this.anchor); + + if(!this.image && this.color && this.width && this.height) { + var canvas = document.createElement('canvas'); + var context = canvas.getContext('2d'); + context.fillStyle = this.color; + context.fillRect(0, 0, this.width, this.height); + this.image = context.getImageData(0, 0, this.width, this.height); + } + + this.cacheOffsets() + + return this +} + +/** + * @private + * + * Creates a new sprite from current sprites attributes() + * Checks JawsJS magic property '_constructor' when deciding with which constructor to create it + * + */ +jaws.Sprite.prototype.clone = function(object) { + var constructor = this._constructor ? eval(this._constructor) : this.constructor + var new_sprite = new constructor( this.attributes() ); + new_sprite._constructor = this._constructor || this.constructor.name + return new_sprite +} + + +/** + * Sets image from image/canvas or asset-string ("foo.png") + * If asset isn't previously loaded setImage() will try to load it. + */ +jaws.Sprite.prototype.setImage = function(value) { + var that = this + + // An image, great, set this.image and return + if(jaws.isDrawable(value)) { + this.image = value + return this.cacheOffsets() + } + // Not an image, therefore an asset string, i.e. "ship.bmp" + else { + // Assets already loaded? Set this.image + if(jaws.assets.isLoaded(value)) { this.image = jaws.assets.get(value); this.cacheOffsets(); } + + // Not loaded? Load it with callback to set image. + else { + console.log("WARNING: Image '" + value + "' not preloaded with jaws.assets.add(). Image and a working sprite.rect() will be delayed.") + jaws.assets.load(value, function() { that.image = jaws.assets.get(value); that.cacheOffsets(); }) + } + } + return this +} + +/** Flips image vertically, usefull for sidescrollers when player is walking left/right */ +jaws.Sprite.prototype.flip = function() { this.flipped = this.flipped ? false : true; return this } +jaws.Sprite.prototype.flipTo = function(value) { this.flipped = value; return this } +/** Rotate sprite by value degrees */ +jaws.Sprite.prototype.rotate = function(value) { this.angle += value; return this } +/** Force an rotation-angle on sprite */ +jaws.Sprite.prototype.rotateTo = function(value) { this.angle = value; return this } +/** Set x/y */ +jaws.Sprite.prototype.moveTo = function(x,y) { this.x = x; this.y = y; return this } +/** Modify x/y */ +jaws.Sprite.prototype.move = function(x,y) { if(x) this.x += x; if(y) this.y += y; return this } +/** +* scale sprite by given factor. 1=don't scale. <1 = scale down. 1>: scale up. +* Modifies width/height. +**/ +jaws.Sprite.prototype.scaleAll = function(value) { this.scale_x *= value; this.scale_y *= value; return this.cacheOffsets() } +/** set scale factor. ie. 2 means a doubling if sprite in both directions. */ +jaws.Sprite.prototype.scaleTo = function(value) { this.scale_x = this.scale_y = value; return this.cacheOffsets() } +/** scale sprite horizontally by scale_factor. Modifies width. */ +jaws.Sprite.prototype.scaleWidth = function(value) { this.scale_x *= value; return this.cacheOffsets() } +/** scale sprite vertically by scale_factor. Modifies height. */ +jaws.Sprite.prototype.scaleHeight = function(value) { this.scale_y *= value; return this.cacheOffsets() } + +/** Sets x */ +jaws.Sprite.prototype.setX = function(value) { this.x = value; return this } +/** Sets y */ +jaws.Sprite.prototype.setY = function(value) { this.y = value; return this } + +/** Position sprites top on the y-axis */ +jaws.Sprite.prototype.setTop = function(value) { this.y = value + this.top_offset; return this } +/** Position sprites bottom on the y-axis */ +jaws.Sprite.prototype.setBottom = function(value) { this.y = value - this.bottom_offset; return this } +/** Position sprites left side on the x-axis */ +jaws.Sprite.prototype.setLeft = function(value) { this.x = value + this.left_offset; return this } +/** Position sprites right side on the x-axis */ +jaws.Sprite.prototype.setRight = function(value) { this.x = value - this.right_offset; return this } + +/** Set new width. Scales sprite. */ +jaws.Sprite.prototype.setWidth = function(value) { this.scale_x = value/this.image.width; return this.cacheOffsets() } +/** Set new height. Scales sprite. */ +jaws.Sprite.prototype.setHeight = function(value) { this.scale_y = value/this.image.height; return this.cacheOffsets() } +/** Resize sprite by adding width */ +jaws.Sprite.prototype.resize = function(width, height) { + this.scale_x = (this.width + width) / this.image.width + this.scale_y = (this.height + height) / this.image.height + return this.cacheOffsets() +} +/** + * Resize sprite to exact width/height + */ +jaws.Sprite.prototype.resizeTo = function(width, height) { + this.scale_x = width / this.image.width + this.scale_y = height / this.image.height + return this.cacheOffsets() +} + +/** +* The sprites anchor could be describe as "the part of the sprite will be placed at x/y" +* or "when rotating, what point of the of the sprite will it rotate round" +* +* @example +* For example, a topdown shooter could use setAnchor("center") --> Place middle of the ship on x/y +* .. and a sidescroller would probably use setAnchor("center_bottom") --> Place "feet" at x/y +*/ +jaws.Sprite.prototype.setAnchor = function(value) { + var anchors = { + top_left: [0,0], + left_top: [0,0], + center_left: [0,0.5], + left_center: [0,0.5], + bottom_left: [0,1], + left_bottom: [0,1], + top_center: [0.5,0], + center_top: [0.5,0], + center_center: [0.5,0.5], + center: [0.5,0.5], + bottom_center: [0.5,1], + center_bottom: [0.5,1], + top_right: [1,0], + right_top: [1,0], + center_right: [1,0.5], + right_center: [1,0.5], + bottom_right: [1,1], + right_bottom: [1,1] + } + + if(a = anchors[value]) { + this.anchor_x = a[0] + this.anchor_y = a[1] + if(this.image) this.cacheOffsets(); + } + return this +} + +/** @private */ +jaws.Sprite.prototype.cacheOffsets = function() { + if(!this.image) { return } + + this.width = this.image.width * this.scale_x + this.height = this.image.height * this.scale_y + this.left_offset = this.width * this.anchor_x + this.top_offset = this.height * this.anchor_y + this.right_offset = this.width * (1.0 - this.anchor_x) + this.bottom_offset = this.height * (1.0 - this.anchor_y) + + if(this.cached_rect) this.cached_rect.resizeTo(this.width, this.height); + return this +} + +/** Returns a jaws.Rect() perfectly surrouning sprite. Also cache rect in this.cached_rect. */ +jaws.Sprite.prototype.rect = function() { + if(!this.cached_rect && this.width) this.cached_rect = new jaws.Rect(this.x, this.y, this.width, this.height); + if(this.cached_rect) this.cached_rect.moveTo(this.x - this.left_offset, this.y - this.top_offset); + return this.cached_rect +} + +/** + * Make this sprite a DOM-based
sprite + * @private + */ +jaws.Sprite.prototype.createDiv = function() { + this.div = document.createElement("div") + this.div.style.position = "absolute" + if(this.image) { + this.div.style.width = this.image.width + "px" + this.div.style.height = this.image.height + "px" + if(this.image.toDataURL) { this.div.style.backgroundImage = "url(" + this.image.toDataURL() + ")" } + else { this.div.style.backgroundImage = "url(" + this.image.src + ")" } + } + if(this.dom) { this.dom.appendChild(this.div) } + this.updateDiv() +} + +/** + * @private + * Update properties for DOM-based sprite + */ +jaws.Sprite.prototype.updateDiv = function() { + this.div.style.left = this.x + "px" + this.div.style.top = this.y + "px" + + var transform = "" + transform += "rotate(" + this.angle + "deg) " + if(this.flipped) { transform += "scale(-" + this.scale_x + "," + this.scale_y + ")"; } + else { transform += "scale(" + this.scale_x + "," + this.scale_y + ")"; } + + this.div.style.MozTransform = transform + this.div.style.WebkitTransform = transform + this.div.style.OTransform = transform + this.div.style.msTransform = transform + this.div.style.transform = transform + + return this +} + +/** Draw sprite on active canvas or update it's DOM-properties */ +jaws.Sprite.prototype.draw = function() { + if(!this.image) { return this } + if(this.dom) { return this.updateDiv() } + + this.context.save() + this.context.translate(this.x, this.y) + if(this.angle!=0) { jaws.context.rotate(this.angle * Math.PI / 180) } + this.flipped && this.context.scale(-1, 1) + this.context.globalAlpha = this.alpha + this.context.translate(-this.left_offset, -this.top_offset) // Needs to be separate from above translate call cause of flipped + this.context.drawImage(this.image, 0, 0, this.width, this.height) + this.context.restore() + return this +} + +/** + * Scales image using hard block borders. Useful for that cute, blocky retro-feeling. + * Depends on gfx.js beeing loaded. + */ +jaws.Sprite.prototype.scaleImage = function(factor) { + if(!this.image) return; + this.setImage( jaws.gfx.retroScaleImage(this.image, factor) ) + return this +} + +/** + * Returns sprite as a canvas context. + * For certain browsers, a canvas context is faster to work with then a pure image. + */ +jaws.Sprite.prototype.asCanvasContext = function() { + var canvas = document.createElement("canvas") + canvas.width = this.width + canvas.height = this.height + + var context = canvas.getContext("2d") + context.mozImageSmoothingEnabled = jaws.context.mozImageSmoothingEnabled + + context.drawImage(this.image, 0, 0, this.width, this.height) + return context +} + +/** + * Returns sprite as a canvas + */ +jaws.Sprite.prototype.asCanvas = function() { + var canvas = document.createElement("canvas") + canvas.width = this.width + canvas.height = this.height + + var context = canvas.getContext("2d") + context.mozImageSmoothingEnabled = jaws.context.mozImageSmoothingEnabled + + context.drawImage(this.image, 0, 0, this.width, this.height) + return canvas +} + +jaws.Sprite.prototype.toString = function() { return "[Sprite " + this.x.toFixed(2) + ", " + this.y.toFixed(2) + ", " + this.width + ", " + this.height + "]" } + +/** returns Sprites state/properties as a pure object */ +jaws.Sprite.prototype.attributes = function() { + var object = this.options // Start with all creation time properties + object["_constructor"] = this._constructor || "jaws.Sprite" + object["x"] = parseFloat(this.x.toFixed(2)) + object["y"] = parseFloat(this.y.toFixed(2)) + object["image"] = this.image_path + object["alpha"] = this.alpha + object["flipped"] = this.flipped + object["angle"] = parseFloat(this.angle.toFixed(2)) + object["scale_x"] = this.scale_x; + object["scale_y"] = this.scale_y; + object["anchor_x"] = this.anchor_x + object["anchor_y"] = this.anchor_y + + return object +} + +/** + * returns a JSON-string representing the state of the Sprite. + * + * Use this to serialize your sprites / game objects, maybe to save in local storage or on a server + * + * jaws.game_states.Edit uses this to export all edited objects. + * + */ +jaws.Sprite.prototype.toJSON = function() { + return JSON.stringify(this.attributes()) +} + +return jaws; +})(jaws || {}); + +// Support CommonJS require() +if(typeof module !== "undefined" && ('exports' in module)) { module.exports = jaws.Sprite } + +/* +// Chainable setters under consideration: +jaws.Sprite.prototype.setFlipped = function(value) { this.flipped = value; return this } +jaws.Sprite.prototype.setAlpha = function(value) { this.alpha = value; return this } +jaws.Sprite.prototype.setAnchorX = function(value) { this.anchor_x = value; this.cacheOffsets(); return this } +jaws.Sprite.prototype.setAnchorY = function(value) { this.anchor_y = value; this.cacheOffsets(); return this } +jaws.Sprite.prototype.setAngle = function(value) { this.angle = value; return this } +jaws.Sprite.prototype.setScale = function(value) { this.scale_x = this.scale_y = value; this.cacheOffsets(); return this } +jaws.Sprite.prototype.setScaleX = function(value) { this.scale_x = value; this.cacheOffsets(); return this } +jaws.Sprite.prototype.setScaleY = function(value) { this.scale_y = value; this.cacheOffsets(); return this } +jaws.Sprite.prototype.moveX = function(x) { this.x += x; return this } +jaws.Sprite.prototype.moveXTo = function(x) { this.x = x; return this } +jaws.Sprite.prototype.moveY = function(y) { this.y += y; return this } +jaws.Sprite.prototype.moveYTo = function(y) { this.y = y; return this } +jaws.Sprite.prototype.scaleWidthTo = function(value) { this.scale_x = value; return this.cacheOffsets() } +jaws.Sprite.prototype.scaleHeightTo = function(value) { this.scale_y = value; return this.cachOfffsets() } +*/ + var jaws = (function(jaws) { /** * @class Manages all your Sprites in lists. Makes easy mass-draw() / update() possible among others. Implements Array API. "Field Summary" contains options for the SpriteList()-constructor. @@ -2012,6 +2017,10 @@ var jaws = (function(jaws) { jaws.Parallax = function Parallax(options) { if( !(this instanceof arguments.callee) ) return new arguments.callee( options ); jaws.parseOptions(this, options, this.default_options) + + this.width = options.width || jaws.width; + this.height = options.height || jaws.height; + } jaws.Parallax.prototype.default_options = { @@ -2020,6 +2029,8 @@ jaws.Parallax.prototype.default_options = { repeat_y: null, camera_x: 0, camera_y: 0, + width: null, + height: null, layers: [] } @@ -2045,8 +2056,8 @@ jaws.Parallax.prototype.draw = function(options) { } layer.x = initx; - while (layer.y < jaws.height) { - while (layer.x < jaws.width) { + while (layer.y < this.height) { + while (layer.x < this.width) { if (layer.x + layer.width >= 0 && layer.y + layer.height >= 0) { //Make sure it's on screen layer.draw(); //Draw only if actually on screen, for performance reasons }