1 // --- 2 // Copyright (c) 2010 Francesco Cottone, http://www.kesiev.com/ 3 // --- 4 5 /** 6 * @namespace 7 * Toys module provides lots of common routines during the game developing: 8 * from effects for screen titles to HUD handling to platform/SHMUP/RPG oriented routines, 9 * like jumping characters, Z-Indexed objects, bullets, sparks, staff rolls, bonus screens, dialogues etc. 10 */ 11 var toys={ 12 13 // CONSTANTS 14 NOOP:function(){}, 15 PUSH_NONE:0, 16 PUSH_LEFT:1, 17 PUSH_RIGHT:2, 18 PUSH_UP:3, 19 PUSH_DOWN:4, 20 21 FACES:["up","right","down","left"], 22 FACES_ANGLE:[trigo.ANGLE_UP,trigo.ANGLE_RIGHT,trigo.ANGLE_DOWN,trigo.ANGLE_LEFT], 23 FACE_UP:0, 24 FACE_RIGHT:1, 25 FACE_DOWN:2, 26 FACE_LEFT:3, 27 28 /** 29 * @namespace 30 * Top-view RPG specific libraries. 31 */ 32 topview:{ 33 34 /** 35 * Checks if an object checks that both objects are on the same Z plane and if so it calls gbox.collides. 36 * @param {Object} fr The object which collision is being checked for. 37 * <ul> 38 * <li>x{Integer}: (required)Objects x position</li> 39 * <li>y{Integer}: (required)Objects y position</li> 40 * <li>z{Integer}: (required)Objects z position</li> 41 * <li>colx{Integer}: (required)The dimension of the collision box along the x axis</li> 42 * <li>coly{Integer}: (required)The dimension of the collision box along the y axis</li> 43 * <li>colh{Integer}: (required)Collision box height</li> 44 * <li>colw{Integer}: (required)Collision box width</li> 45 * </ul> 46 * @param {Object} to The object that collision is being checked against. 47 * <ul> 48 * <li>x{Integer}: (required)Objects x position</li> 49 * <li>y{Integer}: (required)Objects y position</li> 50 * <li>z{Integer}: (required)Objects z position</li> 51 * <li>colx{Integer}: (required)Collision x</li> 52 * <li>coly{Integer}: (required)Collision y</li> 53 * <li>colh{Integer}: (required)Collision box height</li> 54 * <li>colw{Integer}: (required)Collision box width</li> 55 * </ul> 56 * @param {int} t This is the tollerance (or margin for error) on the collide function. 57 */ 58 collides:function(fr,to,t) { // Special collision. Counts also the Z 59 if (Math.abs(fr.z,to.z)<5) return gbox.collides({x:fr.x+fr.colx,y:fr.y+fr.coly,h:fr.colh,w:fr.colw},{x:to.x+to.colx,y:to.y+to.coly,h:to.colh,w:to.colw},t); else return false; 60 }, 61 62 /** 63 * Checks for pixel collisions with an offset to the X and Y of the colidable using colx and coly. 64 * @param {Object} fr The object which collision is being tested for. 65 * @param {Object} to The object (or point) which collision is being tested against. 66 * @param {int} t The tollerance of the collision algorithm. 67 */ 68 pixelcollides:function(fr,to,t) { // Special collision. Counts also the Z 69 return gbox.pixelcollides(fr,{x:to.x+to.colx,y:to.y+to.coly,h:to.colh,w:to.colw},t); 70 }, 71 72 /** 73 * Initializes the game with the variables needed for topview and whatever else you feed in through data. 74 * @param {Object} th Passes in the object being initialized. 75 * @param {Object} data This is used to pass in everything that's being initiliized. If a value is not in Data then a default value is used instead. This can pass in values which do not have a default. 76 * <ul> 77 * <li>x{Integer}: x position of the object. (defaults to 0)</li> 78 * <li>y{Integer}: y position of the object. (defaults to 0)</li> 79 * <li>z{Integer}: z index of the object. (defaults to 0)</li> 80 * <li>accx{Integer}: The starting x velociyt of the object. (defaults to 0)</li> 81 * <li>accy{Integer}: The starting y velocity of the object. (defaults to 0)</li> 82 * <li>accz{Integer}: The starting z velocity of the object. (defaults to 0)</li> 83 * <li>frames{Object}: This is stores the animation frames for the objects in a map style structure. An empty map means the default image will display with no animation frames. (defaults to an empty map)</li> 84 * <li>shadow: (defaults to null)</li> //incomplete 85 * <li>maxacc{Integer}: (defaults to )4</li> 86 * <li>controlmaxacc{Integer}: (defaults to 4)</li> 87 * <li>responsive: (defaults to 0)</li> 88 * <li>weapon: (defaults to 0)</li> 89 * <li>camera{Boolean}: (defaults to true)</li> 90 * <li>flipv{Boolean}: Notes if the object is flipped vertically(defaults to false)</li> 91 * <li>fliph{Boolean}: Notes if the object is flipped horrizontally(defaults to false)</li> 92 * <li>facing{Integer}: Stores the facing of the object. This is set with pre-defined Integer values from within Toys.(defaults to toys.FACE_DOWN)</li> 93 * <ul> 94 * <li>FACE_UP:0,</li> 95 * <li>FACE_RIGHT:1,</li> 96 * <li>FACE_DOWN:2,</li> 97 * <li>FACE_LEFT:3,</li> 98 * </ul> 99 * <li>flipside{Boolean}: (defaults to true)</li> 100 * <li>haspushing{Boolean}: (defaults to false)</li> 101 * <li>frame: (default to 0)</li> 102 * <li>colh{Integer}: (defaults to gbox.getTiles(th.tileset).tilehh)</li> 103 * <li>colw{Integer}: (defaults to gbox.getTiles(th.tileset).tilew)</li> 104 * <li>colx{Integer}: (defaults to 0)</li> 105 * <li>staticspeed{Integer}: (defaults to 0)</li> 106 * <li>nodiagonals{Boolean}: (defaults to false)</li> 107 * <li>noreset: (defaults to false)</li> 108 * </ul> 109 */ 110 initialize:function(th,data) { 111 help.mergeWithModel( 112 th, 113 help.mergeWithModel( 114 data, 115 { 116 x:0, y:0, 117 z:0, 118 accx:0, accy:0, accz:0, 119 frames:{}, 120 shadow:null, 121 maxacc:4, controlmaxacc:4, 122 responsive:0, // Responsiveness 123 weapon:0, // Weapon 124 camera:true, 125 flipv:false, fliph:false, 126 facing:toys.FACE_DOWN, 127 flipside:true, 128 haspushing:false, 129 frame:0, 130 colh:gbox.getTiles(th.tileset).tilehh, 131 colw:gbox.getTiles(th.tileset).tilew, 132 colx:0, 133 staticspeed:0, 134 nodiagonals:false, 135 noreset:false 136 } 137 ) 138 ); 139 if (th.coly==null) th.coly=gbox.getTiles(th.tileset).tileh-th.colh; 140 th.colhh=Math.floor(th.colh/2); 141 th.colhw=Math.floor(th.colw/2); 142 143 toys.topview.spawn(th); 144 }, 145 146 /** 147 * "Spawns" a new object in the topview namespace. This also merges parameters in data into paramaters in th using help.copyModel. 148 * This initializes some basic basic variables for the object and sets the Z index. 149 * @param {Object} th References "this" which is the object that called the method (generally). 150 * <ul> 151 * <li>y {Integer}: (required)The object's y position.</li> 152 * <li>h {Integer}: (required)The object's height.</li> 153 * </ul> 154 * @param {Object} data This holds variables to be merged into th's stored info. 155 */ 156 spawn:function(th,data) { 157 th.xpushing=toys.PUSH_NONE; // user is moving side 158 th.vpushing=toys.PUSH_NONE; // user is moving side 159 th.zpushing=toys.PUSH_NONE; // user is moving side 160 th.counter=0; // self counter 161 th.hittimer=0; 162 th.killed=false; 163 help.copyModel(th,data); 164 gbox.setZindex(th,th.y+th.h); // these object follows the z-index and uses ZINDEX_LAYER 165 }, 166 167 /** 168 * This sets and runs the control keys for the game. 169 * @param {Object} th This is the object that is being controlled by the keys (assumed to be the player) 170 * <ul> 171 * <li>accx: the object's currect acceleration in the x direction</li> 172 * <li>accy: the object's currect acceleration in the y direction</li> 173 * <li>responsive: minimum movement speed</li> 174 * <li>staticspeed: turns off acceleration</li> 175 * <li>nodiagonals: boolean determining if the object can move along both axis at once.</li> 176 * <li>xpushing: a boolean that notes whether the object is pushing against something in the x direction.</li> 177 * <li>ypushing: a boolean that notes whether the object is pushing against something in the y direction.</li> 178 * <li>controlmaxacc: max acceleration for the object along an axis</li> 179 * <li>noreset: checks for the object being allowed to reset its pushing status (?)</li> 180 * </ul> 181 * @param {Object} keys These are the control keys being passed in for left, right, up, and down. 182 * //incomplete 183 */ 184 controlKeys:function(th,keys) { 185 var cancelx=false; 186 var cancely=false; 187 var idlex=false; 188 var idley=false; 189 190 if (gbox.keyIsPressed(keys.left)||keys.pressleft) { 191 th.xpushing=toys.PUSH_LEFT; 192 th.facing=toys.FACE_LEFT; 193 if (th.accx>th.responsive) th.accx=th.responsive; 194 if (th.staticspeed) th.accx=-th.staticspeed; else th.accx=help.limit(th.accx-1,-th.controlmaxacc,th.controlmaxacc); 195 if (th.nodiagonals) { cancely=true; idley=true } 196 } else if (gbox.keyIsPressed(keys.right)||keys.pressright) { 197 th.xpushing=toys.PUSH_RIGHT; 198 th.facing=toys.FACE_RIGHT; 199 if (th.accx<-th.responsive) th.accx=-th.responsive; 200 if (th.staticspeed) th.accx=th.staticspeed; else th.accx=help.limit(th.accx+1,-th.controlmaxacc,th.controlmaxacc); 201 if (th.nodiagonals) { cancely=true; idley=true } 202 } else idlex=true; 203 204 if (!cancely&&(gbox.keyIsPressed(keys.up)||keys.pressup)) { 205 th.ypushing=toys.PUSH_UP; 206 th.facing=toys.FACE_UP; 207 if (th.accy>th.responsive) th.accy=th.responsive; 208 if (th.staticspeed) th.accy=-th.staticspeed; else th.accy=help.limit(th.accy-1,-th.controlmaxacc,th.controlmaxacc); 209 if (th.nodiagonals) { cancelx=true; idlex=true; } 210 } else if (!cancely&&(gbox.keyIsPressed(keys.down)||keys.pressdown)) { 211 th.ypushing=toys.PUSH_DOWN; 212 th.facing=toys.FACE_DOWN; 213 if (th.accy<-th.responsive) th.accy=-th.responsive; 214 if (th.staticspeed) th.accy=th.staticspeed; else th.accy=help.limit(th.accy+1,-th.controlmaxacc,th.controlmaxacc); 215 if (th.nodiagonals) { cancelx=true; idlex=true; } 216 } else idley=true; 217 218 219 220 if (idlex) { 221 if (cancelx) th.accx=0; 222 if (cancelx||!th.noreset) th.xpushing=toys.PUSH_NONE; 223 } 224 if (idley) { 225 if (cancely) th.accy=0; 226 if (cancely||!th.noreset) th.ypushing=toys.PUSH_NONE; 227 } 228 }, 229 230 /** 231 * Gets the next X position the object is going to move to. 232 * @param {Object} th The object being checked. 233 * <ul> 234 * <li>x: the current x position of the object</li> 235 * <li>accx: the object's currect acceleration in the x direction</li> 236 * <li>maxacc: the max accleration the object can have (if accx is greater than this then this value is used instead)</li> 237 * </ul> 238 */ 239 getNextX:function(th) { return th.x+help.limit(th.accx,-th.maxacc,th.maxacc); }, 240 241 /** 242 * Gets the next Y position the object is going to move to. 243 * @param {Object} th The object being checked. 244 * <ul> 245 * <li>y: the current y position of the object</li> 246 * <li>accy: the object's currect acceleration in the y direction</li> 247 * <li>maxacc: the max accleration the object can have (if accy is greater than this then this value is used instead)</li> 248 * </ul> 249 */ 250 getNextY:function(th) { return th.y+help.limit(th.accy,-th.maxacc,th.maxacc); }, 251 252 /** 253 * Gets the next Z position the object is going to move to. 254 * @param {Object} th The object being checked. 255 * <ul> 256 * <li>z: the current z position of the object</li> 257 * <li>accz: the object's currect acceleration in the z direction</li> 258 * <li>maxacc: the max accleration the object can have (if accz is greater than this then this value is used instead)</li> 259 * </ul> 260 */ 261 getNextZ:function(th) { return th.z+help.limit(th.accz,-th.maxacc,th.maxacc); }, 262 263 /** 264 * Sets the objects current location to its next location using the getNextX and getNextY methods. 265 * @param {Object} th The object being modified. 266 * <ul> 267 * <li>x: the current x position of the object</li> 268 * <li>y: the current y position of the object</li> 269 * <li>accx: the object's currect acceleration in the x direction</li> 270 * <li>accy: the object's currect acceleration in the y direction</li> 271 * <li>maxacc: the max accleration the object can have (if either acceleration is greater than this then this value is used instead for that acceleration)</li> 272 * </ul> 273 */ 274 applyForces:function(th) { 275 th.x=toys.topview.getNextX(th); 276 th.y=toys.topview.getNextY(th); 277 }, 278 279 /** 280 * This applies acceleration in the Z direction (not nessesarily gravity but whatever the next accerlation on the Z axis is) 281 * @param {Object} th The object being modified. 282 * <ul> 283 * <li>z: the current z position of the object</li> 284 * <li>accz: the object's currect acceleration in the z direction</li> 285 * <li>maxacc: the max accleration the object can have (if accz is greater than this then this value is used instead)</li> 286 * </ul> 287 */ 288 applyGravity:function(th) { 289 th.z=toys.topview.getNextZ(th); 290 }, 291 292 /** 293 * Degrades all accelerations on an object by one toward zero. 294 * @param {Object} th The object being modified. 295 * <ul> 296 * <li>xpushing: a boolean that notes whether the object is pushing against something in the x direction.</li> 297 * <li>ypushing: a boolean that notes whether the object is pushing against something in the y direction.</li> 298 * <li>accx: the object's currect acceleration in the x direction</li> 299 * <li>accy: the object's currect acceleration in the y direction</li> 300 * </ul> 301 */ 302 handleAccellerations:function(th) { 303 if (!th.xpushing) th.accx=help.goToZero(th.accx); 304 if (!th.ypushing) th.accy=help.goToZero(th.accy); 305 306 }, 307 308 /** 309 * Increases the Z acceleration on the object by one. 310 * @param {Object} th The object being modified. 311 * <ul> 312 * <li>accz: the acceleration on the Z axis</li> 313 * </ul> 314 */ 315 handleGravity:function(th) { 316 th.accz++; 317 }, 318 319 /** 320 * This sets which frame the object is going to display based on an agregate word that describes predefined states. 321 * @param {Object} th The object whose frame is being set. 322 * <ul> 323 * <li>xpushing: a boolean that notes whether the object is pushing against something in the x direction.</li> 324 * <li>ypushing: a boolean that notes whether the object is pushing against something in the y direction.</li> 325 * <li>haspushing: a boolean that notes if the object changes when pushing against something.</li> 326 * <li>toucheddown: a boolean that notes if the object is touching something below it on the screen.</li> 327 * <li>touchedup: a boolean that notes if the object is touching something above it on the screen.<</li> 328 * <li>touchedright: a boolean that notes if the object is touching something right of it on the screen.<</li> 329 * <li>touchedleft: a boolean that notes if the object is touching something left of it on the screen.<</li> 330 * <li>flipside: </li> 331 * <li>fliph: </li> 332 * <li>facing: </li> 333 * <li>frames: </li> 334 * <li>frame: </li> 335 * <li>counter: </li> 336 * </ul> 337 * // incomplete 338 */ 339 setFrame:function(th) { 340 var pref="stand"; 341 if (th.xpushing||th.ypushing) 342 if (th.haspushing&&(th.toucheddown||th.touchedup||th.touchedleft||th.touchedright)) pref="pushing"; else pref="moving"; 343 if (th.flipside) 344 th.fliph=(th.facing==toys.FACE_RIGHT); 345 th.frame=help.decideFrame(th.counter,th.frames[pref+toys.FACES[th.facing]]); 346 }, 347 348 /** 349 * Checks if the specified object is colliding with tiles in the map in an area defined by the object's colw and colh variables as well as the tolerance and approximation variables that are passed in through data. Only tiles in the map marked as solid are checked against. The alogrithm checks the 350 * @param {Object} th The object that is being checked against the tilemap. 351 * @param {Object} map This is the asci map that the tile map is generated from. 352 * @param {Object} tilemap This is the array of tile objects that it itterated over checking for collisions. 353 * @param {Object} defaulttile The default tile to be returned if nothing can be found. Null can be used here. 354 * @param {Object} data Passes is extra dat to the function. Can be set as null. 355 * <ul> 356 * <li>tolerance{Integer}: This is subtracted from the collision space to get the maximum collision area for the object. This defaults to 6.</li> 357 * <li>approximation{Integer}: This is the amount that the checked values are incremented by until they reach the maximum value allowed. This defaults to 10.</li> 358 * </ul> 359 */ 360 tileCollision:function(th,map,tilemap,defaulttile,data) { 361 362 th.touchedup=false; 363 th.toucheddown=false; 364 th.touchedleft=false; 365 th.touchedright=false; 366 367 var tolerance=(data&&(data.tolerance!=null)?data.tolerance:6); 368 var approximation=(data&&(data.approximation!=null)?data.approximation:10); 369 var t=tolerance-approximation; 370 do { 371 t+=approximation; 372 if (t>th.colw-tolerance-1) t=th.colw-tolerance-1; 373 var bottom=help.getTileInMap(th.x+th.colx+t,th.y+th.coly+th.colh-1,map,defaulttile,tilemap); 374 var top=help.getTileInMap(th.x+th.colx+t,th.y+th.coly,map,defaulttile,tilemap); 375 if (map.tileIsSolid(th,top)) th.touchedup=true; 376 if (map.tileIsSolid(th,bottom)) th.toucheddown=true; 377 } while (t!=th.colw-tolerance-1); 378 379 t=tolerance-approximation; 380 do { 381 t+=approximation; 382 if (t>th.colh-tolerance-1) t=th.colh-tolerance-1; 383 var left=help.getTileInMap(th.x+th.colx,th.y+th.coly+t,map,defaulttile,tilemap); 384 var right=help.getTileInMap(th.x+th.colx+th.colw-1,th.y+th.coly+t,map,defaulttile,tilemap); 385 if (map.tileIsSolid(th,left)) th.touchedleft=true; 386 if (map.tileIsSolid(th,right)) th.touchedright=true; 387 } while (t!=th.colh-tolerance-1); 388 389 if (th.touchedup) { 390 th.accy=0; 391 th.y=help.yPixelToTile(map,th.y+th.coly,1)-th.coly; 392 } 393 if (th.toucheddown) { 394 th.accy=0; 395 th.y=help.yPixelToTile(map,th.y+th.coly+th.colh-1)-th.coly-th.colh; 396 } 397 if (th.touchedleft) { 398 th.accx=0; 399 th.x=help.xPixelToTile(map,th.x+th.colx,1)-th.colx; 400 } 401 if (th.touchedright) { 402 th.accx=0; 403 th.x=help.xPixelToTile(map,th.x+th.colx+th.colw-1)-th.colx-th.colw; 404 } 405 406 }, 407 408 /** 409 * @param {Object} th The object being checked for collisions. 410 * <ul> 411 * <li></li> 412 * <li></li> 413 * <li></li> 414 * <li></li> 415 * </ul> 416 * @param {Object} data This is used to pass in other data and arguments. 417 * <ul> 418 * <li>group {String}: (required) This is the group of objects being checked against.</li> 419 * <li></li> 420 * <li></li> 421 * <li></li> 422 * <li></li> 423 * </ul> //incomplete 424 */ 425 spritewallCollision:function(th,data) { 426 var wl; 427 for (var i in gbox._objects[data.group]) 428 if ((!gbox._objects[data.group][i].initialize)&&toys.topview.collides(th,gbox._objects[data.group][i])) { 429 wl=gbox._objects[data.group][i]; 430 if (toys.topview.pixelcollides({x:th.x+th.colx,y:th.y+th.coly+th.colhh},wl)) { 431 th.touchedleft=true; 432 th.accx=0; 433 th.x=wl.x+wl.colx+wl.colw-th.colx; 434 } else if (toys.topview.pixelcollides({x:th.x+th.colx+th.colw,y:th.y+th.coly+th.colhh},wl)) { 435 th.touchedright=true; 436 th.accx=0; 437 th.x=wl.x+wl.colx-th.colw-th.colx; 438 } 439 if (toys.topview.pixelcollides({x:th.x+th.colx+th.colhw,y:th.y+th.coly+th.colh},wl)) { 440 th.toucheddown=true; 441 th.accy=0; 442 th.y=wl.y+wl.coly-th.colh-th.coly; 443 } else if (toys.topview.pixelcollides({x:th.x+th.colx+th.colhw,y:th.y+th.coly},wl)) { 444 th.touchedup=true; 445 th.accy=0; 446 th.y=wl.y+wl.coly+wl.colh-th.coly; 447 } 448 } 449 450 }, 451 452 /** 453 * This checks if the object's z index is 0 which means it has hit the floor. If this has occured it also plays an impact or bounce noise if one is passed in. Note: The area above the floor is in the negative z index space so a value of 1 for z will return that the object has collided with the floor and z will then be set to zero. 454 * @param {Object} th The object being checked for collision. 455 * <ul> 456 * <li>touchedfloor{boolean}: This value is not passed in but is created or set in the function. This contains the function's return value.</li> 457 * <li></li> 458 * <li></li> 459 * <li></li> 460 * </ul> 461 * @param {Object} data This is used to pass in extra parameters. 462 * <ul> 463 * <li></li> 464 * </ul> 465 */ 466 floorCollision:function(th,data) { 467 th.touchedfloor=false; 468 if (th.z>0) { 469 th.accz=(data==null?0:-Math.floor(th.accz/data.bounce)); 470 if (data&&data.audiobounce&&th.accz) gbox.hitAudio(data.audiobounce); 471 th.z=0; 472 th.touchedfloor=true; 473 } 474 }, 475 476 /** 477 * 478 */ 479 adjustZindex:function(th) { 480 gbox.setZindex(th,th.y+th.h); 481 }, 482 483 /** 484 * 485 */ 486 // Helper: returns the ahead pixel (i.e. destination use action) 487 getAheadPixel:function(th,data) { 488 switch (th.facing) { 489 case toys.FACE_RIGHT:{ 490 return {x:th.x+th.colx+th.colw+data.distance,y:th.y+th.coly+th.colhh}; 491 break; 492 } 493 case toys.FACE_LEFT:{ 494 return {x:th.x+th.colx-data.distance,y:th.y+th.coly+th.colhh}; 495 break; 496 } 497 case toys.FACE_UP:{ 498 return {x:th.x+th.colx+th.colhw,y:th.y+th.coly-data.distance}; 499 break; 500 } 501 case toys.FACE_DOWN:{ 502 return {x:th.x+th.colx+th.colhw,y:th.y+th.coly+th.colh+data.distance}; 503 break; 504 } 505 } 506 }, 507 508 /** 509 * 510 */ 511 // Helper: trigger a method in colliding objects (i.e. "use action") 512 callInColliding:function(th,data) { 513 for (var i in gbox._objects[data.group]) 514 if ((!gbox._objects[data.group][i].initialize)&&toys.topview.pixelcollides(data,gbox._objects[data.group][i])) 515 if (gbox._objects[data.group][i][data.call]) { 516 gbox._objects[data.group][i][data.call](th); 517 return i; 518 } 519 return false; 520 }, 521 522 /** 523 * 524 */ 525 // Enemy methods 526 wander:function(th,map,tilemap,defaulttile,data) { 527 if ((!th.wandercounter)||(th.toucheddown||th.touchedup||th.touchedleft||th.touchedright)) { 528 th.wandercounter=help.random(data.minstep,data.steprange); 529 th.wanderdirection=help.random(0,4); 530 } else th.wandercounter--; 531 switch (th.wanderdirection) { 532 case toys.FACE_LEFT: { 533 th.xpushing=toys.PUSH_LEFT; 534 th.ypushing=toys.PUSH_NONE; 535 th.facing=toys.FACE_LEFT; 536 th.accx=-data.speed; 537 th.accy=0; 538 break; 539 } 540 case toys.FACE_RIGHT: { 541 th.xpushing=toys.PUSH_RIGHT; 542 th.ypushing=toys.PUSH_NONE; 543 th.facing=toys.FACE_RIGHT; 544 th.accx=data.speed; 545 th.accy=0; 546 break; 547 } 548 case toys.FACE_UP: { 549 th.ypushing=toys.PUSH_UP; 550 th.xpushing=toys.PUSH_NONE; 551 th.facing=toys.FACE_UP; 552 th.accy=-data.speed; 553 th.accx=0; 554 break; 555 } 556 case toys.FACE_DOWN: { 557 th.ypushing=toys.PUSH_DOWN; 558 th.xpushing=toys.PUSH_NONE; 559 th.facing=toys.FACE_DOWN; 560 th.accy=data.speed; 561 th.accx=0; 562 break; 563 } 564 } 565 }, 566 567 /** 568 * 569 */ 570 // generators (firebullet specific for topdown - more complex than SHMUP one) 571 fireBullet:function(gr,id,data) { 572 573 var ts=gbox.getTiles(data.tileset); 574 575 576 var obj=gbox.addObject( 577 help.mergeWithModel( 578 data,{ 579 _bullet:true, 580 zindex:0, 581 fliph:false, flipv:false, 582 id:id, 583 group:gr, 584 cnt:0, 585 tileset:"", 586 frames:{}, 587 acc:0, 588 angle:0, 589 camera:data.from.camera, 590 accx:(data.accx==null?Math.floor(trigo.translateX(0,data.angle,data.acc)):0), 591 accy:(data.accy==null?Math.floor(trigo.translateY(0,data.angle,data.acc)):0), 592 accz:0, 593 x:(data.sidex==toys.FACE_LEFT?data.from.x-ts.tilehw:(data.sidex==toys.FACE_RIGHT?data.from.x+data.from.w-ts.tilehw:data.from.x+data.from.hw-ts.tilehw))+(data.gapx?data.gapx:0), 594 y:(data.sidey==toys.FACE_UP?data.from.y-ts.tilehh:(data.sidey==toys.FACE_DOWN?data.from.y+data.from.h-ts.tilehh:data.from.y+data.from.hh-ts.tilehh))+(data.gapy?data.gapy:0), 595 z:(data.from.z==null?0:data.from.z), 596 collidegroup:"", 597 spark:toys.NOOP, 598 power:1, 599 lifetime:null, 600 tilemap:null, 601 defaulttile:0, 602 applyzgravity:false, 603 map:null, 604 defaulttile:0, 605 mapindex:"", 606 spritewalls:null, 607 colx:(data.fullhit?0:null), 608 coly:(data.fullhit?0:null), 609 colh:(data.fullhit?ts.tileh:null), 610 colw:(data.fullhit?ts.tilew:null), 611 duration:null, 612 onWallHit:function() { 613 this.spark(this); 614 gbox.trashObject(this); 615 }, 616 bulletIsAlive:function() { 617 return gbox.objectIsVisible(this); 618 } 619 } 620 ) 621 ); 622 623 obj.initialize=function() { 624 toys.topview.initialize(this); 625 }; 626 627 obj[(data.logicon==null?"first":data.logicon)]=function() { 628 this.cnt=(this.cnt+1)%10; 629 630 if (this.applyzgravity) toys.topview.handleGravity(this); // z-gravity 631 toys.topview.applyForces(this); // Apply forces 632 if (this.applyzgravity) toys.topview.applyGravity(this); // z-gravity 633 if (this.map!=null) toys.topview.tileCollision(this,this.map,this.mapindex,this.defaulttile); // tile collisions 634 if (this.spritewalls!=null) toys.topview.spritewallCollision(this,{group:this.spritewalls}); // walls collisions 635 if (this.applyzgravity) toys.topview.floorCollision(this); // Collision with the floor (for z-gravity) 636 toys.topview.adjustZindex(this); 637 if (this.duration!=null) { 638 this.duration--; 639 if (this.duration==0) gbox.trashObject(this); 640 } 641 if (!this.bulletIsAlive()) gbox.trashObject(this); 642 else if (this.toucheddown||this.touchedup||this.touchedleft||this.touchedright) this.onWallHit(); 643 else if (this.collidegroup!=null) 644 for (var i in gbox._objects[this.collidegroup]) 645 if ((!gbox._objects[this.collidegroup][i].initialize)&&toys.topview.collides(this,gbox._objects[this.collidegroup][i],gbox._objects[this.collidegroup][i].tolerance)) { 646 if (gbox._objects[this.collidegroup][i]["hitByBullet"]!=null) 647 if (!gbox._objects[this.collidegroup][i].hitByBullet(this)) { 648 this.spark(this); 649 gbox.trashObject(this); 650 } 651 } 652 } 653 654 obj[(data.bliton==null?"blit":data.bliton)]=function() { 655 if (!gbox.objectIsTrash(this)) 656 gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.cnt,this.frames),dx:this.x,dy:this.y+this.z,camera:this.camera,fliph:this.fliph,flipv:this.flipv}); 657 } 658 659 gbox.setZindex(obj,obj.y+obj.h); 660 661 return obj; 662 663 }, 664 665 /** 666 * 667 */ 668 makedoor:function(gr,id,map,data) { 669 670 var mts=gbox.getTiles(map.tileset); 671 var ts=gbox.getTiles(data.tileset); 672 673 var obj=gbox.addObject( 674 help.mergeWithModel( 675 data,{ 676 zindex:0, 677 fliph:false, flipv:false, 678 id:id, 679 group:gr, 680 cnt:0, 681 tileset:"", 682 frames:{}, 683 camera:true, 684 x:data.tilex*mts.tilew, 685 y:data.tiley*mts.tileh, 686 z:0, 687 tilemap:null, 688 defaulttile:0, 689 map:map, 690 colx:(data.fullhit?0:null), 691 coly:(data.fullhit?0:null), 692 colh:(data.fullhit?ts.tileh:null), 693 colw:(data.fullhit?ts.tilew:null), 694 opening:false, 695 doorheight:ts.tileh, 696 opencounter:0, 697 opening:false, 698 closing:false, 699 audiobefore:null, 700 audioafter:null, 701 doOpen:function() { 702 this.opening=true; 703 }, 704 whenClosed:toys.NOOP, 705 whenOpened:toys.NOOP, 706 whileMoving:toys.NOOP, 707 hitByBullet:function(by) { 708 709 } 710 } 711 ) 712 ); 713 714 // Closing animation 715 if (obj.closing) obj.opencounter=obj.doorheight; 716 717 obj.initialize=function() { 718 this.ismoving=false; 719 toys.topview.initialize(this); 720 }; 721 722 obj[(data.logicon==null?"first":data.logicon)]=function() { 723 if (this.closing) { 724 if (!this.ismoving) { 725 if (this.audiobefore) gbox.hitAudio(this.audiobefore); 726 this.ismoving=true; 727 } 728 this.whileMoving(); 729 this.opencounter--; 730 if (this.opencounter<0) { 731 if (this.audioafter) gbox.hitAudio(this.audioafter); 732 this.ismoving=false; 733 this.opencounter=0; 734 this.closing=false; 735 this.whenClosed(); 736 } 737 } 738 if (this.opening) { 739 if (!this.ismoving) { 740 if (this.audiobefore) gbox.hitAudio(this.audiobefore); 741 this.ismoving=true; 742 } 743 this.whileMoving(); 744 this.opencounter++; 745 if (this.opencounter>=this.doorheight) { 746 if (this.audioafter) gbox.hitAudio(this.audioafter); 747 this.ismoving=false; 748 if (!this.whenOpened()) gbox.trashObject(this); 749 } 750 } 751 } 752 753 obj[(data.bliton==null?"blit":data.bliton)]=function() { 754 if (!gbox.objectIsTrash(this)) 755 gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.cnt,this.frames),dx:this.x,dy:this.y+this.z+this.opencounter,h:this.h-this.opencounter,camera:this.camera,fliph:this.fliph,flipv:this.flipv}); 756 } 757 758 gbox.setZindex(obj,obj.y+obj.h); 759 760 return obj; 761 }, 762 // Set the object speed making sure that the X and Y coords are multiple of the speed. Useful on maze-based games. 763 setStaticSpeed:function(th,speed) { 764 th.staticspeed=speed; 765 th.x=Math.round(th.x/speed)*speed; 766 th.y=Math.round(th.y/speed)*speed; 767 } 768 }, 769 770 771 /** 772 * @namespace shmup The libraries for a 2D top-down Shmup game. 773 */ 774 // Shoot'em up specifics 775 shmup:{ 776 777 /** 778 * 779 */ 780 initialize:function(th,data) { 781 help.mergeWithModel( 782 th, 783 help.mergeWithModel( 784 data, 785 { 786 x:0, y:0, 787 accx:0, accy:0, 788 frames:{}, 789 maxacc:5, controlmaxacc:5, 790 responsive:0, // Responsiveness 791 bounds:{x:0,y:0,w:gbox.getScreenW(),h:gbox.getScreenH()}, // Bounds box (ship cannot exit from there) 792 weapon:0, // Weapon 793 hittime:5, 794 camera:false, 795 flipv:false, fliph:false, 796 health:1, 797 tolerance:4 798 } 799 ) 800 ); 801 toys.shmup.spawn(th); 802 }, 803 804 /** 805 * 806 */ 807 spawn:function(th,data) { 808 th.xpushing=toys.PUSH_NONE; // user is moving side 809 th.vpushing=toys.PUSH_NONE; // user is moving side 810 th.counter=0; // self counter 811 th.hittimer=0; 812 th.killed=false; 813 help.copyModel(th,data); 814 }, 815 816 /** 817 * 818 */ 819 getNextX:function(th) { return th.x+help.limit(th.accx,-th.maxacc,th.maxacc); }, 820 821 /** 822 * 823 */ 824 getNextY:function(th) { return th.y+help.limit(th.accy,-th.maxacc,th.maxacc); }, 825 826 /** 827 * 828 */ 829 controlKeys:function(th,keys) { 830 831 if (gbox.keyIsPressed(keys.left)) { 832 th.xpushing=toys.PUSH_LEFT; 833 if (th.accx>th.responsive) th.accx=th.responsive; 834 th.accx=help.limit(th.accx-1,-th.controlmaxacc,th.controlmaxacc); 835 } else if (gbox.keyIsPressed(keys.right)) { 836 th.xpushing=toys.PUSH_RIGHT; 837 if (th.accx<-th.responsive) th.accx=-th.responsive; 838 th.accx=help.limit(th.accx+1,-th.controlmaxacc,th.controlmaxacc); 839 } else th.xpushing=toys.PUSH_NONE; 840 if (gbox.keyIsPressed(keys.up)) { 841 th.ypushing=toys.PUSH_UP; 842 if (th.accy>th.responsive) th.accy=th.responsive; 843 th.accy=help.limit(th.accy-1,-th.controlmaxacc,th.controlmaxacc); 844 } else if (gbox.keyIsPressed(keys.down)) { 845 th.ypushing=toys.PUSH_DOWN; 846 if (th.accy<-th.responsive) th.accy=-th.responsive; 847 th.accy=help.limit(th.accy+1,-th.controlmaxacc,th.controlmaxacc); 848 } else th.ypushing=toys.PUSH_NONE; 849 }, 850 851 /** 852 * 853 */ 854 applyForces:function(th) { 855 th.x=toys.shmup.getNextX(th); 856 th.y=toys.shmup.getNextY(th); 857 }, 858 859 /** 860 * 861 */ 862 handleAccellerations:function(th) { 863 if (!th.xpushing) th.accx=help.goToZero(th.accx); 864 if (!th.ypushing) th.accy=help.goToZero(th.accy); 865 }, 866 867 /** 868 * 869 */ 870 keepInBounds:function(th) { 871 if (th.x<th.bounds.x) { 872 th.x=th.bounds.x; 873 th.accx=0; 874 } else if (th.x+th.w>th.bounds.x+th.bounds.w) { 875 th.x=th.bounds.x+th.bounds.w-th.w; 876 th.accx=0; 877 } 878 if (th.y<th.bounds.y) { 879 th.y=th.bounds.y; 880 th.accy=0; 881 } else if (th.y+th.h>th.bounds.y+th.bounds.h) { 882 th.y=th.bounds.y+th.bounds.h-th.h; 883 th.accy=0; 884 } 885 }, 886 887 /** 888 * 889 */ 890 setFrame:function(th) { 891 if (th.hittimer) th.hittimer--; 892 th.frame=help.decideFrame(th.counter,(th.hittimer?th.frames.hit:th.frames.still)); 893 }, 894 895 /** 896 * 897 */ 898 fireBullet:function(gr,id,data) { 899 900 var ts=gbox.getTiles(data.tileset); 901 902 var obj=gbox.addObject( 903 help.mergeWithModel( 904 data,{ 905 _bullet:true, 906 fliph:false, flipv:false, 907 id:id, 908 group:gr, 909 cnt:0, 910 tileset:"", 911 frames:{}, 912 acc:0, 913 angle:0, 914 camera:false, 915 accx:(data.accx==null?Math.floor(trigo.translateX(0,data.angle,data.acc)):0), 916 accy:(data.accy==null?Math.floor(trigo.translateY(0,data.angle,data.acc)):0), 917 x:data.from.x+data.from.hw-ts.tilehw+(data.gapx?data.gapx:0), 918 y:(data.upper?data.from.y-ts.tilehh+(data.gapy?data.gapy:0):data.from.y+data.from.h-ts.tilehh-(data.gapy?data.gapy:0)), 919 collidegroup:"", 920 spark:toys.NOOP, 921 power:1 922 } 923 ) 924 ); 925 926 obj[(data.logicon==null?"first":data.logicon)]=function() { 927 this.x+=this.accx; 928 this.y+=this.accy; 929 this.cnt=(this.cnt+1)%10; 930 if (!gbox.objectIsVisible(this)) gbox.trashObject(this); 931 else if (this.collidegroup!=null) 932 for (var i in gbox._objects[this.collidegroup]) 933 if ((!gbox._objects[this.collidegroup][i].initialize)&&gbox.collides(this,gbox._objects[this.collidegroup][i],gbox._objects[this.collidegroup][i].tolerance)) { 934 if (gbox._objects[this.collidegroup][i]["hitByBullet"]!=null) 935 if (!gbox._objects[this.collidegroup][i].hitByBullet(this)) { 936 this.spark(this); 937 gbox.trashObject(this); 938 } 939 } 940 } 941 942 obj[(data.bliton==null?"blit":data.bliton)]=function() { 943 gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.cnt,this.frames),dx:this.x,dy:this.y,camera:this.camera,fliph:this.side,flipv:this.flipv}); 944 } 945 946 return obj; 947 948 }, 949 950 /** 951 * 952 */ 953 hitByBullet:function(th,by) { 954 if (by.power) { 955 th.health-=by.power; 956 if (th.health<=0) th.kill(by); else th.hittimer=th.hittime; 957 } 958 }, 959 960 /** 961 * 962 */ 963 generateEnemy:function(gr,id,data,model) { 964 help.mergeWithModel(data,model); 965 var obj=gbox.addObject( 966 help.mergeWithModel( 967 data,{ 968 id:id, 969 group:gr, 970 cnt:0, 971 tileset:"", 972 frames:{}, 973 acc:0, 974 angle:0, 975 camera:false, 976 fliph:false, 977 flipv:false, 978 accx:(data.accx==null?Math.floor(trigo.translateX(0,data.angle,data.acc)):0), 979 accy:(data.accy==null?Math.floor(trigo.translateY(0,data.angle,data.acc)):0), 980 x:data.x, 981 y:data.y, 982 // -- spec 983 animationset:"still", 984 defaultanimationset:"still", 985 hitanimationset:"still", 986 hittime:5, 987 script:toys.NOOP, 988 handler:toys.NOOP, 989 scriptline:(data.scriptline==null?-1:data.scriptline-1), 990 newline:true, 991 waitframes:0, 992 doframes:0, 993 mode:0, 994 line:{}, 995 dohandler:null, 996 ended:false, 997 health:1, 998 hittimer:0, 999 kill:toys.NOOP, 1000 tolerance:0, 1001 initialize:null, 1002 invulnerable:false, 1003 hitAnimation:function(time) { 1004 this.hittimer=(time==null?this.hittime:time); 1005 this.animationset=this.hitanimationset; 1006 }, 1007 goTo:function(nl) { // Jump to a line 1008 this.waitframes=0; 1009 this.doframes=0; 1010 this.line={}; 1011 this.scriptline=nl-1; 1012 }, 1013 hitByBullet:function(by) { 1014 if (!this.invulnerable&&by.power) { 1015 this.health-=by.power; 1016 if (this.health<=0) this.kill(this,by); else this.hitAnimation(); 1017 } 1018 }, 1019 } 1020 ) 1021 ); 1022 1023 1024 obj[(data.logicon==null?"first":data.logicon)]=function() { 1025 if (this.initialize!=null) { 1026 this.initialize(this); 1027 this.initialize=null; 1028 } 1029 if (!this.ended) { 1030 if (!this.waitframes&&!this.doframes&&((this.line.waitfor==null)||this.line.waitfor(this))) { 1031 this.scriptline++; 1032 this.everycnt=-1; 1033 if (this.script[this.scriptline]==null) 1034 this.ended=true; 1035 else { 1036 if (this.script[this.scriptline].goto!=null) this.scriptline=this.script[this.scriptline].goto; 1037 this.line=this.script[this.scriptline]; 1038 if (this.line.afterframes!=null) 1039 this.waitframes=this.line.afterframes; 1040 if (this.line.forframes!=null) 1041 this.doframes=this.line.forframes; 1042 else 1043 this.doframes=1; 1044 if (this.line.cleardo) 1045 this.dohandler=null; 1046 else if (this.line.doit!=null) { 1047 this.dohandler={ 1048 actiontimes:0, 1049 timer:(this.line.doit.every=="keep"?this.dohandler.every:this.line.doit.every), 1050 every:(this.line.doit.every=="keep"?this.dohandler.every:this.line.doit.every), 1051 once:(this.line.doit.once=="keep"?this.dohandler.once:this.line.doit.once), 1052 action:(this.line.doit.action=="keep"?this.dohandler.action:this.line.doit.action), 1053 render:(this.line.doit.render=="keep"?this.dohandler.render:this.line.doit.render) 1054 } 1055 } 1056 1057 } 1058 } 1059 if (!this.waitframes&&this.doframes&&!this.ended) { 1060 this.doframes--; 1061 if (this.line.setinvulnerable!=null) this.invulnerable=this.line.setinvulnerable; 1062 if (this.line.setx!=null) this.x=this.line.setx; 1063 if (this.line.sety!=null) this.y=this.line.sety; 1064 if (this.line.addx!=null) this.x+=this.line.addx; 1065 if (this.line.addy!=null) this.y+=this.line.addy; 1066 if (this.line.setaccx!=null) this.accx=this.line.setaccx; 1067 if (this.line.setaccy!=null) this.accy=this.line.setaccy; 1068 if (this.line.setacc!=null) { 1069 this.acc=this.line.setacc; 1070 this.accx=Math.floor(trigo.translateX(0,this.angle,this.acc)); 1071 this.accy=Math.floor(trigo.translateY(0,this.angle,this.acc)); 1072 } 1073 if (this.line.addaccx!=null) this.accx+=this.line.addaccx; 1074 if (this.line.addaccy!=null) this.accy+=this.line.addaccy; 1075 if (this.line.addacc!=null) { 1076 this.acc+=this.line.addacc; 1077 this.accx=Math.floor(trigo.translateX(0,this.angle,this.acc)); 1078 this.accy=Math.floor(trigo.translateY(0,this.angle,this.acc)); 1079 } 1080 1081 if (this.line.setangle!=null) { 1082 this.angle=this.line.setangle; 1083 this.accx=Math.floor(trigo.translateX(0,this.angle,this.acc)); 1084 this.accy=Math.floor(trigo.translateY(0,this.angle,this.acc)); 1085 } 1086 if (this.line.addangle!=null) { 1087 this.angle+=this.line.addangle; 1088 this.accx=Math.floor(trigo.translateX(0,this.angle,this.acc)); 1089 this.accy=Math.floor(trigo.translateY(0,this.angle,this.acc)); 1090 } 1091 if (this.line.everyframe) this.waitframes=this.line.everyframe; 1092 1093 } 1094 if (this.waitframes>0) this.waitframes--; 1095 } 1096 if (this.dohandler&&(this.dohandler.action!=null)) { 1097 if (this.dohandler.timer==this.dohandler.every) { 1098 this.dohandler.action(this,this.dohandler.actiontimes); 1099 this.dohandler.timer=0; 1100 this.dohandler.actiontimes++; 1101 } else if (!this.dohandler.once) this.dohandler.timer++; 1102 } 1103 if (this.handler!=null) this.handler(this); 1104 1105 if (this.hittimer) { 1106 this.hittimer--; 1107 if (!this.hittimer) this.animationset=this.defaultanimationset; 1108 } 1109 1110 this.x+=this.accx; 1111 this.y+=this.accy; 1112 this.cnt=(this.cnt+1)%10; 1113 1114 } 1115 1116 obj[(data.bliton==null?"blit":data.bliton)]=function() { 1117 gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.cnt,this.frames[this.animationset]),dx:this.x,dy:this.y,camera:this.camera,fliph:this.side,flipv:this.flipv}); 1118 if (this.dohandler&&(this.dohandler.render!=null)) this.dohandler.render(this); 1119 } 1120 1121 return obj; 1122 1123 }, 1124 1125 /** 1126 * 1127 */ 1128 generateScroller:function(gr,id,data) { 1129 var obj=gbox.addObject( 1130 help.mergeWithModel( 1131 help.cloneObject(data),{ 1132 id:id, group:gr, 1133 y:0, x:0, 1134 stage:{}, 1135 speed:0, 1136 stop:null, // Remember to set the last stop ever! or the last loop! 1137 block:-1, 1138 bly:0, 1139 lblock:-1, 1140 lbly:0, 1141 lget:0, 1142 tbly:0, 1143 trb:0, 1144 maxwidth:0, 1145 loopstart:null, loopend:null, looprounds:0, 1146 panspeed:1, panstimer:0, destspeed:0, 1147 1148 setLoop:function(st,en) { 1149 this.loopstart=st; 1150 this.loopend=en; 1151 this.lget=1; 1152 this.looprounds=1; 1153 }, 1154 1155 quitLoop:function() { 1156 this.setLoop(null,null); 1157 this.looprounds=0; 1158 }, 1159 1160 setSpeed:function(s) { 1161 this.speed=s; 1162 this.destspeed=s; 1163 }, 1164 1165 panToSpeed:function(s,pans) { 1166 this.destspeed=s; 1167 this.panspeed=pans; 1168 }, 1169 1170 quitStop:function() { 1171 this.stop=null; 1172 }, 1173 1174 setStop:function(s) { 1175 this.stop=s; 1176 }, 1177 1178 setX:function(x) { 1179 if (x<0) this.x=0; else 1180 if (x+gbox.getScreenW()>this.maxwidth) this.x=this.maxwidth-gbox.getScreenW(); 1181 else this.x=x; 1182 } 1183 1184 } 1185 ) 1186 ); 1187 1188 obj[(data.logicon==null?"first":data.logicon)]=function() { 1189 if ((this.stop==null)||(this.y<this.stop)) { 1190 if (this.speed!=this.destspeed) { 1191 if (this.panstimer) { 1192 this.panstimer--; 1193 } else { 1194 if (this.speed<this.destspeed) this.speed++; else 1195 if (this.speed>this.destspeed) this.speed--; 1196 this.panstimer=this.panspeed; 1197 } 1198 } 1199 this.y+=this.speed; 1200 if ((this.stop!=null)&&(this.y>=this.stop)) this.y=this.stop; 1201 if ((this.loopend!=null)&&(this.y>this.loopend)) { 1202 this.y=this.loopstart+(this.y-this.loopend); 1203 this.looprounds++; 1204 if (this.lget==1) { 1205 this.block=0; 1206 this.bly=0; 1207 this.lget=2; 1208 } else { 1209 this.block=this.lblock; 1210 this.bly=this.lbly; 1211 } 1212 1213 } 1214 } 1215 1216 // Cerca il blocco da mostrare 1217 this.trb=this.block; 1218 this.tbly=this.bly; 1219 do { 1220 this.trb++; 1221 this.tbly+=gbox.getImage(this.stage[this.trb].image).height; 1222 } while (this.tbly<this.y); 1223 1224 this.block=this.trb-1; 1225 this.bly=this.tbly-gbox.getImage(this.stage[this.trb].image).height; 1226 1227 1228 if (this.lget==2) { 1229 this.lblock=this.block; 1230 this.lbly=this.bly; 1231 this.lget=3; 1232 } 1233 1234 } 1235 1236 obj[(data.bliton==null?"blit":data.bliton)]=function() { 1237 var dy=this.tbly-this.y; 1238 var done=false; 1239 do { 1240 if (dy>gbox.getScreenH()) done=true; 1241 gbox.blitAll(gbox.getBufferContext(),gbox.getImage(this.stage[this.trb].image),{dx:-this.x,dy:gbox.getScreenH()-dy}); 1242 this.trb++; 1243 dy+=gbox.getImage(this.stage[this.trb].image).height; 1244 } while (!done); 1245 } 1246 1247 return obj; 1248 } 1249 }, 1250 1251 /** 1252 * @namespace platformer The libraries for generating a 2D platformer game. 1253 */ 1254 platformer:{ 1255 1256 /** 1257 * 1258 */ 1259 initialize:function(th,data) { 1260 help.mergeWithModel( 1261 th, 1262 help.mergeWithModel( 1263 data, 1264 { 1265 maxaccx:5, maxaccy:10, 1266 jumpsize:6, jumpaccy:6, 1267 accx:0, accy:0, 1268 x:0, y:0, 1269 frames:{}, 1270 camera:true, 1271 flipv:false, 1272 side:false 1273 } 1274 ) 1275 ); 1276 toys.platformer.spawn(th); 1277 }, 1278 1279 /** 1280 * 1281 */ 1282 spawn:function(th,data) { 1283 th.curjsize=0; // current jump size 1284 th.counter=0; // self counter 1285 th.touchedfloor=false; // touched floor 1286 th.touchedceil=false; 1287 th.touchedleftwall=false; 1288 th.touchedrightwall=false; 1289 th.pushing=toys.PUSH_NONE; // user is moving side 1290 th.killed=false; 1291 help.copyModel(th,data); 1292 }, 1293 1294 /** 1295 * 1296 */ 1297 getNextX:function(th) { return th.x+th.accx; }, 1298 1299 /** 1300 * 1301 */ 1302 getNextY:function(th) { return th.y+help.limit(th.accy,-th.maxaccy,th.maxaccy); }, 1303 1304 /** 1305 * 1306 */ 1307 applyGravity:function(th) { 1308 th.x=toys.platformer.getNextX(th); 1309 th.y=toys.platformer.getNextY(th); 1310 }, 1311 1312 /** 1313 * 1314 */ 1315 horizontalKeys:function(th,keys) { 1316 if (gbox.keyIsPressed(keys.left)) { 1317 th.pushing=toys.PUSH_LEFT; 1318 th.accx=help.limit(th.accx-1,-th.maxaccx,th.maxaccx); 1319 } else if (gbox.keyIsPressed(keys.right)) { 1320 th.pushing=toys.PUSH_RIGHT; 1321 th.accx=help.limit(th.accx+1,-th.maxaccx,th.maxaccx); 1322 } else th.pushing=toys.PUSH_NONE; 1323 }, 1324 1325 /** 1326 * 1327 */ 1328 verticalTileCollision:function(th,map,tilemap) { 1329 var bottom=help.getTileInMap(th.x+(th.w/2),th.y+th.h,map,0,tilemap); 1330 var top=help.getTileInMap(th.x+(th.w/2),th.y,map,0,tilemap); 1331 th.touchedfloor=false; 1332 th.touchedceil=false; 1333 1334 if (map.tileIsSolidCeil(th,top)) { 1335 th.accy=0; 1336 th.y=help.yPixelToTile(map,th.y,1); 1337 th.touchedceil=true; 1338 } 1339 if (map.tileIsSolidFloor(th,bottom)) { 1340 th.accy=0; 1341 th.y=help.yPixelToTile(map,th.y+th.h)-th.h; 1342 th.touchedfloor=true; 1343 } 1344 }, 1345 1346 /** 1347 * 1348 */ 1349 horizontalTileCollision:function(th,map,tilemap) { 1350 var left=0; 1351 var right=0; 1352 var t=0; 1353 1354 th.touchedleftwall=false; 1355 th.touchedrightwall=false; 1356 1357 while (t<th.h) { 1358 left=help.getTileInMap(th.x,th.y+t,map,0,tilemap); 1359 right=help.getTileInMap(th.x+th.w-1,th.y+t,map,0,tilemap); 1360 1361 if ((th.accx<0)&&map.tileIsSolidFloor(th,left)) { 1362 th.accx=0; 1363 th.x=help.xPixelToTile(map,th.x-1,1); 1364 th.touchedleftwall=true; 1365 } 1366 if ((th.accx>0)&&map.tileIsSolidFloor(th,right)) { 1367 th.accx=0; 1368 th.x=help.xPixelToTile(map,th.x+th.w)-th.w; 1369 th.touchedrightwall=true; 1370 } 1371 t+=gbox.getTiles(map.tileset).tileh; 1372 } 1373 }, 1374 1375 /** 1376 * Checks if the passed object is touching the floor and can therefore jump at present. 1377 * @param th This is the object being checked for jump ability at the time of calling. 1378 */ 1379 canJump:function(th) { 1380 return th.touchedfloor; 1381 }, 1382 1383 /** 1384 * 1385 */ 1386 jumpKeys:function(th,key) { 1387 if ((toys.platformer.canJump(th)||(key.doublejump&&(th.accy>=0)))&&gbox.keyIsHit(key.jump)&&(th.curjsize==0)) { 1388 if (key.audiojump) gbox.hitAudio(key.audiojump); 1389 th.accy=-th.jumpaccy; 1390 th.curjsize=th.jumpsize; 1391 return true; 1392 } else if (th.curjsize&&gbox.keyIsHold(key.jump)) { // Jump modulation 1393 th.accy--; 1394 th.curjsize--; 1395 } else 1396 th.curjsize=0; 1397 return false; 1398 }, 1399 1400 /** 1401 * 1402 */ 1403 bounce:function(th,data) { 1404 th.curjsize=0; 1405 th.accy=-data.jumpsize; 1406 }, 1407 1408 /** 1409 * 1410 */ 1411 handleAccellerations:function(th) { 1412 // Gravity 1413 if (!th.touchedfloor) th.accy++; 1414 // Attrito 1415 if (th.pushing==toys.PUSH_NONE) if (th.accx) th.accx=help.goToZero(th.accx); 1416 }, 1417 1418 /** 1419 * 1420 */ 1421 setSide:function(th) { 1422 if (th.accx) th.side=th.accx>0; 1423 }, 1424 1425 /** 1426 * 1427 */ 1428 setFrame:function(th) { 1429 if (th.touchedfloor) 1430 if (th.pushing!=toys.PUSH_NONE) 1431 th.frame=help.decideFrame(th.counter,th.frames.walking); 1432 else 1433 th.frame=help.decideFrame(th.counter,th.frames.still); 1434 else if (th.accy>0) 1435 th.frame=help.decideFrame(th.counter,th.frames.falling); 1436 else 1437 th.frame=help.decideFrame(th.counter,th.frames.jumping); 1438 }, 1439 1440 /** 1441 * 1442 */ 1443 auto:{ 1444 // Moves on a platform. It tries to do not fall down, if specified. 1445 // Args: (object,{moveWhileFalling:<moves while not touching the floor>,speed:<movement speed>}) 1446 // Outs: the frame 1447 goomba:function(th,data) { 1448 if (data.moveWhileFalling||th.touchedfloor) { 1449 if (th.side) { 1450 th.pushing=toys.PUSH_LEFT; 1451 th.accx=-data.speed; 1452 } else { 1453 th.pushing=toys.PUSH_RIGHT; 1454 th.accx=data.speed; 1455 } 1456 } else th.pushing=toys.PUSH_NONE; 1457 }, 1458 dontFall:function(th,map,tilemap) { 1459 if (th.accx&&th.touchedfloor) { 1460 var til; 1461 if (th.accx>0) til=help.getTileInMap(toys.platformer.getNextX(th)+th.w-1+th.accx,th.y+th.h,map,0,tilemap); 1462 else til=help.getTileInMap(toys.platformer.getNextX(th),th.y+th.h,map,0,tilemap); 1463 if (!map.tileIsSolidFloor(th,til)) { 1464 th.side=!th.side; 1465 th.accx=0; 1466 } 1467 } 1468 }, 1469 horizontalBounce:function(th) { 1470 if (th.touchedleftwall||th.touchedrightwall) th.side=!th.side; 1471 }, 1472 } 1473 }, 1474 1475 // State-based toys 1476 // CONSTANTS 1477 TOY_BUSY:0, 1478 TOY_DONE:1, 1479 TOY_IDLE:2, 1480 1481 // PRIVATE 1482 1483 // Generical toys method 1484 1485 /** 1486 * 1487 */ 1488 resetToy:function(th,id) { if (th.toys) delete th.toys[id] }, 1489 1490 /** 1491 * 1492 */ 1493 getToyValue:function(th,id,v,def) { return ((th.toys==null)||(th.toys[id]==null)?def:th.toys[id][v]) }, 1494 1495 /** 1496 * 1497 */ 1498 getToyStatus:function(th,id) { return ((th.toys==null)||(th.toys[id]==null)?toys.TOY_BUSY:th.toys[id].__status) }, 1499 1500 /** 1501 * 1502 */ 1503 _toydone:function(th,id) { 1504 if (th.toys[id].__status<toys.TOY_IDLE) th.toys[id].__status++; 1505 return th.toys[id].__status; 1506 }, 1507 1508 /** 1509 * 1510 */ 1511 _toybusy:function(th,id) { 1512 th.toys[id].__status=toys.TOY_BUSY; 1513 return th.toys[id].__status; 1514 }, 1515 1516 /** 1517 * 1518 */ 1519 _toyfrombool:function(th,id,b) { return (b?toys._toydone(th,id):toys._toybusy(th,id)) }, 1520 1521 /** 1522 * 1523 */ 1524 _maketoy:function(th,id){ 1525 if (!th.toys) th.toys={}; 1526 if (!th.toys[id]) { 1527 th.toys[id]={__status:toys.TOY_BUSY}; 1528 return true; 1529 } else return false; 1530 }, 1531 1532 /** 1533 * @namespace timer Timer functionality based methods 1534 */ 1535 // Pure timers 1536 timer:{ 1537 1538 /** 1539 * 1540 */ 1541 randomly:function(th,id,data) { 1542 if (toys._maketoy(th,id)) { 1543 th.toys[id].time=help.random(data.base,data.range); 1544 } 1545 if (th.toys[id].time) { 1546 th.toys[id].time--; 1547 return toys._toybusy(th,id); 1548 } else { 1549 th.toys[id].time=help.random(data.base,data.range); 1550 return toys._toydone(th,id); 1551 } 1552 }, 1553 1554 /** 1555 * 1556 */ 1557 real:function(th,id,data) { 1558 if (toys._maketoy(th,id)) { 1559 th.toys[id].subtimer=gbox.getFps(); 1560 th.toys[id].done=false; 1561 if (data.countdown) 1562 th.toys[id].time=data.countdown; 1563 else 1564 th.toys[id].time=0; 1565 } 1566 th.toys[id].subtimer--; 1567 if (!th.toys[id].subtimer) { 1568 th.toys[id].subtimer=gbox.getFps(); 1569 if (data.countdown) { 1570 if (th.toys[id].time) { 1571 th.toys[id].time--; 1572 if (data.audiocritical&&(th.toys[id].time<=data.critical)) 1573 gbox.hitAudio(data.audiocritical); 1574 } else th.toys[id].done=true; 1575 } else 1576 th.toys[id].time++; 1577 } 1578 return toys._toyfrombool(th,id,th.toys[id].done); 1579 1580 }, 1581 1582 /** 1583 * 1584 */ 1585 every:function(th,id,frames){ 1586 if (toys._maketoy(th,id)) th.toys[id].timer=0; 1587 th.toys[id].timer++; 1588 if (th.toys[id].timer==frames) { 1589 th.toys[id].timer=0; 1590 return toys._toydone(th,id); 1591 } else return toys._toybusy(th,id) 1592 }, 1593 1594 /** 1595 * 1596 */ 1597 after:function(th,id,frames) { 1598 if (toys._maketoy(th,id)) th.toys[id].timer=0; 1599 if (th.toys[id].timer==frames) return toys._toydone(th,id); else { 1600 th.toys[id].timer++; 1601 return toys._toybusy(th,id); 1602 } 1603 } 1604 }, 1605 1606 /** 1607 * 1608 */ 1609 // Logical helpers 1610 logic: { 1611 1612 /** 1613 * 1614 */ 1615 once:function(th,id,cond){ 1616 if (toys._maketoy(th,id)) th.toys[id].done=false; 1617 if (th.toys[id].done) return false; else if (cond) th.toys[id].done=true; 1618 return cond; 1619 } 1620 }, 1621 1622 /** 1623 * 1624 */ 1625 // UI 1626 ui:{ 1627 1628 /** 1629 * 1630 */ 1631 menu:function(th,id,opt) { 1632 if (toys._maketoy(th,id)||opt.resetmenu) { 1633 var fd=gbox.getFont(opt.font); 1634 th.toys[id].selected=(opt.selected?opt.selected:0); 1635 th.toys[id].ok=0; 1636 var w=0; 1637 for (var i=0;i<opt.items.length;i++) 1638 if (opt.items[i].length>w) w=opt.items[i].length; 1639 gbox.createCanvas("menu-"+id,{w:w*fd.tilew,h:opt.items.length*fd.tileh}); 1640 for (var i=0;i<opt.items.length;i++) 1641 gbox.blitText(gbox.getCanvasContext("menu-"+id),{font:opt.font,text:opt.items[i],dx:0,dy:fd.tileh*i}); 1642 th.toys[id].fh=fd.tileh; 1643 th.toys[id].fw=fd.tilew; 1644 } 1645 if (!th.toys[id].ok) { 1646 if (gbox.keyIsHit(opt.keys.up)&&(th.toys[id].selected>0)) { 1647 if (opt.audiooption) gbox.hitAudio(opt.audiooption); 1648 th.toys[id].selected--; 1649 } else 1650 if (gbox.keyIsHit(opt.keys.down)&&(th.toys[id].selected<opt.items.length-1)) { 1651 if (opt.audiooption) gbox.hitAudio(opt.audiooption); 1652 th.toys[id].selected++; 1653 } else 1654 if (gbox.keyIsHit(opt.keys.ok)) { 1655 if (opt.audioconfirm) gbox.hitAudio(opt.audioconfirm); 1656 th.toys[id].ok=1; 1657 } else 1658 if (gbox.keyIsHit(opt.keys.cancel)) th.toys[id].ok=-1; 1659 } 1660 gbox.blitAll(gbox.getBufferContext(),gbox.getCanvas("menu-"+id),{dx:opt.x+th.toys[id].fw,dy:opt.y,camera:opt.camera}); 1661 if (!(th.toys[id].ok%2)) gbox.blitText(gbox.getBufferContext(),{font:opt.font,text:opt.selector,dx:opt.x,dy:opt.y+th.toys[id].selected*th.toys[id].fh,camera:opt.camera}); 1662 if (th.toys[id].ok) { 1663 if (th.toys[id].ok>0) 1664 if (th.toys[id].ok<10) { 1665 th.toys[id].ok++; 1666 toys._toybusy(th,id); 1667 } else return toys._toydone(th,id); // selected > 0 1668 else return toys._toydone(th,id); // selected == -1 1669 } else return toys._toybusy(th,id); 1670 }, 1671 1672 /** 1673 * 1674 */ 1675 // Returns a full customizable object for optimized huds 1676 hud:function(id) { 1677 gbox.createCanvas(id); 1678 return { 1679 w:{}, 1680 surfaceid:id, 1681 1682 /** 1683 * 1684 */ 1685 updateWidget:function(i){ 1686 if (!this.w[i].__hidden) { 1687 if (this.w[i].widget=="label") { 1688 if (this.w[i].prepad!=null) this.w[i].text=help.prepad(this.w[i].value,this.w[i].prepad,this.w[i].padwith); else 1689 if (this.w[i].postpad!=null) this.w[i].text=help.postpad(this.w[i].value,this.w[i].postpad,this.w[i].padwith); else 1690 this.w[i].text=this.w[i].value+""; 1691 gbox.blitText(gbox.getCanvasContext(this.surfaceid),this.w[i]); 1692 } 1693 if (this.w[i].widget=="symbols") { 1694 var ts=gbox.getTiles(this.w[i].tileset); 1695 gbox.blitClear(gbox.getCanvasContext(this.surfaceid),{x:this.w[i].dx,y:this.w[i].dy,w:((this.w[i].maxshown-1)*this.w[i].gapx)+ts.tilew,h:((this.w[i].maxshown-1)*this.w[i].gapy)+ts.tileh}); 1696 var cnt=this.w[i].value; 1697 for (var x=0;x<this.w[i].maxshown;x++) { 1698 if (cnt>0) { 1699 gbox.blitTile(gbox.getCanvasContext(this.surfaceid),{tileset:this.w[i].tileset,tile:this.w[i].tiles[(cnt>this.w[i].tiles.length?this.w[i].tiles.length-1:cnt-1)],dx:this.w[i].dx+(x*this.w[i].gapx),dy:this.w[i].dy+(x*this.w[i].gapy),fliph:this.w[i].fliph,flipv:this.w[i].flipv}); 1700 } else 1701 if (this.w[i].emptytile!=null) 1702 gbox.blitTile(gbox.getCanvasContext(this.surfaceid),{tileset:this.w[i].tileset,tile:this.w[i].emptytile,dx:this.w[i].dx+(x*this.w[i].gapx),dy:this.w[i].dy+(x*this.w[i].gapy),fliph:this.w[i].fliph,flipv:this.w[i].flipv}); 1703 cnt-=this.w[i].tiles.length; 1704 } 1705 1706 } 1707 if (this.w[i].widget=="stack") { 1708 var ts=gbox.getTiles(this.w[i].tileset); 1709 var bw=((this.w[i].maxshown-1)*this.w[i].gapx)+ts.tilew; 1710 gbox.blitClear(gbox.getCanvasContext(this.surfaceid),{x:this.w[i].dx-(this.w[i].rightalign?bw:0),y:this.w[i].dy,w:bw,h:((this.w[i].maxshown-1)*this.w[i].gapy)+ts.tileh}); 1711 for (var x=0;x<this.w[i].maxshown;x++) 1712 if (x<this.w[i].value.length) 1713 gbox.blitTile(gbox.getCanvasContext(this.surfaceid),{tileset:this.w[i].tileset,tile:this.w[i].value[x],dx:(this.w[i].rightalign?this.w[i].dx-ts.tileh-(this.w[i].gapx*x):this.w[i].dx+(x*this.w[i].gapx)),dy:this.w[i].dy+(x*this.w[i].gapy),fliph:this.w[i].fliph,flipv:this.w[i].flipv}); 1714 } 1715 if (this.w[i].widget=="radio") { 1716 var ts=gbox.getTiles(this.w[i].tileset); 1717 gbox.blitClear(gbox.getCanvasContext(this.surfaceid),{x:this.w[i].dx,y:this.w[i].dy,w:ts.tilew,h:ts.tileh}); 1718 gbox.blitTile(gbox.getCanvasContext(this.surfaceid),{tileset:this.w[i].tileset,tile:this.w[i].frames[this.w[i].value],dx:this.w[i].dx,dy:this.w[i].dy,fliph:this.w[i].fliph,flipv:this.w[i].flipv}); 1719 1720 } 1721 if (this.w[i].widget=="blit") { 1722 var ts=gbox.getTiles(this.w[i].tileset); 1723 gbox.blitClear(gbox.getCanvasContext(this.surfaceid),{x:this.w[i].dx,y:this.w[i].dy,w:ts.tilew,h:ts.tileh}); 1724 gbox.blitTile(gbox.getCanvasContext(this.surfaceid),{tileset:this.w[i].tileset,tile:this.w[i].value,dx:this.w[i].dx,dy:this.w[i].dy,fliph:this.w[i].fliph,flipv:this.w[i].flipv}); 1725 1726 } 1727 if (this.w[i].widget=="bool") { 1728 var ts=gbox.getTiles(this.w[i].tileset); 1729 gbox.blitClear(gbox.getCanvasContext(this.surfaceid),{x:this.w[i].dx,y:this.w[i].dy,w:ts.tilew,h:ts.tileh}); 1730 if (this.w[i].value) 1731 gbox.blitTile(gbox.getCanvasContext(this.surfaceid),{tileset:this.w[i].tileset,tile:this.w[i].frame,dx:this.w[i].dx,dy:this.w[i].dy,fliph:this.w[i].fliph,flipv:this.w[i].flipv}); 1732 } 1733 if (this.w[i].widget=="gauge") { 1734 var ts=gbox.getTiles(this.w[i].tileset); 1735 gbox.blitTile(gbox.getCanvasContext(this.surfaceid),{tileset:this.w[i].tileset,tile:0,dx:this.w[i].dx,dy:this.w[i].dy}); 1736 gbox.blitTile(gbox.getCanvasContext(this.surfaceid),{tileset:this.w[i].tileset,tile:1,dx:this.w[i].dx,dy:this.w[i].dy,w:(this.w[i].value*ts.tilew)/this.w[i].maxvalue}); 1737 } 1738 } 1739 }, 1740 1741 /** 1742 * 1743 */ 1744 hideWidgets:function(l) { 1745 for (var i=0;i<l.length;i++) this.w[l[i]].__hidden=true; 1746 this.redraw(); 1747 }, 1748 1749 /** 1750 * 1751 */ 1752 showWidgets:function(l) { 1753 for (var i=0;i<l.length;i++) this.w[l[i]].__hidden=false; 1754 this.redraw(); 1755 }, 1756 1757 /** 1758 * 1759 */ 1760 getValue:function(w,k) { 1761 return this.w[w][k]; 1762 }, 1763 1764 /** 1765 * 1766 */ 1767 getNumberValue:function(w,k) { 1768 return this.w[w][k]*1; 1769 }, 1770 1771 /** 1772 * 1773 */ 1774 setValue:function(w,k,v) { 1775 if (this.w[w][k]!=v) { 1776 if (k=="value") { 1777 if ((this.w[w].maxvalue!=null)&&(v>this.w[w].maxvalue)) v=this.w[w].maxvalue; 1778 if ((this.w[w].minvalue!=null)&&(v<this.w[w].minvalue)) v=this.w[w].minvalue; 1779 if (this.w[w].widget=="radio") v=(v%this.w[w].frames.length); 1780 } 1781 this.w[w][k]=v; 1782 this.updateWidget(w); 1783 } 1784 }, 1785 1786 /** 1787 * 1788 */ 1789 pushValue:function(w,k,v) { 1790 this.w[w][k].push(v); 1791 this.updateWidget(w); 1792 }, 1793 1794 /** 1795 * 1796 */ 1797 addValue:function(w,k,v) { 1798 if (v) this.setValue(w,k,this.w[w][k]+v); 1799 }, 1800 1801 /** 1802 * 1803 */ 1804 setWidget:function(id,w) { 1805 this.w[id]=w; 1806 this.updateWidget(id); 1807 }, 1808 1809 /** 1810 * 1811 */ 1812 redraw:function() { 1813 gbox.blitClear(gbox.getCanvasContext(this.surfaceid)); 1814 for (var i in this.w) this.updateWidget(i); 1815 }, 1816 1817 /** 1818 * 1819 */ 1820 blit:function() { 1821 gbox.blitAll(gbox.getBufferContext(),gbox.getCanvas(this.surfaceid),{dx:0,dy:0}); 1822 } 1823 1824 } 1825 } 1826 }, 1827 1828 /** 1829 * 1830 */ 1831 fullscreen:{ 1832 1833 /** 1834 * 1835 */ 1836 fadeout:function(th,id,tox,data) { 1837 if (toys._maketoy(th,id)||data.resetfade) { 1838 th.toys[id].fade=0; 1839 if (data.audiofade) th.toys[id].stv=gbox.getAudioVolume(data.audiofade); 1840 if (data.audiochannelfade) th.toys[id].chv=gbox.getChannelVolume(data.audiochannelfade); 1841 } 1842 th.toys[id].fade+=data.fadespeed; 1843 if (th.toys[id].fade>1) th.toys[id].fade=1; 1844 data.alpha=th.toys[id].fade; 1845 gbox.blitFade(tox,data); 1846 if (data.audiofade) gbox.setAudioVolume(data.audiofade,th.toys[id].stv*(1-data.alpha)); 1847 if (data.audiochannelfade) 1848 if (data.alpha==1) 1849 gbox.stopChannel(data.audiochannelfade); 1850 else 1851 gbox.setChannelVolume(data.audiochannelfade,th.toys[id].chv*(1-data.alpha)); 1852 return toys._toyfrombool(th,id,th.toys[id].fade==1) 1853 }, 1854 1855 /** 1856 * 1857 */ 1858 fadein:function(th,id,tox,data) { 1859 if (toys._maketoy(th,id)||data.resetfade) { 1860 th.toys[id].fade=1; 1861 if (data.audiofade) th.toys[id].stv=gbox.getAudioVolume(data.audiofade); 1862 if (data.audiochannelfade) th.toys[id].chv=gbox.getChannelDefaultVolume(data.audiochannelfade); 1863 } 1864 th.toys[id].fade-=data.fadespeed; 1865 if (th.toys[id].fade<0) th.toys[id].fade=0; 1866 if (th.toys[id].fade) { 1867 data.alpha=th.toys[id].fade; 1868 if (data.audiofade) gbox.setAudioVolume(data.audiofade,th.toys[id].stv*(1-data.alpha)); 1869 if (data.audiochannelfade) gbox.setChannelVolume(data.audiochannelfade,th.toys[id].chv*(1-data.alpha)); 1870 gbox.blitFade(tox,data); 1871 } 1872 return toys._toyfrombool(th,id,th.toys[id].fade==0); 1873 } 1874 }, 1875 1876 /** 1877 * 1878 */ 1879 text:{ 1880 1881 /** 1882 * 1883 */ 1884 blink:function(th,id,tox,data) { 1885 if (toys._maketoy(th,id)) { 1886 th.toys[id].texttimer=0; 1887 th.toys[id].visible=false; 1888 th.toys[id].times=0; 1889 } 1890 if (th.toys[id].texttimer>=data.blinkspeed) { 1891 th.toys[id].texttimer=0; 1892 th.toys[id].visible=!th.toys[id].visible; 1893 if (data.times) th.toys[id].times++; 1894 } else th.toys[id].texttimer++; 1895 if (th.toys[id].visible) 1896 gbox.blitText(tox,data); 1897 return toys._toyfrombool(th,id,(data.times?data.times<th.toys[id].times:false)); 1898 }, 1899 1900 /** 1901 * 1902 */ 1903 fixed:function(th,id,tox,data) { 1904 if (toys._maketoy(th,id)) 1905 th.toys[id].texttimer=0; 1906 else 1907 th.toys[id].texttimer++; 1908 gbox.blitText(tox,data); 1909 return toys._toyfrombool(th,id,data.time<th.toys[id].texttimer); 1910 } 1911 }, 1912 1913 /** 1914 * 1915 */ 1916 logos:{ 1917 1918 /** 1919 * 1920 */ 1921 linear:function(th,id,data) { 1922 if (toys._maketoy(th,id)) { 1923 th.toys[id].x=data.sx; 1924 th.toys[id].y=data.sy; 1925 th.toys[id].every=data.every; 1926 th.toys[id].played=false; 1927 } 1928 if (!th.toys[id].every) { 1929 if ((data.x!=th.toys[id].x)||(data.y!=th.toys[id].y)) 1930 if ((Math.abs(data.x-th.toys[id].x)<=data.speed)&&(Math.abs(data.y-th.toys[id].y)<=data.speed)) { 1931 th.toys[id].x=data.x; 1932 th.toys[id].y=data.y; 1933 } else 1934 trigo.translate(th.toys[id],trigo.getAngle(th.toys[id],data),data.speed); 1935 else 1936 if (!th.toys[id].played) { 1937 if (data.audioreach) gbox.hitAudio(data.audioreach); 1938 th.toys[id].played=true; 1939 } 1940 th.toys[id].every=data.every; 1941 } else th.toys[id].every--; 1942 if (data.text) 1943 gbox.blitText(gbox.getBufferContext(),{ 1944 font:data.font, 1945 dx:th.toys[id].x,dy:th.toys[id].y, 1946 text:data.text 1947 }); 1948 else if (data.tileset) 1949 gbox.blitTile(gbox.getBufferContext(),{tileset:data.tileset,tile:data.tile,dx:th.toys[id].x,dy:th.toys[id].y,camera:data.camera,fliph:data.fliph,flipv:data.flipv,alpha:data.alpha}); 1950 else 1951 gbox.blitAll(gbox.getBufferContext(),gbox.getImage(data.image),{dx:th.toys[id].x,dy:th.toys[id].y,alpha:data.alpha}); 1952 return toys._toyfrombool(th,id,(data.x==th.toys[id].x)&&(data.y==th.toys[id].y)); 1953 }, 1954 1955 /** 1956 * 1957 */ 1958 crossed:function(th,id,data) { 1959 if (toys._maketoy(th,id)) { 1960 th.toys[id].gapx=data.gapx; 1961 th.toys[id].lw=gbox.getImage(data.image).height; 1962 th.toys[id].done=false; 1963 } 1964 if (th.toys[id].gapx) { 1965 th.toys[id].gapx-=data.speed; 1966 if (th.toys[id].gapx<0) th.toys[id].gapx=0; 1967 gbox.blitAll(gbox.getBufferContext(),gbox.getImage(data.image),{dx:data.x-th.toys[id].gapx,dy:data.y,alpha:data.alpha}); 1968 gbox.blitAll(gbox.getBufferContext(),gbox.getImage(data.image),{dx:data.x+th.toys[id].gapx,dy:data.y,alpha:data.alpha}); 1969 return toys._toybusy(th,id); 1970 } else { 1971 if (!th.toys[id].done) { 1972 th.toys[id].done=true; 1973 if (data.audioreach) gbox.hitAudio(data.audioreach); 1974 } 1975 gbox.blitAll(gbox.getBufferContext(),gbox.getImage(data.image),{dx:data.x,dy:data.y}); 1976 return toys._toydone(th,id); 1977 } 1978 }, 1979 1980 /** 1981 * 1982 */ 1983 zoomout:function(th,id,data) { 1984 if (toys._maketoy(th,id)) { 1985 th.toys[id].zoom=data.zoom; 1986 th.toys[id].done=false; 1987 th.toys[id].img=gbox.getImage(data.image); 1988 } 1989 if (th.toys[id].zoom!=1) { 1990 th.toys[id].zoom-=data.speed; 1991 if (th.toys[id].zoom<=1) { 1992 th.toys[id].zoom=1; 1993 if (data.audioreach) gbox.hitAudio(data.audioreach); 1994 } 1995 gbox.blit(gbox.getBufferContext(),gbox.getImage(data.image),{h:th.toys[id].img.height,w:th.toys[id].img.width,dx:data.x-Math.floor(th.toys[id].img.width*(th.toys[id].zoom-1)/2),dy:data.y-Math.floor(th.toys[id].img.height*(th.toys[id].zoom-1)/2),dh:Math.floor(th.toys[id].img.height*th.toys[id].zoom),dw:Math.floor(th.toys[id].img.width*th.toys[id].zoom),alpha:1/th.toys[id].zoom}); 1996 return toys._toybusy(th,id); 1997 } else { 1998 gbox.blitAll(gbox.getBufferContext(),gbox.getImage(data.image),{dx:data.x,dy:data.y}); 1999 return toys._toydone(th,id); 2000 } 2001 }, 2002 2003 /** 2004 * 2005 */ 2006 rising:function(th,id,data) { 2007 if (toys._maketoy(th,id)) { 2008 th.toys[id].cnt=0; 2009 th.toys[id].lh=gbox.getImage(data.image).height; 2010 th.toys[id].lw=gbox.getImage(data.image).width; 2011 th.toys[id].done=false; 2012 } 2013 if (th.toys[id].cnt<th.toys[id].lh) { 2014 th.toys[id].cnt+=data.speed; 2015 if (th.toys[id].cnt>th.toys[id].lh) th.toys[id].gapx=th.toys[id].lh; 2016 gbox.blit(gbox.getBufferContext(),gbox.getImage(data.image),{dh:th.toys[id].cnt,dw:th.toys[id].lw,dx:data.x,dy:data.y+th.toys[id].lh-th.toys[id].cnt,alpha:data.alpha}); 2017 if (data.reflex) gbox.blit(gbox.getBufferContext(),gbox.getImage(data.image),{dh:th.toys[id].cnt,dw:th.toys[id].lw,dx:data.x,dy:data.y+th.toys[id].lh,alpha:data.reflex,flipv:true}); 2018 if (th.toys[id].cnt>=th.toys[id].lh) 2019 if (data.audioreach) gbox.hitAudio(data.audioreach); 2020 return toys._toybusy(th,id); 2021 } else { 2022 gbox.blitAll(gbox.getBufferContext(),gbox.getImage(data.image),{dx:data.x,dy:data.y}); 2023 if (data.reflex) gbox.blitAll(gbox.getBufferContext(),gbox.getImage(data.image),{dx:data.x,dy:data.y+th.toys[id].lh,alpha:data.reflex,flipv:true}); 2024 2025 return toys._toydone(th,id); 2026 } 2027 }, 2028 2029 /** 2030 * 2031 */ 2032 bounce:function(th,id,data) { 2033 if (toys._maketoy(th,id)) { 2034 th.toys[id].accy=data.accy; 2035 th.toys[id].y=data.y; 2036 th.toys[id].h=gbox.getImage(data.image).height; 2037 th.toys[id].done=false; 2038 } 2039 if (!th.toys[id].done) { 2040 if (th.toys[id].y+th.toys[id].h>=data.floory) { 2041 if (data.audiobounce) gbox.hitAudio(data.audiobounce); 2042 th.toys[id].y=data.floory-th.toys[id].h; 2043 th.toys[id].accy=-Math.ceil(th.toys[id].accy/(data.heavy?data.heavy:2)); 2044 th.toys[id].done=(th.toys[id].accy==0); 2045 } else th.toys[id].accy--; 2046 th.toys[id].y-=th.toys[id].accy; 2047 } 2048 gbox.blitAll(gbox.getBufferContext(),gbox.getImage(data.image),{dx:data.x,dy:th.toys[id].y}); 2049 2050 return toys._toyfrombool(th,id,th.toys[id].done); 2051 } 2052 }, 2053 2054 /** 2055 * 2056 */ 2057 dialogue: { 2058 2059 /** 2060 * 2061 */ 2062 render:function(th,id,data){ 2063 if (toys._maketoy(th,id)) { 2064 th.toys[id].newscene=true; 2065 th.toys[id].sceneid=-1; 2066 th.toys[id].ended=false; 2067 th.toys[id].timer=0; 2068 th.toys[id].counter=0; 2069 th.toys[id].anim=0; 2070 gbox.createCanvas("dialogue-"+id); 2071 } 2072 if (!data.hideonend||(data.hideonend&&!th.toys[id].ended)) { 2073 if (th.toys[id].newscene&&!th.toys[id].ended) { 2074 th.toys[id].anim=0; 2075 th.toys[id].timer=0; 2076 th.toys[id].newscene=false; 2077 th.toys[id].sceneid++; 2078 th.toys[id].ended=(th.toys[id].sceneid==data.scenes.length); 2079 if (!th.toys[id].ended) { 2080 th.toys[id].letter=0; 2081 th.toys[id].wait=false; 2082 th.toys[id].scene=data.scenes[th.toys[id].sceneid]; 2083 th.toys[id].fd=gbox.getFont((th.toys[id].scene.font?th.toys[id].scene.font:data.font)); 2084 th.toys[id].sceneH=(th.toys[id].scene.dh?th.toys[id].scene.dh:gbox.getScreenH()); 2085 th.toys[id].sceneW=(th.toys[id].scene.dw?th.toys[id].scene.dw:gbox.getScreenW()); 2086 th.toys[id].sceneX=(th.toys[id].scene.dx?th.toys[id].scene.dx:0); 2087 th.toys[id].sceneY=(th.toys[id].scene.dy?th.toys[id].scene.dy:0); 2088 gbox.blitClear(gbox.getCanvasContext("dialogue-"+id)); 2089 if (th.toys[id].scene.slide) { 2090 gbox.blitAll(gbox.getCanvasContext("dialogue-"+id),gbox.getImage(th.toys[id].scene.slide.image),{dx:th.toys[id].scene.slide.x,dy:th.toys[id].scene.slide.y}); 2091 } 2092 if (th.toys[id].scene.scroller) { 2093 gbox.createCanvas("scroller-"+id,{w:th.toys[id].sceneW,h:(th.toys[id].scene.scroller.length)*(th.toys[id].fd.tileh+th.toys[id].scene.spacing)}); 2094 for (var i=0;i<th.toys[id].scene.scroller.length;i++) 2095 gbox.blitText(gbox.getCanvasContext("scroller-"+id),{ 2096 font:th.toys[id].fd.id, 2097 dx:0, 2098 dy:i*(th.toys[id].fd.tileh+th.toys[id].scene.spacing), 2099 dw:th.toys[id].sceneW, 2100 halign:gbox.ALIGN_CENTER, 2101 text:th.toys[id].scene.scroller[i] 2102 }); 2103 } 2104 if (th.toys[id].scene.bonus) { 2105 gbox.createCanvas("bonus-"+id,{w:th.toys[id].sceneW,h:(th.toys[id].scene.bonus.length)*(th.toys[id].fd.tileh+th.toys[id].scene.spacing)}); 2106 } 2107 if (th.toys[id].scene.audiomusic) gbox.hitAudio(th.toys[id].scene.audiomusic); 2108 } 2109 } 2110 if (!th.toys[id].ended) { 2111 if (th.toys[id].wait) { 2112 if (gbox.keyIsHit(data.esckey)) th.toys[id].ended=true; else 2113 if (gbox.keyIsHit(data.skipkey)) th.toys[id].newscene=true; 2114 } else { 2115 2116 // SKIP KEYS 2117 2118 if (gbox.keyIsHit(data.esckey)) th.toys[id].ended=true; else 2119 if (gbox.keyIsHold(data.skipkey)) th.toys[id].counter=th.toys[id].scene.speed; 2120 else th.toys[id].counter++; 2121 2122 // MOVING 2123 2124 if (th.toys[id].scene.talk) { // DIALOGUES 2125 2126 2127 if (th.toys[id].counter==th.toys[id].scene.speed) { 2128 th.toys[id].letter++; 2129 th.toys[id].counter=0; 2130 if (th.toys[id].scene.audio&&!(th.toys[id].letter%3)) gbox.hitAudio(th.toys[id].scene.audio); 2131 var tmp=th.toys[id].letter; 2132 var row=0; 2133 while (tmp>th.toys[id].scene.talk[row].length) { 2134 tmp-=th.toys[id].scene.talk[row].length; 2135 row++; 2136 if (row==th.toys[id].scene.talk.length) { 2137 row=-1; 2138 break; 2139 } 2140 } 2141 if (row>=0) { 2142 gbox.blitText(gbox.getCanvasContext("dialogue-"+id),{ 2143 font:data.font, 2144 dx:data.who[th.toys[id].scene.who].x, 2145 dy:(data.who[th.toys[id].scene.who].y)+(row*th.toys[id].fd.tileh), 2146 text:th.toys[id].scene.talk[row].substr(0,tmp) 2147 }); 2148 } else 2149 th.toys[id].wait=true; 2150 } 2151 2152 } else if (th.toys[id].scene.scroller) { // SCROLLER (i.e. credits) 2153 2154 if (th.toys[id].counter==th.toys[id].scene.speed) { 2155 th.toys[id].letter++; 2156 th.toys[id].counter=0; 2157 if (th.toys[id].letter==(gbox.getCanvas("scroller-"+id).height+th.toys[id].scene.push)) 2158 th.toys[id].wait=true; 2159 } 2160 2161 } else if (th.toys[id].scene.bonus) { // BONUS (classic bonus award screen) 2162 for (var row=0;row<=th.toys[id].letter;row++) { 2163 if (th.toys[id].scene.bonus[row].text) 2164 gbox.blitText(gbox.getCanvasContext("bonus-"+id),{ 2165 font:data.font, 2166 dx:0, 2167 dy:(row*(th.toys[id].fd.tileh+th.toys[id].scene.spacing)), 2168 text:th.toys[id].scene.bonus[row].text 2169 }); 2170 else if (th.toys[id].scene.bonus[row].mul) { 2171 // Mask is %VAL%e%MUL%=%TOT% 2172 th.toys[id].scene.bonus[row].tmptext=th.toys[id].scene.bonus[row].mask.replace(/%VAL%/,th.toys[id].timer).replace(/%MUL%/,th.toys[id].scene.bonus[row].mul).replace(/%TOT%/,(th.toys[id].timer*th.toys[id].scene.bonus[row].mul)); 2173 gbox.blitText(gbox.getCanvasContext("bonus-"+id),{ 2174 clear:true, 2175 font:data.font, 2176 dx:0, 2177 dy:(row*(th.toys[id].fd.tileh+th.toys[id].scene.spacing)), 2178 text:th.toys[id].scene.bonus[row].tmptext 2179 }); 2180 } 2181 } 2182 2183 if (!th.toys[id].wait) { 2184 var next=false; 2185 if (th.toys[id].scene.bonus[th.toys[id].letter].mul&&!th.toys[id].scene.bonus[th.toys[id].letter].text) { 2186 if (th.toys[id].counter>=th.toys[id].scene.bonus[th.toys[id].letter].speed) { 2187 th.toys[id].counter=0; 2188 th.toys[id].timer++; 2189 if (th.toys[id].timer>th.toys[id].scene.bonus[th.toys[id].letter].mulvalue) { 2190 th.toys[id].scene.bonus[th.toys[id].letter].text=th.toys[id].scene.bonus[th.toys[id].letter].tmptext; 2191 next=true; 2192 } else { 2193 if (th.toys[id].scene.bonus[th.toys[id].letter].callback) 2194 th.toys[id].scene.bonus[th.toys[id].letter].callback(th.toys[id].scene.bonus[th.toys[id].letter],th.toys[id].scene.bonus[th.toys[id].letter].arg); 2195 } 2196 } 2197 2198 } else if (th.toys[id].counter>=th.toys[id].scene.speed) next=true; 2199 if (next) { 2200 if (th.toys[id].letter==th.toys[id].scene.bonus.length-1) 2201 th.toys[id].wait=true; 2202 else { 2203 th.toys[id].letter++; 2204 if (th.toys[id].scene.bonus[th.toys[id].letter].mul) { 2205 th.toys[id].scene.bonus[th.toys[id].letter].text=null; 2206 th.toys[id].scene.bonus[th.toys[id].letter].tmptext=null; 2207 th.toys[id].timer=0; 2208 } 2209 th.toys[id].counter=0; 2210 } 2211 } 2212 } 2213 } 2214 2215 } 2216 2217 } 2218 2219 // RENDERING 2220 2221 2222 if (th.toys[id].scene.talk) { // DIALOGUES 2223 if (data.who[th.toys[id].scene.who].box) 2224 gbox.blitRect(gbox.getBufferContext(),data.who[th.toys[id].scene.who].box); 2225 if (data.who[th.toys[id].scene.who].tileset) { 2226 th.toys[id].anim=(th.toys[id].anim+1)%20; 2227 gbox.blitTile(gbox.getBufferContext(),{tileset:data.who[th.toys[id].scene.who].tileset,tile:help.decideFrame(th.toys[id].anim,data.who[th.toys[id].scene.who].frames),dx:data.who[th.toys[id].scene.who].portraitx,dy:data.who[th.toys[id].scene.who].portraity,camera:false,fliph:data.who[th.toys[id].scene.who].fliph,flipv:data.who[th.toys[id].scene.who].flipv}); 2228 } 2229 gbox.blitAll(gbox.getBufferContext(),gbox.getCanvas("dialogue-"+id),{dx:0,dy:0}); 2230 } else if (th.toys[id].scene.scroller) // SCROLLER (i.e. credits) 2231 gbox.blit(gbox.getBufferContext(),gbox.getCanvas("scroller-"+id),{dx:th.toys[id].sceneX,dy:th.toys[id].sceneY+(th.toys[id].letter<th.toys[id].sceneH?th.toys[id].sceneH-th.toys[id].letter:0),dw:th.toys[id].sceneW,y:(th.toys[id].letter<th.toys[id].sceneH?0:th.toys[id].letter-th.toys[id].sceneH),dh:(th.toys[id].letter<th.toys[id].sceneH?th.toys[id].letter:th.toys[id].sceneH)}); 2232 else if (th.toys[id].scene.bonus) // BONUS (i.e. credits) 2233 gbox.blitAll(gbox.getBufferContext(),gbox.getCanvas("bonus-"+id),{dx:th.toys[id].sceneX,dy:th.toys[id].sceneY}); 2234 } 2235 return toys._toyfrombool(th,id,th.toys[id].ended); 2236 } 2237 }, 2238 2239 // GENERATORS 2240 2241 2242 /** 2243 * 2244 */ 2245 generate: { 2246 2247 /** 2248 * 2249 */ 2250 sparks:{ 2251 simple:function(th,group,id,data) { 2252 var ts=gbox.getTiles(data.tileset); 2253 if (data.frames==null) { 2254 data.frames={ speed:(data.animspeed==null?1:data.animspeed), frames:[]}; 2255 for (var i=0;i<ts.tilerow;i++) data.frames.frames[i]=i; 2256 } 2257 2258 var obj=gbox.addObject( 2259 help.mergeWithModel( 2260 data,{ 2261 id:id, 2262 group:group, 2263 x:th.x+th.hw-ts.tilehw+(data.gapx==null?0:data.gapx), 2264 y:(data.valign=="top"?th.y:th.y+th.hh-ts.tilehh+(data.gapy==null?0:data.gapy)), 2265 tileset:data.tileset, 2266 alpha:null, 2267 accx:0, accy:0, 2268 frame:0, 2269 timer:(data.delay?-data.delay:-1), 2270 frames:data.frames, 2271 toptimer:((data.frames.frames.length)*data.frames.speed)-1, 2272 camera:th.camera, 2273 gravity:false, 2274 trashoffscreen:true, 2275 fliph:(data.fliph==null?th.fliph:data.fliph), flipv:(data.flipv==null?th.flipv:data.flipv), 2276 blinkspeed:0 2277 } 2278 ) 2279 ); 2280 2281 obj[(data.logicon==null?"first":data.logicon)]=function() { 2282 this.timer++; 2283 if (this.timer>=0) { 2284 this.x+=this.accx; 2285 this.y+=this.accy; 2286 if (this.gravity) this.accy++; 2287 if ((this.timer==this.toptimer)||(this.trashoffscreen&&(!gbox.objectIsVisible(this)))) gbox.trashObject(this); 2288 } 2289 } 2290 2291 obj[(data.bliton==null?"blit":data.bliton)]=function() { 2292 if ((this.timer>=0)&&(!this.blinkspeed||(Math.floor(this.timer/this.blinkspeed)%2))) 2293 gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.timer,this.frames),dx:this.x,dy:this.y,camera:this.camera,fliph:this.fliph,flipv:this.flipv,alpha:this.alpha}); 2294 } 2295 2296 return obj; 2297 }, 2298 2299 /** 2300 * 2301 */ 2302 popupText:function(th,group,id,data) { 2303 data.text+=""; 2304 var fd=gbox.getFont(data.font); 2305 2306 var obj=gbox.addObject( 2307 help.mergeWithModel( 2308 data,{ 2309 id:id, 2310 group:group, 2311 x:Math.floor(th.x+th.hw-(fd.tilehw*data.text.length)), 2312 y:th.y-fd.tilehh, 2313 vaccy:-data.jump, 2314 font:"small", 2315 keep:0, 2316 text:data.text, 2317 cnt:0, 2318 camera:th.camera 2319 } 2320 ) 2321 ); 2322 2323 obj[(data.logicon==null?"first":data.logicon)]=function() { 2324 if (gbox.objectIsVisible(this)) { 2325 if (this.vaccy) 2326 this.vaccy++; 2327 else 2328 this.cnt++; 2329 this.y+=this.vaccy; 2330 if (this.cnt>=this.keep) gbox.trashObject(this); 2331 } else gbox.trashObject(this); 2332 } 2333 2334 obj[(data.bliton==null?"blit":data.bliton)]=function() { 2335 gbox.blitText(gbox.getBufferContext(),{font:this.font,text:this.text,dx:this.x,dy:this.y,camera:this.camera}); 2336 } 2337 2338 return obj; 2339 }, 2340 2341 /** 2342 * 2343 */ 2344 bounceDie:function(th,group,id,data){ 2345 var obj=gbox.addObject( 2346 help.mergeWithModel( 2347 data,{ 2348 id:id, 2349 group:group, 2350 tileset:th.tileset, 2351 frame:th.frame, 2352 side:th.side, 2353 frames:th.frames.die, 2354 x:th.x, 2355 y:th.y, 2356 vaccy:-data.jump, 2357 accx:0, 2358 flipv:data.flipv, 2359 cnt:0, 2360 blinkspeed:0, 2361 camera:th.camera 2362 } 2363 ) 2364 ); 2365 2366 obj[(data.logicon==null?"first":data.logicon)]=function() { 2367 if (gbox.objectIsVisible(this)) { 2368 this.vaccy++; 2369 this.y+=this.vaccy; 2370 this.x+=this.accx; 2371 this.cnt++; 2372 } else gbox.trashObject(this); 2373 } 2374 2375 obj[(data.bliton==null?"blit":data.bliton)]=function() { 2376 if (!this.blinkspeed||(Math.floor(this.cnt/this.blinkspeed)%2)) 2377 gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.cnt,this.frames),dx:this.x,dy:this.y,camera:this.camera,fliph:this.side,flipv:this.flipv}); 2378 } 2379 2380 return obj; 2381 } 2382 }, 2383 2384 /** 2385 * 2386 */ 2387 audio:{ 2388 2389 /** 2390 * 2391 */ 2392 fadeOut:function(th,group,id,data){ 2393 var obj=gbox.addObject( 2394 help.mergeWithModel( 2395 data,{ 2396 id:id, 2397 group:group, 2398 fadespeed:-0.02*(data.fadein?-1:1), 2399 stoponmute:true, 2400 audio:null, 2401 channel:null, 2402 destination:null 2403 } 2404 ) 2405 ); 2406 2407 obj[(data.logicon==null?"first":data.logicon)]=function() { 2408 if (this.destination==null) 2409 if (this.audio) 2410 if (this.fadespeed>0) this.destination=1; else this.destination=0; 2411 else 2412 if (this.fadespeed>0) this.destination=gbox.getChannelDefaultVolume(this.channel); else this.destination=0; 2413 if (this.fadespeed>0) gbox.playAudio(this.audio); 2414 } 2415 2416 obj[(data.bliton==null?"blit":data.bliton)]=function() { 2417 if (this.audio) gbox.changeAudioVolume(this.audio,this.fadespeed); 2418 if (this.channel) gbox.changeChannelVolume(this.channel,this.fadespeed); 2419 if ( 2420 (this.audio&&( 2421 ((this.fadespeed<0)&&(gbox.getAudioVolume(this.audio)<=this.destination))|| 2422 ((this.fadespeed>0)&&(gbox.getAudioVolume(this.audio)>=this.destination)) 2423 ))|| 2424 (this.channel&&( 2425 ((this.fadespeed<0)&&(gbox.getChannelVolume(this.channel)<=this.destination))|| 2426 ((this.fadespeed>0)&&(gbox.getChannelVolume(this.channel)>=this.destination)) 2427 )) 2428 ) { 2429 if (this.channel&&this.stoponmute&&(this.fadespeed<0)) gbox.stopChannel(this.channel); 2430 if (this.audio&&this.stoponmute&&(this.fadespeed<0)) gbox.stopAudio(this.audio); 2431 gbox.trashObject(this); 2432 } 2433 } 2434 } 2435 2436 } 2437 2438 } 2439 2440 2441 } 2442