├── README.md
├── example
├── img
│ ├── .DS_Store
│ ├── bg.jpg
│ ├── reptile.png
│ └── reptile2.png
├── index-minifiedLib.html
└── index.html
├── mibbu-min.js
└── mibbu.js
/README.md:
--------------------------------------------------------------------------------
1 | Mibbu
2 | ========
3 |
4 | #### First Javascript Game MicroFramework ####
5 |
6 | Mibbu gives you everything you need for fast prototyping your Javascript game in less than 2.5KB of gzipped code. Games created with Mibbu can be displayed using Canvas or DOM mode (you can change it with one single function, or use feature detection to use DOM where it is no canvas, like in IE family). Mibbu supports also CSS animations in Webkit ([blogpost](http://michalbe.blogspot.com/2011/05/css3-animations-in-mibbu.html)) and in Firefox BETA (5.0).
7 |
8 |
9 | [Documentation](http://mibbu.eu)
10 |
11 |
12 | ### Features of Mibbu ###
13 | * Rendering game using both - Canvas or DOM
14 | * Animation of the sprites (using Canvas, DOM or CSS Animation in Webkit & Firefox 5+)
15 | * Collisions detection with collision zones
16 | * Simple background manager
17 | * Callbacks after given number of frames
18 | * Method's chaining
19 | * Check [example](https://github.com/michalbe/mibbu/tree/master/example) for more
20 |
21 | ### Change Log ###
22 |
23 | 2011 08 09 - **0.3.2/nagasaki** (5.62 KB, gzip 2.29 KB)
24 |
25 | * one pixel background margin bug in Canvas Mode fixed.
26 |
27 | 2011 08 07 - **0.3.1/victor** (5.91 KB, gzip 2.36 KB) by [end3r](https://github.com/end3r)
28 |
29 | * it's now possible to switch background image using .img() function
30 |
31 | 2011 06 12 - **0.3/arkansas** (5.89 KB, gzip 2.37 KB)
32 |
33 | * every method now return itself when you call it with parameters (like .speed(3)) so it's possile to connect multiple methods into one chain (like background.speed(4).direction(-20)). Methods called without arguments returns value of given metod (like background.speed() return the speed of the background)
34 |
35 | 2011 06 12 - **0.2.4/annefrank** (5.57 KB, gzip 2.30 KB) by [MartinDoms](https://github.com/MartinDoms)
36 |
37 | * background direction could be now specified in both, strings ("N", "S", "E", "W") and numbers (radians)
38 | * it is possible to change background direction 'on the fly' without resetting the background position
39 |
40 | 2011 06 11 - **0.2.3/kamehameha** (5.42 KB, gzip 2.12 KB)
41 |
42 | * FPS module optimization
43 |
44 | 2011 06 05 - **v0.2.2/blackwater** (5.43 KB, gzip 2.12 KB)
45 |
46 | * Animation structure changed according to Marek Stepien's research on CSS Animations in Firefox [[blogpost](http://michalbe.blogspot.com/2011/06/css-animation-in-firefox.html#update)]
47 |
48 | 2011 06 04 - **v0.2.1/birthdayAfterparty** (5.46 KB, gzip 2.12 KB)
49 |
50 | * CSS3 Animations support in Firefox (tested in 5.0/BETA)
51 | * .indexOf() name changed for minimization and compatibility with other solutions [[blogpost](http://michalbe.blogspot.com/2011/06/css-animation-in-firefox.html)]
52 |
53 | 2011 05 23 - **v0.2/suiko** (5.54 KB, gzip 2.13 KB) [[blogpost](http://michalbe.blogspot.com/2011/05/css3-animations-in-mibbu.html)]
54 |
55 | * CSS3 Animations support in Webkit browsers (tested on Chrome 11 & Safari 5.03)
56 | * .cssAnimationOff() function added (works the same as .canvasOff() but for CSS Animations)
57 | * some major & minor bug fixes
58 |
59 | 2011 05 19 - **v0.1.2/guanabhadra** (4.36 KB, gzip: 1.81 KB)
60 |
61 | * Changes in Array#indexOf - we don't need full spec implementation here. This one is faster and smaller.
62 |
63 | 2011 05 09 - **v0.1.1/atilla** (4.45 KB, gzip: 1.83 KB)
64 |
65 | * Array#indexOf fix by [killdream](https://github.com/killdream)
66 | * Proper declaration of MB_mainCanvasStyle variable
67 |
68 | 2011 05 05 - **v0.1/odoacer** (4.35 KB, gzip: 1.81 KB)
69 |
70 | * First release
71 |
72 | ----
73 |
74 | ### License ###
75 |
76 | ####The MIT License####
77 |
78 | Copyright (c) 2011 [Michal Budzynski](https://profiles.google.com/michal.budzynski.js/about). All rights reserved.
79 |
80 | Permission is hereby granted, free of charge, to any person obtaining a copy
81 | of this software and associated documentation files (the "Software"), to deal
82 | in the Software without restriction, including without limitation the rights
83 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
84 | copies of the Software, and to permit persons to whom the Software is
85 | furnished to do so, subject to the following conditions:
86 |
87 | The above copyright notice and this permission notice shall be included in
88 | all copies or substantial portions of the Software.
89 |
90 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
91 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
92 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
93 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
94 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
95 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
96 | THE SOFTWARE.
97 |
--------------------------------------------------------------------------------
/example/img/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michalbe/mibbu/52bbde1ac98def0f8644566a126ad1e2f079fc2f/example/img/.DS_Store
--------------------------------------------------------------------------------
/example/img/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michalbe/mibbu/52bbde1ac98def0f8644566a126ad1e2f079fc2f/example/img/bg.jpg
--------------------------------------------------------------------------------
/example/img/reptile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michalbe/mibbu/52bbde1ac98def0f8644566a126ad1e2f079fc2f/example/img/reptile.png
--------------------------------------------------------------------------------
/example/img/reptile2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michalbe/mibbu/52bbde1ac98def0f8644566a126ad1e2f079fc2f/example/img/reptile2.png
--------------------------------------------------------------------------------
/example/index-minifiedLib.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Mibbu test
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
128 |
129 |
130 |
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Mibbu test
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
128 |
129 |
130 |
--------------------------------------------------------------------------------
/mibbu-min.js:
--------------------------------------------------------------------------------
1 | var l=void 0,mibbu=function(J,K,A){function q(){for(var c=n.length,e,d,f,g,b,h,a,B,C;c--;)for(e in d=n[c],g=d.d+d.b.A,b=d.d+d.height-d.b.q,h=d.c+d.b.u,d=d.c+d.width-d.b.w,n[c].t)if(f=D[e],a=f.d+f.b.A,B=f.d+f.height-f.b.q,C=f.c+f.b.u,f=f.c+f.width-f.b.w,!(g>B||bf||d=1E3&&(G=v,v=0,u=c);c="FPS: "+G;if(k)o.fillText(c,4,15);else if(s)s.innerHTML=c;v++}w&&(H=I(E,g))}function L(){g=m.createElement("canvas");o=g.getContext("2d");o.j=o.drawImage;e.sort(function(c,e){return c.h-e.h})}function M(){F=k?function(){o.clearRect(0,0,x,y)}:function(){};r&&(u=new Date);I=function(){return window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(c){setTimeout(c,1E3/60)}}();p=g.style;g.width=x;g.height=y;p.width=x+"px";p.height=y+"px";p.position="absolute";p.overflow="hidden";z.appendChild(g)}var k=!0,j=!1,m=document,e=[],z=A?m.getElementById(A):m.body,g,o,x=J||400,y=K||300,i=[],H,F,u=new Date,r=!1,s,n=[],D=[],I,p,t,h;Array.prototype.j=Array.prototype.indexOf||function(c){for(var e=this.length;e--&&this[e]!==c;);return e};var v=0,G=0,w=!0;m.createElement("canvas").getContext||(k=!1);return{fps:function(){r=!0;return this},init:function(){k?L():(g=m.createElement("div"),r&&(s=m.createElement("div"),g.appendChild(s)));M();return this},on:function(){w=!0;E();if(j)for(var c=e.length;c--;)e[c].k&&(e[c].k.style[h+"AnimationDuration"]=~~(1/(60/e[c].e)*100)/100*(e[c].g+1)+"s");return this},off:function(){clearTimeout(H);w=!1;if(j)for(var c=e.length;c--;)e[c].k&&(e[c].k.style[h+"AnimationDuration"]=0);return this},canvas:function(){return g},ctx:function(){return o},canvasOff:function(){k=!1;typeof z.style.WebkitAnimation!=="undefined"?(t="-webkit-",h="Webkit",j=!0):typeof z.style.MozAnimation!=="undefined"&&(t="-moz-",h="Moz",j=!0);return this},cssAnimationOff:function(){j=!1;return this},hitsOn:function(){i.j(q)===-1&&i.push(q);return this},hitsOff:function(){i.j(q)!==-1&&i.splice(i.j(q),1);return this},spr:function(c,i,d,f,p){function b(){for(var b="@"+t+"keyframes s"+a.id+" {\n",c=100/(a.g+1),e="% { "+t+"transform: translate(",d=0;d0){if(a.p==a.e&&a.e!==0){if(a.l==a.g){if(a.l=0,typeof a.s==="function"&&(a.r++,a.r===a.B))a.s(),a.r=0}else a.l++;a.p=0}a.e!==0&&a.p++;q()}};return{position:function(b,c,d){return b!==l?(a.c=b||a.c,a.d=c||a.d,a.h=d||a.h,k?d&&e.sort(function(a,b){return b.h-a.h}):(a.f.left=b+"px",a.f.top=c+"px",a.f.zIndex=d||a.h),this):{x:a.c,y:a.d,J:a.h}},hit:function(b,c){n.j(a)===-1&&n.push(a);a.t[b.id()]=c;n.j(a)===-1&&n.push(a);return this},zone:function(b,c,d,e){return b!==l?(a.b.u=e,a.b.A=b,a.b.w=c,a.b.q=d,this):a.b},noHits:function(){a.t={};return this},callback:function(b,c){a.s=b;a.B=c;return this},change:function(c,d,e,f,g){a.k.src=c;a.width=d;a.height=e;a.F=d;a.D=e;a.g=f;a.i=g;a.p=0;a.l=0;a.s=null;a.r=0;a.B=0;if(!k&&(a.a.width=d*(a.i+1)+"px",a.a.height=e*(a.g+1)+"px",a.f.width=d+"px",a.f.height=e+"px",j))a.a[h+"AnimationName"]="",a.o.innerHTML=b(),a.a[h+"AnimationName"]="s"+a.id;a.b={A:0,u:0,q:0,w:0};return this},size:function(c,d){if(c!==l){if(!k)a.f.width=c+"px",a.f.height=d+"px",a.a.width=c*(a.H+1)+"px",a.a.height=d*(a.g+1)+"px";a.width=c;a.height=d;if(j)a.a[h+"AnimationName"]="",a.o.innerHTML=b(),a.a[h+"AnimationName"]="s"+a.id;return this}else return{width:a.width,height:a.height}},speed:function(b){return b!==l?(a.e=b,a.p=0,j&&(a.a[h+"AnimationDuration"]=~~(1/(60/b)*100)/100*(a.g+1)+"s"),this):a.e},animation:function(c){if(c!==l){a.i=c;if(j)a.a[h+"AnimationName"]="",a.o.innerHTML=b(),a.a[h+"AnimationName"]="s"+a.id;return this}else return a.i},frame:function(b){return b!==l?(a.l=b,this):a.l},id:function(){return a.id}}},bg:function(c,i,d,f){function h(a){b.m=0;b.n=0;if(typeof a==="string")switch(a){case "N":b.m=0;b.n=-1;break;case "W":b.m=-1;b.n=0;break;case "S":b.m=0;b.n=1;break;case "E":b.m=1,b.n=0}else if(typeof a==="number")a*=j,b.m=Math.cos(a),b.n=Math.sin(a)}var b=this;g.style.backgroundImage="url("+c+")";b.e=i||3;var j=Math.PI/180;h(d);b.h=f.z||0;b.c=f.x||0;b.d=f.y||0;b.id=e.push(b);b.v=0;b.G=function(){b.c+=b.e*b.m*b.v;b.d+=b.e*b.n*b.v;var a=b.c,c=b.d;a.toString().indexOf("e")!=-1&&(a=0);c.toString().indexOf("e")!=-1&&(c=0);g.style.backgroundPosition=a+"px "+c+"px"};return{on:function(){b.v=1;return this},off:function(){b.v=0;return this},dir:function(a){h(a);return this},speed:function(a){return a!==l?(b.e=a,this):b.e},img:function(a){return a!==l?(g.style.backgroundImage="url("+a+")",this):c},position:function(a,c){return a!==l?(b.c=a||b.c,b.d=c||b.d,this):{x:b.c,y:b.d}}}},hook:function(c){i.push(c);return this},unhook:function(c){i.j(c)!==-1&&i.splice(i.j(c),1);return this}}};
--------------------------------------------------------------------------------
/mibbu.js:
--------------------------------------------------------------------------------
1 | /*global document, setInterval, setTimeout, Image, clearTimeout*/
2 |
3 | /**
4 | *
5 | * mibbu - javascript canvas/DOM game framework
6 | * by Michal Budzynski
7 | * http://michalbe.blogspot.com
8 | * http://twitter.com/michalbe
9 | * http://mibbu.eu
10 | * http://onGameStart.com
11 | *
12 | */
13 |
14 | var mibbu = function(Cwidth, Cheight, _parent){
15 | var MB_usingCanvas = true, //use canvas or DOM?
16 | MB_usingCSSAnimations = false,
17 | document = window['document'], //document declaration for Closure Compiler
18 | MB_elements = [], //all drawable elements
19 | MB_parentElement = _parent ? document.getElementById(_parent) : document.body, //parent element the canvas will be appended to
20 | MB_mainCanvas,
21 | MB_mainContext,
22 | MB_mainCanvasWidth = Cwidth || 400,
23 | MB_mainCanvasHeight = Cheight || 300,
24 | MB_addedLoops=[], //functions added to each loop frame
25 | MB_drawLoop, //main loop
26 | MB_preClear,
27 | MB_lastTime = new Date(), //time for FPS counter
28 | MB_fpsMeasure=false,
29 | MB_ftpsDiv,
30 | MB_collides=[], //array with references to objects with enabled collisions
31 | MB_fixedIndexColl = [], //workaround for collisions
32 | MB_Animate,
33 | MB_mainCanvasStyle,
34 | MB_prefixCSS,
35 | MB_prefixJS;
36 | /**
37 | * Older browser's fixes
38 | */
39 | // Fallback for Array#indexOf, where the implementation does not support it
40 | // natively
41 | //
42 | // Follows the algorithm described in ES-262 15.4.4.14
43 | //
44 | /*
45 | //MDC spec-like implementation
46 | Array.prototype.indexOf = Array.prototype.indexOf
47 | || function (value, start) {
48 | var key;
49 | var obj = Object(this);
50 | var len = obj.length >>> 0;
51 |
52 | start = +start || 0;
53 | if (!len || start >= len){
54 | return -1;
55 | }
56 | if (start < 0){
57 | start = Math.max(0, len - Math.abs(start));
58 | }
59 |
60 | for (key = start; key < len; ++key){
61 | if (key in obj && obj[key] === value){
62 | return key;
63 | }
64 | }
65 | return -1;
66 | }
67 | */
68 | // lastIndexOf implementation by Andrea Giammarchi
69 | // form Falsy Values conference
70 | // http://webreflection.blogspot.com
71 | Array.prototype.i = Array.prototype.indexOf ||
72 | function(value){
73 | for (var i = this.length; i-- && this[i]!== value;) {}
74 | return i;
75 | };
76 |
77 | //and custom remove() method
78 | var rm = function(value, array) {
79 | if (array.i(value)!==-1) {
80 | array.splice(array.i(value), 1);
81 | return true;
82 | } else {
83 | return false;
84 | }
85 | } ;
86 |
87 |
88 | /**
89 | * DEBUG FUNCTIONS
90 | **/
91 |
92 | var frameCount=0;
93 | var fps = 0;
94 | var MeasureFPS = function(){
95 | var newTime = +(new Date());
96 | var diffTime = ~~((newTime - MB_lastTime));
97 |
98 | if (diffTime >= 1000) {
99 | fps = frameCount;
100 | frameCount = 0;
101 | MB_lastTime = newTime;
102 | }
103 | var stringFps = 'FPS: ' + fps;
104 | if (MB_usingCanvas) {
105 | //MB_mainContext.fillStyle = "#fff";
106 | //MB_mainContext.font = "12px Arial";
107 | MB_mainContext.fillText(stringFps, 4, 15);
108 | } else {
109 | if (MB_ftpsDiv) {
110 | MB_ftpsDiv.innerHTML = stringFps;
111 | }
112 | }
113 | frameCount++;
114 | };
115 |
116 | /**
117 | * end of debug functions
118 | *
119 | * Start/Stop functions
120 | **/
121 |
122 | var calculateSpeed = function(speed, frames) {
123 | return (~~((1/(60/speed))*100)/100)*(frames+1);
124 | };
125 | //main drawing function
126 | var DrawAll = function(){
127 |
128 | MB_preClear();
129 |
130 | //draw all element
131 | var loopIndex = MB_elements.length;
132 | while (loopIndex--) {
133 | MB_elements[loopIndex].draw();
134 | }
135 |
136 | //run other functions
137 | loopIndex = MB_addedLoops.length;
138 | while (loopIndex--) {
139 | MB_addedLoops[loopIndex]();
140 | }
141 |
142 | if (MB_fpsMeasure) {
143 | MeasureFPS();
144 | }
145 |
146 | };
147 | //check if it is possible to use canvas
148 | var MB_detectCanvas = function() {
149 | if(!document.createElement('canvas').getContext) {
150 | MB_usingCanvas = false;
151 | }
152 | };
153 |
154 | var MB_InitCore = function() {
155 | //common part of both modes
156 |
157 | MB_preClear = MB_usingCanvas ? function(){MB_mainContext.clearRect(0, 0, MB_mainCanvasWidth, MB_mainCanvasHeight);} : function(){};
158 |
159 | if (MB_fpsMeasure) {
160 | MB_lastTime = new Date();
161 | }
162 |
163 | //use requestAnimationFrame() if possible
164 | //inspired by Paul Irish Blog
165 | //http://paulirish.com/2011/requestanimationframe-for-smart-animating/
166 | //support only for moz & webkit now - Opera or IE are no
167 | //interested in it so far.
168 | MB_Animate = (function(){
169 | return window['webkitRequestAnimationFrame'] ||
170 | window['mozRequestAnimationFrame'] ||
171 | function(/* function */ callback, /* DOMElement */ element){
172 | setTimeout(callback, 1000 / 60);
173 | };
174 | })();
175 |
176 | //inline styling, not using setAttribute()
177 | //because of IE7 & IE8 bugs
178 | MB_mainCanvasStyle = MB_mainCanvas.style;
179 | MB_mainCanvas.width = MB_mainCanvasWidth;
180 | MB_mainCanvas.height = MB_mainCanvasHeight;
181 | MB_mainCanvasStyle.width = MB_mainCanvasWidth+'px';
182 | MB_mainCanvasStyle.height =MB_mainCanvasHeight+'px';
183 | MB_mainCanvasStyle.position ='absolute';
184 | MB_mainCanvasStyle.overflow = 'hidden';
185 |
186 | MB_parentElement.appendChild(MB_mainCanvas);
187 |
188 | };
189 |
190 | var MB_InitCanvas = function() {
191 | MB_mainCanvas = document.createElement('canvas');
192 |
193 | MB_mainContext = MB_mainCanvas.getContext('2d');
194 | MB_mainContext.i = MB_mainContext.drawImage;
195 |
196 | //sorting all elements is like Z-Index for canvas
197 | MB_elements.sort(function(a,b){return a.zOrder - b.zOrder;});
198 |
199 | };
200 |
201 | var MB_InitDOM = function() {
202 |
203 | MB_mainCanvas = document.createElement('div');
204 |
205 | //MB_mainCanvas.style.overflow = 'hidden';
206 |
207 | if (MB_fpsMeasure) {
208 |
209 | MB_ftpsDiv = document.createElement('div');
210 | MB_mainCanvas.appendChild(MB_ftpsDiv);
211 |
212 | }
213 |
214 | };
215 |
216 | //initiation of main loop
217 | var running = true,
218 | MB_Start = function() {
219 | DrawAll();
220 |
221 | if(running)
222 | MB_drawLoop = MB_Animate(MB_Start, MB_mainCanvas);
223 | };
224 |
225 | var MB_Stop = function() {
226 | clearTimeout(MB_drawLoop);
227 | running=false;
228 | };
229 |
230 | /**
231 | * End of Start/Stop functions
232 | **/
233 | //collisions
234 | var MB_checkCollides = function() {
235 | var loopIndex = MB_collides.length,
236 | element,
237 | p1, p2,
238 | p1Top, p1Bottom, p1Left, p1Right,
239 | p2Top, p2Bottom, p2Left, p2Right;
240 |
241 | while(loopIndex--) {
242 | p1 = MB_collides[loopIndex];
243 | p1Top = p1.posY + p1.cZ.t;
244 | p1Bottom = p1.posY + p1.height - p1.cZ.b;
245 | p1Left = p1.posX + p1.cZ.l;
246 | p1Right = p1.posX + p1.width - p1.cZ.r;
247 |
248 | //UNCOMMENT THSE TWO BLOCKS FOR COLLISION BOXES.
249 | //IN CANVAS MODE ONLY!
250 | /*
251 | MB_mainContext.moveTo(p1Right, p1Top);
252 |
253 | MB_mainContext.lineTo(p1Right, p1Bottom);
254 | MB_mainContext.lineTo(p1Left, p1Bottom);
255 | MB_mainContext.lineTo(p1Left, p1Top);
256 | MB_mainContext.lineTo(p1Right, p1Top);
257 | */
258 | for(element in MB_collides[loopIndex].hits){
259 | p2 = MB_fixedIndexColl[element];
260 | p2Top = p2.posY + p2.cZ.t;
261 | p2Bottom = p2.posY + p2.height - p2.cZ.b;
262 | p2Left = p2.posX + p2.cZ.l;
263 | p2Right = p2.posX + p2.width - p2.cZ.r;
264 | /*
265 | MB_mainContext.moveTo(p2Right, p2Top);
266 |
267 | MB_mainContext.lineTo(p2Right, p2Bottom);
268 | MB_mainContext.lineTo(p2Left, p2Bottom);
269 | MB_mainContext.lineTo(p2Left, p2Top);
270 | MB_mainContext.lineTo(p2Right, p2Top);
271 | MB_mainContext.stroke();
272 | */
273 | if (!(
274 | (p1Top > p2Bottom) ||
275 | (p1Bottom < p2Top) ||
276 | (p1Left > p2Right) ||
277 | (p1Right < p2Left)
278 | )){
279 | //console.dir(MB_collides[loopIndex].hits)
280 | MB_collides[loopIndex].hits[element]();
281 | }
282 | }
283 |
284 | }
285 | };
286 |
287 | /**
288 | * SPRITES
289 | **/
290 |
291 | var MB_Sprite = function(_image, _width, _height, _frames, _animations) {
292 |
293 | var draw = MB_usingCanvas ? function(){
294 | //draw canvas
295 | try {
296 | MB_mainContext.i(t.image,
297 | t.iWidth * t.animation,
298 | t.iHeight * t.f,
299 | t.iWidth,
300 | t.iHeight,
301 | t.posX,
302 | t.posY,
303 | t.width,
304 | t.height);
305 | } catch(e) {
306 | //if image is not ready yet try to display it on another frame
307 | //delete this and build preLoader
308 | }
309 | } : MB_usingCSSAnimations ? function(){ /*css animations*/ } : function(){
310 | //draw DOM
311 | t.si.top = t.height * t.f*-1+'px';
312 | t.si.left = t.width * t.animation*-1+'px';
313 | },
314 | t = {},
315 | //prepare class for CSS animation
316 | constructAnimationClass = function(){
317 | var animationClass = "@" + MB_prefixCSS + "keyframes s"+t.id+" {\n",
318 | step = 100/(t.fs+1),
319 | str = "% { " + MB_prefixCSS + "transform: translate(";
320 | for (var q = 0; q < t.fs+1; q++) {
321 | animationClass += ~~((step*q)*100)/100+ str +t.animation*t.width*-1+'px,'+q*t.height*-1+'px); }\n';
322 | animationClass += ~~((step*(q+1)-0.01)*100)/100+ str +t.animation*t.width*-1+'px,'+q*t.height*-1+'px); }\n';
323 | }
324 |
325 | return animationClass += '100'+ str +t.animation*t.width+'px, 0px); }\n}';
326 |
327 | };
328 |
329 |
330 | t.id = MB_elements.length;
331 |
332 | t.image = new Image();
333 | t.image.src = _image;
334 |
335 | t.speed = 1;
336 | t.width = _width;
337 | t.iWidth = _width;
338 | t.height = _height;
339 | t.iHeight = _height;
340 | t.fs = _frames;
341 | t.animations = _animations;
342 | t.colllides = false;
343 | t.hits = {};
344 |
345 | t.f = 0;
346 | t.animation = 0;
347 | t.speed = 1;
348 | t.interval = 0;
349 |
350 | t.posX = 0;
351 | t.posY = 0;
352 |
353 | t.zOrder = 1;
354 |
355 | t.callback = null;
356 | t.callIters=0;
357 | t.callMaxIters=0;
358 |
359 | //collision zones
360 | t.cZ = {
361 | t: 0,
362 | l: 0,
363 | b:0,
364 | r: 0
365 | }
366 |
367 | if (!MB_usingCanvas) {
368 | //document.createElement('img') not allowed in IE6
369 | t.div = document.createElement('div');
370 | t.s = t.div.style;
371 |
372 | t.s.overflow = 'hidden';
373 | t.s.width = _width+'px';
374 | t.s.height = _height+'px';
375 | t.s.position = 'absolute';
376 | t.s.zIndex = t.zOrder;
377 |
378 | t.si = t.image.style;
379 |
380 | t.si.position="absolute";
381 |
382 | if (MB_usingCSSAnimations) {
383 | //calculate keyframes for CSS animation
384 |
385 |
386 | //append keyframe class to the document
387 | t.animStyle = document.createElement('style');
388 | t.animStyle.innerHTML = constructAnimationClass();
389 | //document.getElementsByTagName('head')[0]
390 | document.body.appendChild(t.animStyle);
391 |
392 | //additional style attribute for the image,
393 | t.si[ MB_prefixJS + "Animation" ] = "s"+t.id+" "+calculateSpeed(t.speed, t.fs)+"s linear 0s infinite";
394 |
395 |
396 | }
397 |
398 | t.div.appendChild(t.image);
399 |
400 | MB_mainCanvas.appendChild(t.div);
401 | }
402 |
403 | t.id = MB_elements.push(t)-1;
404 | MB_fixedIndexColl.push(t); //for collisions, temporary
405 |
406 | var setPosition = function(x, y, z) {
407 | //there is at least one argument,
408 | //set position and return 'this' for chaining
409 | if (x !== undefined) {
410 | t.posX = x || t.posX;
411 | t.posY = y || t.posY;
412 | t.zOrder = z || t.zOrder;
413 |
414 | if (MB_usingCanvas) {
415 | if (z) {
416 | MB_elements.sort(function(a, b){
417 |
418 | return b.zOrder - a.zOrder;
419 | }
420 | );
421 |
422 | }
423 | } else {
424 | t.s.left = x+'px';
425 | t.s.top = y+'px';
426 | t.s.zIndex = z || t.zOrder;
427 | }
428 | return this;
429 | } else {
430 | //method called without parameters, return
431 | //actual position
432 | return {x:t.posX, y:t.posY, z:t.zOrder}
433 | }
434 | },
435 |
436 | setCollide = function(e) {
437 | if (e && MB_collides.i(t) === -1) {
438 | MB_collides.push(t);
439 | } else if (!e && MB_collides.i(t) !== -1){
440 | rm(t, MB_collides);
441 | }
442 | },
443 |
444 | onHit = function (object, callback) {
445 | setCollide(true);
446 | t.hits[object.id()] = callback;
447 | if (MB_collides.i(t) === -1) {
448 | MB_collides.push(t);
449 | }
450 | return this;
451 | };
452 |
453 | t.draw = function() {
454 |
455 | if (t.fs > 0) {
456 | if (t.interval == t.speed && t.speed !== 0) {
457 | if (t.f == t.fs) {
458 | t.f = 0;
459 |
460 | if (typeof t.callback === "function") {
461 | t.callIters++;
462 | if (t.callIters === t.callMaxIters) {
463 | t.callback();
464 | t.callIters = 0;
465 | }
466 |
467 | }
468 |
469 | }
470 | else {
471 | t.f++;
472 | }
473 | t.interval = 0;
474 | }
475 | if (t.speed !== 0) {
476 | t.interval++;
477 | }
478 |
479 | draw();
480 |
481 | }
482 | };
483 | var reSize = function(w, h){
484 | //there are some arguments
485 | //so change size of the sprite
486 | //and return 'this' for chaining
487 | if (w !== undefined) {
488 | if (!MB_usingCanvas){
489 |
490 | t.s.width = w+'px';
491 | t.s.height = h+'px';
492 |
493 | t.si.width = w*(t.animations+1)+'px';
494 | t.si.height = h*(t.fs+1)+'px';
495 |
496 | }
497 | t.width = w;
498 | t.height = h;
499 | if (MB_usingCSSAnimations) {
500 | //any smarter way to refresh cssAnimation than clearing the name of it?
501 | t.si[ MB_prefixJS+ "AnimationName" ] = '';
502 | t.animStyle.innerHTML = constructAnimationClass();
503 | t.si[ MB_prefixJS+ "AnimationName" ] = 's'+t.id;
504 |
505 | };
506 |
507 | return this;
508 |
509 | } else {
510 |
511 | return {width:t.width,height:t.height};
512 | }
513 | };
514 |
515 | return {
516 | 'position':setPosition,
517 | 'hit':onHit,
518 | 'zone': function(top, right, bottom, left) {
519 | if (top !== undefined) {
520 | t.cZ.l = left;
521 | t.cZ.t = top;
522 | t.cZ.r = right;
523 | t.cZ.b = bottom;
524 |
525 | return this;
526 | } else {
527 | return t.cZ;
528 | }
529 | },
530 | 'noHits':function() {
531 | t.hits = {};
532 | return this;
533 | },
534 | 'callback':function(fn, iteration) {
535 | t.callback = fn;
536 | t.callMaxIters = iteration;
537 | return this;
538 | },
539 | 'change': function(image, width, height, frames, animation) {
540 | t.image.src = image;
541 | t.width = width;
542 | t.height = height;
543 | t.iWidth = width;
544 | t.iHeight = height;
545 | t.fs = frames;
546 | t.animation = animation;
547 | t.interval = 0;
548 | t.f = 0;
549 | t.callback = null;
550 | t.callIters=0;
551 | t.callMaxIters=0;
552 |
553 | if (!MB_usingCanvas) {
554 | t.si.width = width*(t.animation+1)+'px';
555 | t.si.height = height*(t.fs+1)+'px';
556 | t.s.width = width+'px';
557 | t.s.height = height+'px';
558 | if (MB_usingCSSAnimations) {
559 | //any smarter way to refresh cssAnimation than clearing it's name?
560 | t.si[ MB_prefixJS+ "AnimationName" ] = '';
561 | t.animStyle.innerHTML = constructAnimationClass();
562 | t.si[ MB_prefixJS+ "AnimationName" ] = 's'+t.id;
563 | }
564 | }
565 |
566 | t.cZ = {
567 | t: 0,
568 | l: 0,
569 | b: 0,
570 | r: 0
571 | }
572 |
573 | return this;
574 | },
575 |
576 | 'size':reSize,
577 | 'speed':function(e) {
578 | if (e !== undefined) {
579 | t.speed=e;
580 | t.interval=0;
581 | if (MB_usingCSSAnimations){
582 | t.si[ MB_prefixJS+ "AnimationDuration" ] = calculateSpeed(e, t.fs)+'s';
583 | }
584 |
585 | return this;
586 | } else {
587 | return t.speed;
588 | }
589 | },
590 | 'animation':function(e) {
591 | if (e !== undefined) {
592 |
593 | t.animation=e;
594 |
595 | if (MB_usingCSSAnimations) {
596 | //any smarter way to refresh cssAnimation than clearing the name of it?
597 | t.si[ MB_prefixJS+ "AnimationName" ] = '';
598 | t.animStyle.innerHTML = constructAnimationClass();
599 | t.si[ MB_prefixJS+ "AnimationName" ] = 's'+t.id;
600 | }
601 |
602 | return this;
603 | } else {
604 | return t.animation;
605 | }
606 | },
607 | 'frame':function(e) {
608 | if (e !== undefined) {
609 | t.f=e;
610 | return this;
611 | } else {
612 | return t.f;
613 | }
614 | },
615 | 'id': function() { return t.id; }
616 | };
617 | };
618 |
619 | /**
620 | * SPRITES END
621 | **/
622 |
623 | /**
624 | * START BACKGROUNDS
625 | **/
626 | var MB_Background = function(image, speed, direction, options) {
627 |
628 | var draw = function(){
629 | //draw DOM & Canvas
630 | // If the values are too close to 0 JS will print them as exponentials
631 | // which won't work on the DOM. There's probably a more efficient way to
632 | // do this.
633 | var posX = t.posX,
634 | posY = t.posY;
635 |
636 | if (posX.toString().indexOf('e') != -1) posX = 0;
637 | if (posY.toString().indexOf('e') != -1) posY = 0;
638 | MB_mainCanvas.style.backgroundPosition = posX +"px "+posY+"px";
639 | },
640 | t = this;
641 |
642 | var setImage = function(img) {
643 | MB_mainCanvas.style.backgroundImage = 'url('+img+')';
644 | };
645 |
646 | setImage(image);
647 |
648 | t.speed = speed || 3;
649 |
650 | var radsPerDegree = Math.PI / 180,
651 | direcionFromParameter = function(dir){
652 | t.dX = 0;
653 | t.dY = 0;
654 | if (typeof dir === "string") {
655 | switch (dir) {
656 | case 'N':
657 | t.dX = 0;
658 | t.dY = -1;
659 | break;
660 | case 'W':
661 | t.dX = -1;
662 | t.dY = 0;
663 | break;
664 | case 'S':
665 | t.dX = 0;
666 | t.dY = 1;
667 | break;
668 | case 'E':
669 | t.dX = 1;
670 | t.dY = 0;
671 | break;
672 | default:
673 | break;
674 | }
675 | }
676 | else if (typeof dir === "number") {
677 | dir = radsPerDegree * dir; // convert from degrees to radians
678 | t.dX = Math.cos(dir);
679 | t.dY = Math.sin(dir);
680 | }
681 | }
682 |
683 | direcionFromParameter(direction);
684 |
685 | t.zOrder = options['z'] || 0;
686 | t.posX = options['x'] || 0;
687 | t.posY = options['y'] || 0;
688 |
689 | t.id = MB_elements.push(t);
690 | t.moving = 0;
691 |
692 | var setPosition = function(x, y) {
693 | if (x !== undefined) {
694 | t.posX = x || t.posX;
695 | t.posY = y || t.posY;
696 |
697 | return this;
698 | } else {
699 | return {x:t.posX, y:t.posY}
700 | }
701 | };
702 |
703 | t.draw = function() {
704 | t.posX += t.speed*t.dX*t.moving;
705 | t.posY += t.speed*t.dY*t.moving;
706 |
707 | draw();
708 | }
709 |
710 | return {
711 | 'on': function() { t.moving = 1; return this;},
712 | 'off': function() { t.moving = 0; return this;},
713 | 'dir': function(direction) { direcionFromParameter(direction); return this;},
714 | 'speed':function(e) { if (e !== undefined) { t.speed=e; return this;} else return t.speed;},
715 | 'img': function(img) { if (img !== undefined) { setImage(img); return this;} else return image;},
716 | 'position':setPosition
717 | }
718 |
719 | }
720 |
721 |
722 | /**
723 | * Constructor functions
724 | */
725 | MB_detectCanvas();
726 |
727 |
728 | return {
729 | //config
730 | 'fps': function() {MB_fpsMeasure=true; return this;},
731 | 'init': function() { MB_usingCanvas ? MB_InitCanvas() : MB_InitDOM(); MB_InitCore(); return this;},
732 | 'on': function() {
733 | running=true;
734 | MB_Start();
735 | if (MB_usingCSSAnimations){
736 | //this solution is really stupid and temporary ( I hope )
737 | //unfortunatelly any other didn't really work
738 | var i = MB_elements.length;
739 | for (;i--;){
740 | if (MB_elements[i].image)
741 | MB_elements[i].image.style[ MB_prefixJS+ "AnimationDuration" ] = calculateSpeed(MB_elements[i].speed, MB_elements[i].fs)+'s';
742 | }
743 | }
744 | return this;
745 | },
746 | 'off': function(){
747 | MB_Stop();
748 | if (MB_usingCSSAnimations){
749 | //this solution is really stupid and temporary ( I hope )
750 | //unfortunatelly any other didn't really work
751 | var i = MB_elements.length;
752 | for (;i--;){
753 | if (MB_elements[i].image)
754 | MB_elements[i].image.style[ MB_prefixJS+ "AnimationDuration" ] = 0;
755 | }
756 | }
757 | return this;
758 | },
759 | 'canvas': function(){ return MB_mainCanvas; },
760 | 'ctx': function() {return MB_mainContext; },
761 | 'canvasOff': function() {
762 |
763 | MB_usingCanvas=false;
764 |
765 |
766 | if (typeof MB_parentElement.style.WebkitAnimation !== "undefined") {
767 |
768 | //we have webkit CSS3 animation support
769 | MB_prefixCSS = "-webkit-";
770 | MB_prefixJS = "Webkit";
771 | MB_usingCSSAnimations = true;
772 |
773 | } else if (typeof MB_parentElement.style['MozAnimation'] !== "undefined") {
774 | //stupid Closure Compiler don't understand style.MozAnimation so I had to use brackets here
775 |
776 | //and in Firefox
777 | MB_prefixCSS = "-moz-";
778 | MB_prefixJS = "Moz";
779 | MB_usingCSSAnimations = true;
780 | }
781 | return this;
782 | },
783 |
784 | 'cssAnimationOff': function() {
785 | MB_usingCSSAnimations=false;
786 | return this;
787 | },
788 |
789 | 'hitsOn': function() {
790 | if (MB_addedLoops.i(MB_checkCollides) === -1)
791 | MB_addedLoops.push(MB_checkCollides);
792 | return this;
793 | },
794 |
795 | 'hitsOff': function() {
796 | rm(MB_checkCollides, MB_addedLoops);
797 | return this;
798 | },
799 |
800 | //elements
801 | 'spr':MB_Sprite,
802 | 'bg': MB_Background,
803 |
804 | //loops
805 | 'hook': function(e){
806 | MB_addedLoops.push(e);
807 | return this;
808 | },
809 |
810 | 'unhook': function(e){
811 | rm(e, MB_addedLoops);
812 | return this;
813 | }
814 |
815 | };
816 | };
817 | //declaration of mibbu object for Closure Compiler
818 | window['mibbu'] = mibbu;
819 |
--------------------------------------------------------------------------------