1
2 (function(window){3
4 var Sakri = window.Sakri ||{};5 window.Sakri = window.Sakri ||Sakri;6
7 Sakri.MathUtil ={};8
9 //used for radiansToDegrees and degreesToRadians
10 Sakri.MathUtil.PI_180 = Math.PI/180;
11 Sakri.MathUtil.ONE80_PI = 180/Math.PI;
12
13 //precalculations for values of 90, 270 and 360 in radians
14 Sakri.MathUtil.PI2 = Math.PI*2;15 Sakri.MathUtil.HALF_PI = Math.PI/2;
16
17
18 //return number between 1 and 0
19 Sakri.MathUtil.normalize = function(value, minimum, maximum){20 return (value - minimum) / (maximum -minimum);21 };22
23 //map normalized number to values
24 Sakri.MathUtil.interpolate = function(normValue, minimum, maximum){25 return minimum + (maximum - minimum) *normValue;26 };27
28 //map a value from one set to another
29 Sakri.MathUtil.map = function(value, min1, max1, min2, max2){30 returnSakri.MathUtil.interpolate( Sakri.MathUtil.normalize(value, min1, max1), min2, max2);31 };32
33 Sakri.MathUtil.getRandomNumberInRange = function(min, max){34 return min + Math.random() * (max -min);35 };36
37 Sakri.MathUtil.getRandomIntegerInRange = function(min, max){38 returnMath.round(Sakri.MathUtil.getRandomNumberInRange(min, max));39 };40
41
42 }(window));43
44 (function(window){45
46 var Sakri = window.Sakri ||{};47 window.Sakri = window.Sakri ||Sakri;48
49 Sakri.Geom ={};50
51 //==================================================
52 //=====================::POINT::====================
53 //==================================================
54
55 Sakri.Geom.Point = function(x,y){56 this.x = isNaN(x) ? 0: x;57 this.y = isNaN(y) ? 0: y;58 };59
60 Sakri.Geom.Point.prototype.clone = function(){61 return new Sakri.Geom.Point(this.x,this.y);62 };63
64 Sakri.Geom.Point.prototype.update = function(x, y){65 this.x = isNaN(x) ? this.x : x;66 this.y = isNaN(y) ? this.y : y;67 };68
69 Sakri.Geom.Point.prototype.equals = function(point){70 return this.x==point.x && this.y==point.y;71 };72
73 Sakri.Geom.Point.prototype.toString = function(){74 return "{x:"+this.x+" , y:"+this.y+"}";75 };76
77
78
79 //==================================================
80 //===================::RECTANGLE::==================
81 //==================================================
82
83 Sakri.Geom.Rectangle = function(x, y, width, height){84 this.update(x, y, width, height);85 };86
87 Sakri.Geom.Rectangle.prototype.update = function(x, y, width, height){88 this.x = isNaN(x) ? 0: x;89 this.y = isNaN(y) ? 0: y;90 this.width = isNaN(width) ? 0: width;91 this.height = isNaN(height) ? 0: height;92 };93
94
95 Sakri.Geom.Rectangle.prototype.getRight = function(){96 return this.x + this.width;97 };98
99 Sakri.Geom.Rectangle.prototype.getBottom = function(){100 return this.y + this.height;101 };102
103 Sakri.Geom.Rectangle.prototype.getCenterX = function(){104 return this.x + this.width/2;
105 };106
107 Sakri.Geom.Rectangle.prototype.getCenterY = function(){108 return this.y + this.height/2;
109 };110
111 Sakri.Geom.Rectangle.prototype.containsPoint = function(x, y){112 return x >= this.x && y >= this.y && x <= this.getRight() && y <= this.getBottom();113 };114
115
116 Sakri.Geom.Rectangle.prototype.clone = function(){117 return new Sakri.Geom.Rectangle(this.x, this.y, this.width, this.height);118 };119
120 Sakri.Geom.Rectangle.prototype.toString = function(){121 return "Rectangle{x:"+this.x+" , y:"+this.y+" , width:"+this.width+" , height:"+this.height+"}";122 };123
124 }(window));125
126 (function(window){127
128 var Sakri = window.Sakri ||{};129 window.Sakri = window.Sakri ||Sakri;130
131 Sakri.CanvasTextUtil ={};132
133 //returns the biggest font size that best fits into rect
134 Sakri.CanvasTextUtil.getFontSizeForRect = function(string, fontProps, rect, canvas, fillStyle){135 if(!canvas){136 var canvas = document.createElement("canvas");137 }138 if(!fillStyle){139 fillStyle = "#000000";140 }141 var context = canvas.getContext('2d');142 context.font =fontProps.getFontString();143 context.textBaseline = "top";144
145 var copy =fontProps.clone();146 //console.log("getFontSizeForRect() 1 : ", copy.fontSize);
147 context.font =copy.getFontString();148 var width =context.measureText(string).width;149 //console.log(width, rect.width);
150
151 //SOME DISAGREEMENT WHETHER THIS SHOOULD BE WITH && or ||
152 if(width rect.width){158 while(context.measureText(string).width > rect.width || copy.fontSize*1.5 >rect.height){159 copy.fontSize--;160 context.font =copy.getFontString();161 }162 }163 //console.log("getFontSizeForRect() 2 : ", copy.fontSize);
164 returncopy.fontSize;165 }166
167 //=========================================================================================
168 //==============::CANVAS TEXT PROPERTIES::====================================
169 //========================================================
170
171 Sakri.CanvasTextProperties = function(fontWeight, fontStyle, fontSize, fontFace){172 this.setFontWeight(fontWeight);173 this.setFontStyle(fontStyle);174 this.setFontSize(fontSize);175 this.fontFace = fontFace ? fontFace : "sans-serif";176 };177
178 Sakri.CanvasTextProperties.NORMAL = "normal";179 Sakri.CanvasTextProperties.BOLD = "bold";180 Sakri.CanvasTextProperties.BOLDER = "bolder";181 Sakri.CanvasTextProperties.LIGHTER = "lighter";182
183 Sakri.CanvasTextProperties.ITALIC = "italic";184 Sakri.CanvasTextProperties.OBLIQUE = "oblique";185
186
187 Sakri.CanvasTextProperties.prototype.setFontWeight = function(fontWeight){188 switch(fontWeight){189 caseSakri.CanvasTextProperties.NORMAL:190 caseSakri.CanvasTextProperties.BOLD:191 caseSakri.CanvasTextProperties.BOLDER:192 caseSakri.CanvasTextProperties.LIGHTER:193 this.fontWeight =fontWeight;194 break;195 default:196 this.fontWeight =Sakri.CanvasTextProperties.NORMAL;197 }198 };199
200 Sakri.CanvasTextProperties.prototype.setFontStyle = function(fontStyle){201 switch(fontStyle){202 caseSakri.CanvasTextProperties.NORMAL:203 caseSakri.CanvasTextProperties.ITALIC:204 caseSakri.CanvasTextProperties.OBLIQUE:205 this.fontStyle =fontStyle;206 break;207 default:208 this.fontStyle =Sakri.CanvasTextProperties.NORMAL;209 }210 };211
212 Sakri.CanvasTextProperties.prototype.setFontSize = function(fontSize){213 if(fontSize && fontSize.indexOf && fontSize.indexOf("px")>-1){214 var size = fontSize.split("px")[0];215 fontProperites.fontSize = isNaN(size) ? 24 : size;//24 is just an arbitrary number
216 return;217 }218 this.fontSize = isNaN(fontSize) ? 24 : fontSize;//24 is just an arbitrary number
219 };220
221 Sakri.CanvasTextProperties.prototype.clone = function(){222 return new Sakri.CanvasTextProperties(this.fontWeight, this.fontStyle, this.fontSize, this.fontFace);223 };224
225 Sakri.CanvasTextProperties.prototype.getFontString = function(){226 return this.fontWeight + " " + this.fontStyle + " " + this.fontSize + "px " + this.fontFace;227 };228
229 }(window));230
231
232 window.requestAnimationFrame =
233 window.__requestAnimationFrame ||
234 window.requestAnimationFrame ||
235 window.webkitRequestAnimationFrame ||
236 window.mozRequestAnimationFrame ||
237 window.oRequestAnimationFrame ||
238 window.msRequestAnimationFrame ||
239 (function() {240 return function(callback, element) {241 var lastTime =element.__lastTime;242 if (lastTime ===undefined) {243 lastTime = 0;244 }245 var currTime =Date.now();246 var timeToCall = Math.max(1, 33 - (currTime -lastTime));247 window.setTimeout(callback, timeToCall);248 element.__lastTime = currTime +timeToCall;249 };250 })();251
252 var readyStateCheckInterval = setInterval( function() {253 if (document.readyState === "complete") {254 clearInterval(readyStateCheckInterval);255 init();256 }257 }, 10);258
259 //========================
260 //general properties for demo set up
261 //========================
262
263 varcanvas;264 varcontext;265 varcanvasContainer;266 varhtmlBounds;267 varbounds;268 var minimumStageWidth = 300;269 var minimumStageHeight = 300;270 var maxStageWidth = 800;271 var maxStageHeight = 1100;272 var resizeTimeoutId = -1;273 //var stats;
274
275 functioninit(){276 canvasContainer = document.getElementById("canvasContainer");277 window.onresize =resizeHandler;278 //stats = new Stats();
279 //canvasContainer.appendChild( stats.getDisplayElement() );
280 window.addEventListener( "keydown", keyUpEventHandler, false)281 commitResize();282 }283
284 function getWidth( element ){returnMath.max(element.scrollWidth,element.offsetWidth,element.clientWidth );}285 function getHeight( element ){returnMath.max(element.scrollHeight,element.offsetHeight,element.clientHeight );}286
287 //avoid running resize scripts repeatedly if a browser window is being resized by dragging
288 functionresizeHandler(){289 context.clearRect(0,0,canvas.width, canvas.height);290 clearTimeout(resizeTimeoutId);291 clearTimeoutsAndIntervals();292 resizeTimeoutId = setTimeout(commitResize, 300);293 }294
295 functioncommitResize(){296 if(canvas){297 canvasContainer.removeChild(canvas);298 }299 canvas = document.createElement('canvas');300 canvas.style.position = "absolute";301 context = canvas.getContext("2d");302 canvasContainer.appendChild(canvas);303
304 htmlBounds = new Sakri.Geom.Rectangle(0,0, getWidth(canvasContainer) , getHeight(canvasContainer));305 if(htmlBounds.width >=maxStageWidth){306 canvas.width =maxStageWidth;307 canvas.style.left = htmlBounds.getCenterX() - (maxStageWidth/2)+"px";
308 }else{309 canvas.width =htmlBounds.width;310 canvas.style.left ="0px";311 }312 if(htmlBounds.height >maxStageHeight){313 canvas.height =maxStageHeight;314 canvas.style.top = htmlBounds.getCenterY() - (maxStageHeight/2)+"px";
315 }else{316 canvas.height =htmlBounds.height;317 canvas.style.top ="0px";318 }319 bounds = new Sakri.Geom.Rectangle(0,0, canvas.width, canvas.height);320 context.clearRect(0,0,canvas.width, canvas.height);321
322 if(bounds.width
327 var textInputSpan = document.getElementById("textInputSpan");328 var textInputSpanY = (canvas.height - canvas.height*.85)/2 + 15;//15 is an estimate for half of textInputHeight
329 textInputSpan.style.top = htmlBounds.getCenterY() + (bounds.height/2) - textInputSpanY +"px";
330 textInputSpan.style.left = (htmlBounds.getCenterX() - getWidth(textInputSpan)/2)+"px";
331
332 startDemo();333 }334
335 functionstageTooSmallHandler(){336 var warning = "Sorry, bigger screen required :(";337 context.font = "bold normal 24px sans-serif";338 context.fillText(warning, bounds.getCenterX() - context.measureText(warning).width/2, bounds.getCenterY()-12);
339 }340
341
342
343
344 //========================
345 //Demo specific properties
346 //========================
347
348
349 var HOME = 0;350 var GAME = 1;351 var GAME_OVER = 2;352 vargameState;353 var scrollSpeed = 3;354 varscore;355 var fontProperties = new Sakri.CanvasTextProperties(Sakri.CanvasTextProperties.BOLD, null, 100);356
357 var word = "张董";358
359 functionstartDemo(){360 canvas.addEventListener('touchstart', handleUserTap, false);361 canvas.addEventListener('mousedown', handleUserTap, false);362
363 var logoText = "飞翔的字母";364 if(!logoCanvas){365 logoCanvas = document.createElement("canvas");366 logoCanvasBG = document.createElement("canvas");367 }368 createLogo("飞翔的字母", logoCanvas, logoCanvasBG);369 if(!gameOverCanvas){370 gameOverCanvas = document.createElement("canvas");371 gameOverCanvasBG = document.createElement("canvas");372 }373 createLogo("行了 到此为止吧", gameOverCanvas, gameOverCanvasBG);374
375 createGroundPattern();376 createBird();377 createTubes();378 createCityGraphic();379 score = 0;380 gameState =HOME;381 loop();382 }383
384 functionloop(){385 switch(gameState){386 caseHOME:387 renderHome();388 break;389 caseGAME :390 renderGame();391 break;392 caseGAME_OVER:393 renderGameOver();394 break;395 }396 //stats.tick();
397 }398
399 functionhandleUserTap(event){400 switch(gameState){