1 // --- 2 // Copyright (c) 2010 Francesco Cottone, http://www.kesiev.com/ 3 // --- 4 5 /** 6 * @namespace Help module provides some Javascript-specific functions, such object copying, randomizing functions, 7 * string/array handlers and the akihabaraInit function. 8 */ 9 var help={ 10 11 /** 12 * Generates numbers from st to ed, along with a skip value. 13 * @param {Integer} st Starting number. 14 * @param {Integer} ed Ending number. 15 * @param {Integer} skip Number to increment by. 16 * @returns An array containing the set of numbers from st to ed, incrementing by skip. 17 */ 18 seq:function(st,ed,skip) { 19 var ret=[]; 20 for (var i=st;i<ed;i+=(skip==null?1:skip)) ret.push(i); 21 return ret; 22 }, 23 24 /** 25 * Multiplies two numbers together, returning the result, unless the first parameter is less than 2, in which case it returns 1. 26 * @param {Float} v First value. 27 * @param {Float} mul Second value. 28 * @returns An integer, v*mul, unless v<2 in which case it returns 1. 29 */ 30 // Handle a multiplier like counter. that means, 0=1 / 1=1 / 2=2*mul etc... 31 multiplier:function(v,mul) { 32 return (!v||(v<2)?1:v*(!mul?1:mul)); 33 }, 34 35 /** 36 * Prepends a string with repeated instances of another string until it the result is greater than or equal to a desired length. 37 * @param {String} str The string you wish to modify. 38 * @param {Integer} len The desired length of your resultant string. 39 * @param {String} pad The string you wish to prepend to str. 40 * @returns A string whose length is no greater than len+pad.length, with pad prepending str repeatedly. 41 */ 42 prepad:function(str,len,pad) { 43 str+=""; 44 while (str.length<len) str=pad+str; 45 return str; 46 }, 47 48 /** 49 * Postpends a string with repeated instances of another string until it the result is greater than or equal to a desired length. 50 * @param {String} str The string you wish to modify. 51 * @param {Integer} len The desired length of your resultant string. 52 * @param {String} pad The string you wish to postpend to str. 53 * @returns A string whose length is no greater than len+pad.length, with pad postpending str repeatedly. 54 */ 55 postpad:function(str,len,pad) { 56 str+=""; 57 while (str.length<len) str+=pad; 58 return str; 59 }, 60 61 /** 62 * Tests to see if an object is being "jumped on" by another object. Only works for platformers, since it assumes accy>0 means you're falling onto something else. 63 * @param {Object} th The object that is (possibly) being jumped on. 64 * @param {Object} by The object doing the jumping-on. 65 * @returns True if the two objects are overlapping enough and by.accy>0. 66 */ 67 isSquished:function(th,by) { 68 return ((by.accy>0)&&gbox.collides(th,by)&&(Math.abs(th.y-(by.y+by.h))<(th.h/2))) 69 }, 70 71 /** 72 * Generates uniformly distributed random integers between min and min+range, non-inclusive. So help.random(0,2) will only return 0 and 1, etc. 73 * @param {Integer} min The minimum random value to be returned by the function. 74 * @param {Integer} range The number of different values returned by the function. 75 * @returns An integer between min (includive) and min+range (noninclusive). 76 */ 77 random:function(min,range) { 78 return min+Math.floor(Math.random()*range); 79 }, 80 81 82 /** 83 * Determines which frame of a given animation to display. Will loop an animation. 84 * @param {Integer} cnt A global frame counter. 85 * @param {Object} anim An object with parameters speed (the animation speed) and frames (the array representing the animation sequence). 86 * @returns The particular animation frame to display during this step. 87 */ 88 decideFrame:function(cnt,anim) { 89 return anim.frames[Math.floor(cnt/anim.speed)%anim.frames.length]; 90 }, 91 92 /** 93 * Determines which frame of a given animation to display. Will remain on the last frame when the animation has played once. 94 * @param {Integer} cnt A global frame counter. 95 * @param {Object} anim An object with parameters speed (the animation speed) and frames (the array representing the animation sequence). 96 * @returns The particular animation frame to display during this step. 97 */ 98 decideFrameOnce:function(cnt,anim) { 99 return anim.frames[(cnt>=anim.frames.length*anim.speed?anim.frames.length-1:Math.floor(cnt/anim.speed))]; 100 }, 101 102 /** 103 * Returns whether the animation was fully played at least once with decideFrame or fully with decideFrameOnce. 104 * @param {Integer} cnt A global frame counter. 105 * @param {Object} anim An object with parameters speed (the animation speed) and frames (the array representing the animation sequence). 106 * @returns A boolean, true if the animation has been played at least once. 107 */ 108 isLastFrameOnce:function(cnt,anim) { 109 return (cnt>=anim.frames.length*anim.speed); 110 }, 111 112 /** 113 * Given an incrementing value each step, this will return a value increasing from 0 until max/2, at which point it will decrement to 0, then go back up to max/2, in an endless cycle. 114 * @param {Integer} counter A counter. 115 * @param {Integer} max This determines the period of the function -- assuming counter is incrementing by one, a complete back-and-forth will take 'max' steps. 116 * @returns An integer. 117 */ 118 upAndDown:function(counter,max) { 119 if ((counter%max)>(max/2)) return max-(counter%max); else return (counter%max); 120 }, 121 122 /** 123 * Given x,y coordinates and map information, this returns the tile at a given point. 124 * @param {Integer} x An x-coordinate. 125 * @param {Integer} y A y-coordinate. 126 * @param {Object} map The map object. 127 * @param {Object} ifout An object or value to be returned if the x,y coordinate pair is outside the map. 128 * @param {String} mapid The id for the map array within the map object. Default is 'map'. 129 * @returns An integer representing the value of the tile in the map array at that x,y coordinate. If there is no tile, null is returned. 130 */ 131 getTileInMap:function(x,y,map,ifout,mapid) { 132 if (!mapid) mapid="map"; 133 var ts=gbox._tiles[map.tileset]; 134 var tx=Math.floor(x/ts.tilew); 135 var ty=Math.floor(y/ts.tileh); 136 if ((ty<0)||(ty>=map[mapid].length)) return ifout; else 137 if ((tx<0)||(tx>=map[mapid][ty].length)) return ifout; else 138 return map[mapid][ty][tx]; 139 }, 140 141 /** 142 * Takes an ascii-art-style array of characters and converts it to an Akihabara-compatible map format. 143 * @param {Array} map An array of characters representing a map. 144 * @param {Array} tra A translation array. This is an array of arrays, formatted like [ [null, char1], [0, char2], [1, char3] ]. There must at least be a null entry, followed by one numerical entry for each tile type you want to render, corresponding to the unique characters in the map array. The null entry maps a character to empty space. 145 * @returns A map array formatted such that it can be attached to a map object. 146 */ 147 asciiArtToMap:function(map,tra) { 148 var sz=tra[0][1].length; 149 var ret=[]; 150 var xpos; 151 var pie; 152 for (var y=0;y<map.length;y++) { 153 var row=[]; 154 xpos=0; 155 while (xpos<map[y].length) { 156 pie=map[y].substr(xpos,sz); 157 for (var t=0;t<tra.length;t++) 158 if (pie==tra[t][1]) { 159 if (t==0) row.push(null); else row.push(tra[t][0]); 160 break; 161 } 162 xpos+=sz; 163 } 164 ret.push(row); 165 } 166 return ret; 167 }, 168 169 /** 170 * Calculates and sets the width and height (map.h, map.w) and half-width and half-height (map.hh, map.hw) of a map object. 171 * @param {Object} map A map object, containing a map array and a tileset array. 172 * @returns A map object with map.w, map.h, map.hh, and map.hw set correctly. 173 */ 174 // Finalize a map definition, setting height and width in pixels etc. 175 // Args: (map) 176 // Outs: finalized map 177 finalizeTilemap:function(map) { 178 var ts=gbox._tiles[map.tileset]; 179 map.h=map.map.length*ts.tileh; 180 map.w=map.map[0].length*ts.tilew; 181 map.hw=Math.floor(map.w/2); 182 map.hh=Math.floor(map.h/2); 183 return map; 184 }, 185 186 /** 187 * Converts an x-coordinate of a pixel to its corresponding tile x-coordinate. 188 * @param {Object} map A map object, containing a map array and a tileset array. 189 * @param {Integer} x An x-coordinate. 190 * @param {Integer} gap (Not used.) 191 * @returns A map object with map.w, map.h, map.hh, and map.hw set correctly. 192 */ 193 xPixelToTileX:function(map,x,gap) { 194 var ts=gbox._tiles[map.tileset]; 195 return Math.floor(x/ts.tilew); 196 }, 197 198 /** 199 * Converts a y-coordinate of a pixel to its corresponding tile y-coordinate. 200 * @param {Object} map A map object, containing a map array and a tileset array. 201 * @param {Integer} y A y-coordinate. 202 * @param {Integer} gap (Not used.) 203 * @returns A map object with map.w, map.h, map.hh, and map.hw set correctly. 204 */ 205 yPixelToTileY:function(map,y,gap) { 206 var ts=gbox._tiles[map.tileset]; 207 return Math.floor(y/ts.tileh); 208 }, 209 210 /** 211 * Converts an x-coordinate of a pixel to the x-coordinate of the tile column it's in. This effectively "snaps" an x coordinate to a tile edge. 212 * @param {Object} map A map object, containing a map array and a tileset array. 213 * @param {Integer} x An x-coordinate. 214 * @param {Integer} gap Number of pixels gap in tilemap. Default is 0. 215 * @returns The x-coordinate in pixels of the tile column. 216 */ 217 xPixelToTile:function(map,x,gap) { 218 var ts=gbox._tiles[map.tileset]; 219 return (Math.floor(x/ts.tilew)+(gap?gap:0))*ts.tilew; 220 }, 221 222 /** 223 * Converts a y-coordinate of a pixel to the y-coordinate of the tile row it's in. This effectively "snaps" a y coordinate to a tile edge. 224 * @param {Object} map A map object, containing a map array and a tileset array. 225 * @param {Integer} y A y-coordinate. 226 * @param {Integer} gap Number of pixels gap in tilemap. Default is 0. 227 * @returns The y-coordinate in pixels of the tile row. 228 */ 229 yPixelToTile:function(map,y,gap) { 230 var ts=gbox._tiles[map.tileset]; 231 return (Math.floor(y/ts.tileh)+(gap?gap:0))*ts.tileh; 232 }, 233 234 /** 235 * Limits a number to a certain range. If the number is below the minimum, the minimum is returned. If the number is above the maximum, the maximum is returned. 236 * @param {Float} v A value. 237 * @param {Float} min The minimum limit. 238 * @param {Float} max The maximum limit. 239 * @returns A value equal to v if min<v<max. Returns min if v<min, max if v>max. 240 */ 241 limit:function(v,min,max) { 242 if (v<min) return min; else if (v>max) return max; else return v; 243 }, 244 245 /** 246 * Subtracts or adds 1 to a value, always converging to zero. For example, passing -3 yields -2, 5 yields 4, etc. Works best with integers. 247 * @param {Integer} v A value. 248 * @returns A value that is one closer to 0 on the number line than v. 249 */ 250 goToZero:function(v) { return (v?v-(v/Math.abs(v)):0); }, 251 252 /** 253 * Merges two sets of parameters together without overwriting existing parameters. This merges from model to data, and if data and model share parameters, data's values remain intact. 254 * @param {Object} data An object containing a set of parameters, the destination of the merge. 255 * @param {Object} model An object containing a set of parameters, the source of the merge. 256 * @returns A merged model where the values of 'data' remain untouched: only new parameters and values from 'model' make it in. 257 * @example 258 * dst = {a: 1, b: 2, c: "three"}; 259 * src = {c: "three", d: "four"}; 260 * merged = help.mergeWithModel(dst,src); 261 * merged; // => {a: 1, b: 2, c: 3, d: "four"}; 262 */ 263 mergeWithModel:function(data,model) { 264 if (data==null) data={}; 265 if (model!=null) 266 for (var i in model) 267 if (data[i]==null) data[i]=model[i]; 268 return data; 269 }, 270 271 /** 272 * Merges two sets of parameters together overwriting any existing parameters. This merges model->data, and if data and model share parameters, data's are overwritten by model's. 273 * @param {Object} data An object containing a set of parameters, the destination of the merge. 274 * @param {Object} model An object containing a set of parameters, the source of the merge. 275 * @returns A merged model where the values of 'model' take precedence over those of 'data'. The 'data' object is returned and will be an exact copy of 'model', plus any parameters that 'data' had before the merge that 'model' did not. 276 * @example 277 * dst = {a: 1, b: 2, c: "three"}; 278 * src = {c: "three", d: "four"}; 279 * merged = help.mergeWithModel(dst,src); 280 * merged; // => {a: 1, b: 2, c: "three", d: "four"} 281 */ 282 copyModel:function(data,model) { 283 if (data==null) data={}; 284 if (model!=null) 285 for (var i in model) data[i]=model[i]; 286 return data; 287 }, 288 289 /** 290 * Creates a subset of an existing set of parameters. 291 * @param {Object} obj An object containing a set of parameters, the source of the data. 292 * @param {Array} attrs An array of strings, containing the names of parameters you wish to copy. 293 * @returns A new set of parameters based on the subset specified. 294 * @example 295 * data = {a: 1, b: 2, c: "three"}; 296 * newdata = help.createModel(data, ["a", "c"]); 297 * newdata; // => {a: 1, c: "three"} 298 */ 299 createModel:function(obj,attrs) { 300 var ret={}; 301 for (var i=0;i<attrs.length;i++) ret[attrs[i]]=obj[attrs[i]]; 302 return ret; 303 }, 304 305 /** 306 * Creates a duplicate of an existing set of parameters. 307 * @param {Object} model An object containing a set of parameters. 308 * @returns A new object, equivalent to 'model'. 309 * @example 310 * data = {a: 1, b: 2, c: "three"}; 311 * newdata = help.cloneObject(data); 312 * newdata; // => {a: 1, b: 2, c: "three"} 313 */ 314 cloneObject:function(model) { 315 if (!model) return model; 316 var data={}; 317 for (var i in model) data[i]=model[i]; 318 return data; 319 }, 320 321 /** 322 * Sets a tile in the map and draws it. Does not return anything. 323 * @param {Object} ctx The canvas context for the map. Accessed via gbox.getCanvasContext("canvasname") 324 * @param {Object} map The game map object. 325 * @param {Integer} x The index of the tile column within the map array -- so a 1 would mean the second column of tiles. 326 * @param {Integer} y The index of the tile row within the map array -- so a 1 would mean the second row of tiles. 327 * @param {Integer} tile The integer representing the new tile you wish to draw. This is its index within the tileset; a null value will erase whatever tile is present. 328 * @param {String} The ID of the map. Defaults to 'map'. 329 * @example 330 * // Remove the second tile to the right and down from the upper left corner of the tile map. Assumes our map canvas is called 'map_canvas'. 331 * help.setTileInMap(gbox.getCanvasContext("map_canvas"),map,1,1,null,"map"); 332 */ 333 setTileInMap:function(ctx,tilemap,x,y,tile,map) { 334 var ts=gbox.getTiles(tilemap.tileset); 335 tilemap[(map==null?"map":map)][y][x]=tile; 336 if (tile==null) 337 gbox.blitClear(ctx,{x:x*ts.tilew,y:y*ts.tilew,h:ts.tileh,w:ts.tilew}); 338 else 339 gbox.blitTile(ctx,{tileset:tilemap.tileset,tile:tile,dx:x*ts.tilew,dy:y*ts.tilew}); 340 }, 341 342 343 /** 344 * Returns the Nth element in an array. If the array is shorter than N, it returns the last element of the array. 345 * @param {Array} a An array. 346 * @param {Integer} id An index to the array. 347 * @returns If id > a.length, it returns a[a.length-1]. Otherwise returns a[id]. 348 */ 349 getArrayCapped:function(a,id) { 350 if (id>=a.length) return a[a.length-1]; else return a[id]; 351 }, 352 353 // Get an item of an array of object, using a field as index. is returned the first entry if the field is not valued. 354 getArrayIndexed:function(a,value,field) { 355 if (a[0][field]==null) return a[0]; 356 var i=0; 357 while ((value>a[i][field])&&(i!=a.length-1)) i++; 358 return a[i]; 359 }, 360 361 362 /** 363 * Converts a quantity of frames into a timestamp formatted "mm:ss:cs" (minutes, seconds, centiseconds). Calculated using the current frames per second. 364 * @param {Integer} frames A quantity of frames. 365 * @returns A string containing a timestamp formatted "mm:ss:cs", representing the length of time it would take to render that many frames. 366 * @example 367 * // Assuming 25 frames per second, Akihabara's default. 368 * timestamp = help.framestotime(25); 369 * timestamp; // => '00:01:00'; 370 * timestamp = help.framestotime(25 * 60); 371 * timestamp; // => '01:00:00'; 372 */ 373 framestotime:function(frames) { 374 var csec=Math.ceil(frames/gbox.getFps()*100); 375 return this.prepad((Math.floor(csec/6000)%60),2,"0")+":"+this.prepad((Math.floor(csec/100)%60),2,"0")+":"+this.prepad(csec%100,2,"0"); 376 377 }, 378 379 /** 380 * Reads the value of a query parameter from the URL of the web page. 381 * @param {String} name The name of the URL parameter. 382 * @returns The value of the URL parameter, as a string. 383 * @example 384 * // If the URL is http://example.com/game.html?lives=3 385 * player.lives = help.geturlparameter("lives"); 386 * player.lives; // => 3 387 */ 388 geturlparameter:function( name ) { 389 name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]"); 390 var regexS = "[\\?&]"+name+"=([^]*)"; 391 var regex = new RegExp( regexS ); 392 var results = regex.exec( window.location.href ); 393 if( results == null ) 394 return ""; 395 else 396 return results[1]; 397 }, 398 399 /** 400 * Writes the contents of an object to a string. Useful for debugging. 401 * @param {Object} Any object. 402 * @returns A string containing all the contents of an object. If the object contains functions, the string will contain the code for those functions. 403 */ 404 objToStr:function(o) { 405 var ret=""; 406 for (var n in o) ret+=n+":["+o[n]+"] "; 407 return ret; 408 }, 409 410 /** 411 * Tests whether an object contains a given parameter. 412 * @param {Object} A reference to a parameter of an object. 413 * @returns True if the object contains that parameter, false if it does not. 414 * @example 415 * foo = {a: 1, b: 2}; 416 * help.isDefined(foo.a); // => true 417 * help.isDefined(foo.c); // => false 418 */ 419 isDefined:function(v) { 420 return ((typeof(v) !== 'undefined') || (v===null)); 421 }, 422 423 /** 424 * Automatically configures a bunch of settings depending on the web browser and device that is viewing the game. Mostly sets the maximum number of audio channels and touch settings. 425 */ 426 getDeviceConfig:function() { 427 428 var cap; 429 if (navigator.userAgent.match(/iPhone/i)||navigator.userAgent.match(/iPod/i) || navigator.userAgent.match(/Android/i)) 430 cap={touch:true,width:320}; 431 else if (navigator.userAgent.match(/iPad/i)) 432 cap={touch:true,width:768,forcedidle:10}; // Forced idle time is needed for correct framerate calculation. 433 else 434 cap={zoom:2}; 435 436 cap.canaudio=!!(document.createElement('audio').canPlayType); 437 438 if (cap.canaudio) { 439 if (navigator.userAgent.match(/iPad/i)||navigator.userAgent.match(/iPhone/i)||navigator.userAgent.match(/iPod/i)) { 440 cap.audiocompatmode=2; // Single audio per time, so compatibility mode is needed. Plays only the "bgmusic" channel. 441 cap.audioteam=1; // Only a member is required in the audioteam. 442 cap.audioisexperimental=true; // Audio is experimental, since limited. 443 } else if (navigator.userAgent.match(/Chrome/i)) { 444 cap.audioteam=3; // Quite low performance on playback responsiveness. 445 } else if (navigator.userAgent.match(/Firefox/i)) { 446 cap.audioteam=1; // Testing smaller audioteam 447 cap.audiopositiondelay=0.3; // Ogg playback is slower 0.3 between MP3 playback. Don't know why :) 448 cap.audiocreatemode=1; // Firefox is stalling while downloading lot of things 449 } else if (navigator.userAgent.match(/Minefield/i)) { 450 cap.audioteam=1; // Testing smaller audioteam 451 cap.audiocreatemode=1; // Firefox is stalling while downloading lot of things 452 // Minefield has fixed the 0.3 delay! 453 } else if (navigator.userAgent.match(/Safari/i)) { 454 cap.audioteam=1; // Testing smaller audioteam 455 } else if (navigator.userAgent.match(/Opera/i)) { 456 cap.audioteam=1; // Testing smaller audioteam 457 cap.audiocreatemode=1; // Do not like audio object cloning very much 458 } else 459 cap.audioisexperimental=true; // Audio is just experimental on all other devices. 460 461 } 462 463 return cap; 464 }, 465 466 /** 467 * This provides a number of configurations: fps, display zoom, dynamic frameskip, force touch parameters, etc. Many of these settings can 468 * be set manually by passing an object with the parameters defined, or via URL parameters. 469 * @param {Object} data An optional object containing parameters you wish to set. Works for data.zoom, data.splash, data.width, data.height, data.title, data.fps, and data.padmode. 470 */ 471 akihabaraInit:function(data) { 472 if ((typeof data).toLowerCase() == "string") data={title:data}; 473 var device=this.getDeviceConfig(); 474 var footnotes=["MADE WITH AKIHABARA (C)2010 - GPL2/MIT","Project: www.kesiev.com/akihabara","Sources: github.com/kesiev/akihabara"]; 475 document.title=(data.title?data.title:"Akihabara"); 476 if (data.splash) { 477 if (data.splash.footnotes) 478 for (var i=0;i<footnotes.length;i++) data.splash.footnotes.push(footnotes[i]); 479 gbox.setSplashSettings(data.splash); 480 } 481 var screenwidth=(data.width?data.width:(data.portrait?240:320)); 482 var screenheight=(data.height?data.height:(data.portrait?320:240)); 483 if (!data.splash||(data.splash.minilogo==null)) gbox.setSplashSettings({minilogo:"logo"}); 484 if (!data.splash||(data.splash.background==null)) gbox.setSplashSettings({background:"akihabara/splash.png"}); 485 if (!data.splash||(data.splash.minimalTime==null)) gbox.setSplashSettings({minimalTime:3000}); 486 if (!data.splash||(data.splash.footnotes==null)) gbox.setSplashSettings({footnotes:footnotes}); 487 document.body.style.backgroundColor="#000000"; 488 gbox.setScreenBorder(false); 489 if (help.geturlparameter("statusbar")) gbox.setStatusBar(1); 490 if (help.geturlparameter("db")) gbox.setDoubleBuffering(true); 491 if (help.geturlparameter("noautoskip")) gbox.setAutoskip(null); 492 if (help.geturlparameter("zoom")) gbox.setZoom(help.geturlparameter("zoom")); else 493 if (help.isDefined(data.zoom)) gbox.setZoom(data.zoom); else 494 if (help.isDefined(device.zoom)) gbox.setZoom(device.zoom); else 495 if (help.isDefined(device.width)) gbox.setZoom(device.width/screenwidth); 496 if (help.geturlparameter("fps")) gbox.setFps(help.geturlparameter("fps")*1); 497 else gbox.setFps((data.fps?data.fps:25)); 498 if (help.geturlparameter("fskip")) gbox.setFrameskip(help.geturlparameter("fskip")); 499 if (help.geturlparameter("forcedidle")) gbox.setForcedIdle(help.geturlparameter("forcedidle")*1); 500 else if (help.isDefined(device.forcedidle)) gbox.setForcedIdle(device.forcedidle); 501 if (help.geturlparameter("canlog")) gbox.setCanLog(true); 502 503 gbox.initScreen(screenwidth,screenheight); 504 505 if (help.geturlparameter("showplayers")) gbox.setShowPlayers(help.geturlparameter("showplayers")=="yes"); 506 if (help.geturlparameter("canaudio")) gbox.setCanAudio(help.geturlparameter("canaudio")=="yes"); else 507 gbox.setCanAudio(device.canaudio&&(!device.audioisexperimental||gbox.getFlag("experimental"))); 508 if (help.geturlparameter("audiocompatmode")) gbox.setAudioCompatMode(help.geturlparameter("audiocompatmode")*1); else 509 if (help.isDefined(device.audiocompatmode)) gbox.setAudioCompatMode(device.audiocompatmode); 510 if (help.geturlparameter("audioteam")) gbox.setAudioTeam(help.geturlparameter("audioteam")*1); else 511 if (help.isDefined(device.audioteam)) gbox.setAudioTeam(device.audioteam); 512 if (help.geturlparameter("loweraudioteam")) gbox.setLowerAudioTeam(help.geturlparameter("loweraudioteam")*1); else 513 if (help.isDefined(device.loweraudioteam)) gbox.setLowerAudioTeam(device.loweraudioteam); 514 if (help.geturlparameter("audiocreatemode")) gbox.setAudioCreateMode(help.geturlparameter("audiocreatemode")*1); else 515 if (help.isDefined(device.audiocreatemode)) gbox.setAudioCreateMode(device.audiocreatemode); 516 if (help.geturlparameter("audiodequeuetime")) gbox.setAudioDequeueTime(help.geturlparameter("audiodequeuetime")*1); else 517 if (help.isDefined(device.audiodequeuetime)) gbox.setAudioDequeueTime(device.audiodequeuetime); 518 if (help.geturlparameter("audiopositiondelay")) gbox.setAudioPositionDelay(help.geturlparameter("audiopositiondelay")*1); else 519 if (help.isDefined(device.audiopositiondelay)) gbox.setAudioPositionDelay(device.audiopositiondelay); 520 521 522 523 if (help.geturlparameter("touch")=="no"); 524 else if ((help.geturlparameter("touch")=="yes")||device.touch) 525 switch (data.padmode) { 526 case "fretboard": { 527 iphofretboard.initialize({h:100,bg:"akihabara/fretboard.png"}); 528 break; 529 } 530 case "none": { 531 break; 532 } 533 default: { 534 iphopad.initialize({h:100,dpad:"akihabara/dpad.png",buttons:"akihabara/buttons.png",bg:"akihabara/padbg.png"}); 535 break; 536 } 537 } 538 } 539 } 540