PageRenderTime 3177ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/org/flixel/FlxG.as

http://github.com/AdamAtomic/flixel
ActionScript | 1256 lines | 666 code | 83 blank | 507 comment | 141 complexity | adbd3454013b96558257b5a10b725cba MD5 | raw file
  1. package org.flixel
  2. {
  3. import flash.display.BitmapData;
  4. import flash.display.Graphics;
  5. import flash.display.Sprite;
  6. import flash.display.Stage;
  7. import flash.geom.Matrix;
  8. import flash.geom.Point;
  9. import flash.geom.Rectangle;
  10. import org.flixel.plugin.DebugPathDisplay;
  11. import org.flixel.plugin.TimerManager;
  12. import org.flixel.system.FlxDebugger;
  13. import org.flixel.system.FlxQuadTree;
  14. import org.flixel.system.input.*;
  15. /**
  16. * This is a global helper class full of useful functions for audio,
  17. * input, basic info, and the camera system among other things.
  18. * Utilities for maths and color and things can be found in <code>FlxU</code>.
  19. * <code>FlxG</code> is specifically for Flixel-specific properties.
  20. *
  21. * @author Adam Atomic
  22. */
  23. public class FlxG
  24. {
  25. /**
  26. * If you build and maintain your own version of flixel,
  27. * you can give it your own name here.
  28. */
  29. static public var LIBRARY_NAME:String = "flixel";
  30. /**
  31. * Assign a major version to your library.
  32. * Appears before the decimal in the console.
  33. */
  34. static public var LIBRARY_MAJOR_VERSION:uint = 2;
  35. /**
  36. * Assign a minor version to your library.
  37. * Appears after the decimal in the console.
  38. */
  39. static public var LIBRARY_MINOR_VERSION:uint = 55;
  40. /**
  41. * Debugger overlay layout preset: Wide but low windows at the bottom of the screen.
  42. */
  43. static public const DEBUGGER_STANDARD:uint = 0;
  44. /**
  45. * Debugger overlay layout preset: Tiny windows in the screen corners.
  46. */
  47. static public const DEBUGGER_MICRO:uint = 1;
  48. /**
  49. * Debugger overlay layout preset: Large windows taking up bottom half of screen.
  50. */
  51. static public const DEBUGGER_BIG:uint = 2;
  52. /**
  53. * Debugger overlay layout preset: Wide but low windows at the top of the screen.
  54. */
  55. static public const DEBUGGER_TOP:uint = 3;
  56. /**
  57. * Debugger overlay layout preset: Large windows taking up left third of screen.
  58. */
  59. static public const DEBUGGER_LEFT:uint = 4;
  60. /**
  61. * Debugger overlay layout preset: Large windows taking up right third of screen.
  62. */
  63. static public const DEBUGGER_RIGHT:uint = 5;
  64. /**
  65. * Some handy color presets. Less glaring than pure RGB full values.
  66. * Primarily used in the visual debugger mode for bounding box displays.
  67. * Red is used to indicate an active, movable, solid object.
  68. */
  69. static public const RED:uint = 0xffff0012;
  70. /**
  71. * Green is used to indicate solid but immovable objects.
  72. */
  73. static public const GREEN:uint = 0xff00f225;
  74. /**
  75. * Blue is used to indicate non-solid objects.
  76. */
  77. static public const BLUE:uint = 0xff0090e9;
  78. /**
  79. * Pink is used to indicate objects that are only partially solid, like one-way platforms.
  80. */
  81. static public const PINK:uint = 0xfff01eff;
  82. /**
  83. * White... for white stuff.
  84. */
  85. static public const WHITE:uint = 0xffffffff;
  86. /**
  87. * And black too.
  88. */
  89. static public const BLACK:uint = 0xff000000;
  90. /**
  91. * Internal tracker for game object.
  92. */
  93. static internal var _game:FlxGame;
  94. /**
  95. * Handy shared variable for implementing your own pause behavior.
  96. */
  97. static public var paused:Boolean;
  98. /**
  99. * Whether you are running in Debug or Release mode.
  100. * Set automatically by <code>FlxPreloader</code> during startup.
  101. */
  102. static public var debug:Boolean;
  103. /**
  104. * Represents the amount of time in seconds that passed since last frame.
  105. */
  106. static public var elapsed:Number;
  107. /**
  108. * How fast or slow time should pass in the game; default is 1.0.
  109. */
  110. static public var timeScale:Number;
  111. /**
  112. * The width of the screen in game pixels.
  113. */
  114. static public var width:uint;
  115. /**
  116. * The height of the screen in game pixels.
  117. */
  118. static public var height:uint;
  119. /**
  120. * The dimensions of the game world, used by the quad tree for collisions and overlap checks.
  121. */
  122. static public var worldBounds:FlxRect;
  123. /**
  124. * How many times the quad tree should divide the world on each axis.
  125. * Generally, sparse collisions can have fewer divisons,
  126. * while denser collision activity usually profits from more.
  127. * Default value is 6.
  128. */
  129. static public var worldDivisions:uint;
  130. /**
  131. * Whether to show visual debug displays or not.
  132. * Default = false.
  133. */
  134. static public var visualDebug:Boolean;
  135. /**
  136. * Setting this to true will disable/skip stuff that isn't necessary for mobile platforms like Android. [BETA]
  137. */
  138. static public var mobile:Boolean;
  139. /**
  140. * The global random number generator seed (for deterministic behavior in recordings and saves).
  141. */
  142. static public var globalSeed:Number;
  143. /**
  144. * <code>FlxG.levels</code> and <code>FlxG.scores</code> are generic
  145. * global variables that can be used for various cross-state stuff.
  146. */
  147. static public var levels:Array;
  148. static public var level:int;
  149. static public var scores:Array;
  150. static public var score:int;
  151. /**
  152. * <code>FlxG.saves</code> is a generic bucket for storing
  153. * FlxSaves so you can access them whenever you want.
  154. */
  155. static public var saves:Array;
  156. static public var save:int;
  157. /**
  158. * A reference to a <code>FlxMouse</code> object. Important for input!
  159. */
  160. static public var mouse:Mouse;
  161. /**
  162. * A reference to a <code>FlxKeyboard</code> object. Important for input!
  163. */
  164. static public var keys:Keyboard;
  165. /**
  166. * A handy container for a background music object.
  167. */
  168. static public var music:FlxSound;
  169. /**
  170. * A list of all the sounds being played in the game.
  171. */
  172. static public var sounds:FlxGroup;
  173. /**
  174. * Whether or not the game sounds are muted.
  175. */
  176. static public var mute:Boolean;
  177. /**
  178. * Internal volume level, used for global sound control.
  179. */
  180. static protected var _volume:Number;
  181. /**
  182. * An array of <code>FlxCamera</code> objects that are used to draw stuff.
  183. * By default flixel creates one camera the size of the screen.
  184. */
  185. static public var cameras:Array;
  186. /**
  187. * By default this just refers to the first entry in the cameras array
  188. * declared above, but you can do what you like with it.
  189. */
  190. static public var camera:FlxCamera;
  191. /**
  192. * Allows you to possibly slightly optimize the rendering process IF
  193. * you are not doing any pre-processing in your game state's <code>draw()</code> call.
  194. * @default false
  195. */
  196. static public var useBufferLocking:Boolean;
  197. /**
  198. * Internal helper variable for clearing the cameras each frame.
  199. */
  200. static protected var _cameraRect:Rectangle;
  201. /**
  202. * An array container for plugins.
  203. * By default flixel uses a couple of plugins:
  204. * DebugPathDisplay, and TimerManager.
  205. */
  206. static public var plugins:Array;
  207. /**
  208. * Set this hook to get a callback whenever the volume changes.
  209. * Function should take the form <code>myVolumeHandler(Volume:Number)</code>.
  210. */
  211. static public var volumeHandler:Function;
  212. /**
  213. * Useful helper objects for doing Flash-specific rendering.
  214. * Primarily used for "debug visuals" like drawing bounding boxes directly to the screen buffer.
  215. */
  216. static public var flashGfxSprite:Sprite;
  217. static public var flashGfx:Graphics;
  218. /**
  219. * Internal storage system to prevent graphics from being used repeatedly in memory.
  220. */
  221. static protected var _cache:Object;
  222. static public function getLibraryName():String
  223. {
  224. return FlxG.LIBRARY_NAME + " v" + FlxG.LIBRARY_MAJOR_VERSION + "." + FlxG.LIBRARY_MINOR_VERSION;
  225. }
  226. /**
  227. * Log data to the debugger.
  228. *
  229. * @param Data Anything you want to log to the console.
  230. */
  231. static public function log(Data:Object):void
  232. {
  233. if((_game != null) && (_game._debugger != null))
  234. _game._debugger.log.add((Data == null)?"ERROR: null object":Data.toString());
  235. }
  236. /**
  237. * Add a variable to the watch list in the debugger.
  238. * This lets you see the value of the variable all the time.
  239. *
  240. * @param AnyObject A reference to any object in your game, e.g. Player or Robot or this.
  241. * @param VariableName The name of the variable you want to watch, in quotes, as a string: e.g. "speed" or "health".
  242. * @param DisplayName Optional, display your own string instead of the class name + variable name: e.g. "enemy count".
  243. */
  244. static public function watch(AnyObject:Object,VariableName:String,DisplayName:String=null):void
  245. {
  246. if((_game != null) && (_game._debugger != null))
  247. _game._debugger.watch.add(AnyObject,VariableName,DisplayName);
  248. }
  249. /**
  250. * Remove a variable from the watch list in the debugger.
  251. * Don't pass a Variable Name to remove all watched variables for the specified object.
  252. *
  253. * @param AnyObject A reference to any object in your game, e.g. Player or Robot or this.
  254. * @param VariableName The name of the variable you want to watch, in quotes, as a string: e.g. "speed" or "health".
  255. */
  256. static public function unwatch(AnyObject:Object,VariableName:String=null):void
  257. {
  258. if((_game != null) && (_game._debugger != null))
  259. _game._debugger.watch.remove(AnyObject,VariableName);
  260. }
  261. /**
  262. * How many times you want your game to update each second.
  263. * More updates usually means better collisions and smoother motion.
  264. * NOTE: This is NOT the same thing as the Flash Player framerate!
  265. */
  266. static public function get framerate():Number
  267. {
  268. return 1000/_game._step;
  269. }
  270. /**
  271. * @private
  272. */
  273. static public function set framerate(Framerate:Number):void
  274. {
  275. _game._step = 1000/Framerate;
  276. if(_game._maxAccumulation < _game._step)
  277. _game._maxAccumulation = _game._step;
  278. }
  279. /**
  280. * How many times you want your game to update each second.
  281. * More updates usually means better collisions and smoother motion.
  282. * NOTE: This is NOT the same thing as the Flash Player framerate!
  283. */
  284. static public function get flashFramerate():Number
  285. {
  286. if(_game.root != null)
  287. return _game.stage.frameRate;
  288. else
  289. return 0;
  290. }
  291. /**
  292. * @private
  293. */
  294. static public function set flashFramerate(Framerate:Number):void
  295. {
  296. _game._flashFramerate = Framerate;
  297. if(_game.root != null)
  298. _game.stage.frameRate = _game._flashFramerate;
  299. _game._maxAccumulation = 2000/_game._flashFramerate - 1;
  300. if(_game._maxAccumulation < _game._step)
  301. _game._maxAccumulation = _game._step;
  302. }
  303. /**
  304. * Generates a random number. Deterministic, meaning safe
  305. * to use if you want to record replays in random environments.
  306. *
  307. * @return A <code>Number</code> between 0 and 1.
  308. */
  309. static public function random():Number
  310. {
  311. return globalSeed = FlxU.srand(globalSeed);
  312. }
  313. /**
  314. * Shuffles the entries in an array into a new random order.
  315. * <code>FlxG.shuffle()</code> is deterministic and safe for use with replays/recordings.
  316. * HOWEVER, <code>FlxU.shuffle()</code> is NOT deterministic and unsafe for use with replays/recordings.
  317. *
  318. * @param A A Flash <code>Array</code> object containing...stuff.
  319. * @param HowManyTimes How many swaps to perform during the shuffle operation. Good rule of thumb is 2-4 times as many objects are in the list.
  320. *
  321. * @return The same Flash <code>Array</code> object that you passed in in the first place.
  322. */
  323. static public function shuffle(Objects:Array,HowManyTimes:uint):Array
  324. {
  325. var i:uint = 0;
  326. var index1:uint;
  327. var index2:uint;
  328. var object:Object;
  329. while(i < HowManyTimes)
  330. {
  331. index1 = FlxG.random()*Objects.length;
  332. index2 = FlxG.random()*Objects.length;
  333. object = Objects[index2];
  334. Objects[index2] = Objects[index1];
  335. Objects[index1] = object;
  336. i++;
  337. }
  338. return Objects;
  339. }
  340. /**
  341. * Fetch a random entry from the given array.
  342. * Will return null if random selection is missing, or array has no entries.
  343. * <code>FlxG.getRandom()</code> is deterministic and safe for use with replays/recordings.
  344. * HOWEVER, <code>FlxU.getRandom()</code> is NOT deterministic and unsafe for use with replays/recordings.
  345. *
  346. * @param Objects A Flash array of objects.
  347. * @param StartIndex Optional offset off the front of the array. Default value is 0, or the beginning of the array.
  348. * @param Length Optional restriction on the number of values you want to randomly select from.
  349. *
  350. * @return The random object that was selected.
  351. */
  352. static public function getRandom(Objects:Array,StartIndex:uint=0,Length:uint=0):Object
  353. {
  354. if(Objects != null)
  355. {
  356. var l:uint = Length;
  357. if((l == 0) || (l > Objects.length - StartIndex))
  358. l = Objects.length - StartIndex;
  359. if(l > 0)
  360. return Objects[StartIndex + uint(FlxG.random()*l)];
  361. }
  362. return null;
  363. }
  364. /**
  365. * Load replay data from a string and play it back.
  366. *
  367. * @param Data The replay that you want to load.
  368. * @param State Optional parameter: if you recorded a state-specific demo or cutscene, pass a new instance of that state here.
  369. * @param CancelKeys Optional parameter: an array of string names of keys (see FlxKeyboard) that can be pressed to cancel the playback, e.g. ["ESCAPE","ENTER"]. Also accepts 2 custom key names: "ANY" and "MOUSE" (fairly self-explanatory I hope!).
  370. * @param Timeout Optional parameter: set a time limit for the replay. CancelKeys will override this if pressed.
  371. * @param Callback Optional parameter: if set, called when the replay finishes. Running to the end, CancelKeys, and Timeout will all trigger Callback(), but only once, and CancelKeys and Timeout will NOT call FlxG.stopReplay() if Callback is set!
  372. */
  373. static public function loadReplay(Data:String,State:FlxState=null,CancelKeys:Array=null,Timeout:Number=0,Callback:Function=null):void
  374. {
  375. _game._replay.load(Data);
  376. if(State == null)
  377. FlxG.resetGame();
  378. else
  379. FlxG.switchState(State);
  380. _game._replayCancelKeys = CancelKeys;
  381. _game._replayTimer = Timeout*1000;
  382. _game._replayCallback = Callback;
  383. _game._replayRequested = true;
  384. }
  385. /**
  386. * Resets the game or state and replay requested flag.
  387. *
  388. * @param StandardMode If true, reload entire game, else just reload current game state.
  389. */
  390. static public function reloadReplay(StandardMode:Boolean=true):void
  391. {
  392. if(StandardMode)
  393. FlxG.resetGame();
  394. else
  395. FlxG.resetState();
  396. if(_game._replay.frameCount > 0)
  397. _game._replayRequested = true;
  398. }
  399. /**
  400. * Stops the current replay.
  401. */
  402. static public function stopReplay():void
  403. {
  404. _game._replaying = false;
  405. if(_game._debugger != null)
  406. _game._debugger.vcr.stopped();
  407. resetInput();
  408. }
  409. /**
  410. * Resets the game or state and requests a new recording.
  411. *
  412. * @param StandardMode If true, reset the entire game, else just reset the current state.
  413. */
  414. static public function recordReplay(StandardMode:Boolean=true):void
  415. {
  416. if(StandardMode)
  417. FlxG.resetGame();
  418. else
  419. FlxG.resetState();
  420. _game._recordingRequested = true;
  421. }
  422. /**
  423. * Stop recording the current replay and return the replay data.
  424. *
  425. * @return The replay data in simple ASCII format (see <code>FlxReplay.save()</code>).
  426. */
  427. static public function stopRecording():String
  428. {
  429. _game._recording = false;
  430. if(_game._debugger != null)
  431. _game._debugger.vcr.stopped();
  432. return _game._replay.save();
  433. }
  434. /**
  435. * Request a reset of the current game state.
  436. */
  437. static public function resetState():void
  438. {
  439. _game._requestedState = new (FlxU.getClass(FlxU.getClassName(_game._state,false)))();
  440. }
  441. /**
  442. * Like hitting the reset button on a game console, this will re-launch the game as if it just started.
  443. */
  444. static public function resetGame():void
  445. {
  446. _game._requestedReset = true;
  447. }
  448. /**
  449. * Reset the input helper objects (useful when changing screens or states)
  450. */
  451. static public function resetInput():void
  452. {
  453. keys.reset();
  454. mouse.reset();
  455. }
  456. /**
  457. * Set up and play a looping background soundtrack.
  458. *
  459. * @param Music The sound file you want to loop in the background.
  460. * @param Volume How loud the sound should be, from 0 to 1.
  461. */
  462. static public function playMusic(Music:Class,Volume:Number=1.0):void
  463. {
  464. if(music == null)
  465. music = new FlxSound();
  466. else if(music.active)
  467. music.stop();
  468. music.loadEmbedded(Music,true);
  469. music.volume = Volume;
  470. music.survive = true;
  471. music.play();
  472. }
  473. /**
  474. * Creates a new sound object.
  475. *
  476. * @param EmbeddedSound The embedded sound resource you want to play. To stream, use the optional URL parameter instead.
  477. * @param Volume How loud to play it (0 to 1).
  478. * @param Looped Whether to loop this sound.
  479. * @param AutoDestroy Whether to destroy this sound when it finishes playing. Leave this value set to "false" if you want to re-use this <code>FlxSound</code> instance.
  480. * @param AutoPlay Whether to play the sound.
  481. * @param URL Load a sound from an external web resource instead. Only used if EmbeddedSound = null.
  482. *
  483. * @return A <code>FlxSound</code> object.
  484. */
  485. static public function loadSound(EmbeddedSound:Class=null,Volume:Number=1.0,Looped:Boolean=false,AutoDestroy:Boolean=false,AutoPlay:Boolean=false,URL:String=null):FlxSound
  486. {
  487. if((EmbeddedSound == null) && (URL == null))
  488. {
  489. FlxG.log("WARNING: FlxG.loadSound() requires either\nan embedded sound or a URL to work.");
  490. return null;
  491. }
  492. var sound:FlxSound = sounds.recycle(FlxSound) as FlxSound;
  493. if(EmbeddedSound != null)
  494. sound.loadEmbedded(EmbeddedSound,Looped,AutoDestroy);
  495. else
  496. sound.loadStream(URL,Looped,AutoDestroy);
  497. sound.volume = Volume;
  498. if(AutoPlay)
  499. sound.play();
  500. return sound;
  501. }
  502. /**
  503. * Creates a new sound object from an embedded <code>Class</code> object.
  504. * NOTE: Just calls FlxG.loadSound() with AutoPlay == true.
  505. *
  506. * @param EmbeddedSound The sound you want to play.
  507. * @param Volume How loud to play it (0 to 1).
  508. * @param Looped Whether to loop this sound.
  509. * @param AutoDestroy Whether to destroy this sound when it finishes playing. Leave this value set to "false" if you want to re-use this <code>FlxSound</code> instance.
  510. *
  511. * @return A <code>FlxSound</code> object.
  512. */
  513. static public function play(EmbeddedSound:Class,Volume:Number=1.0,Looped:Boolean=false,AutoDestroy:Boolean=true):FlxSound
  514. {
  515. return FlxG.loadSound(EmbeddedSound,Volume,Looped,AutoDestroy,true);
  516. }
  517. /**
  518. * Creates a new sound object from a URL.
  519. * NOTE: Just calls FlxG.loadSound() with AutoPlay == true.
  520. *
  521. * @param URL The URL of the sound you want to play.
  522. * @param Volume How loud to play it (0 to 1).
  523. * @param Looped Whether or not to loop this sound.
  524. * @param AutoDestroy Whether to destroy this sound when it finishes playing. Leave this value set to "false" if you want to re-use this <code>FlxSound</code> instance.
  525. *
  526. * @return A FlxSound object.
  527. */
  528. static public function stream(URL:String,Volume:Number=1.0,Looped:Boolean=false,AutoDestroy:Boolean=true):FlxSound
  529. {
  530. return FlxG.loadSound(null,Volume,Looped,AutoDestroy,true,URL);
  531. }
  532. /**
  533. * Set <code>volume</code> to a number between 0 and 1 to change the global volume.
  534. *
  535. * @default 0.5
  536. */
  537. static public function get volume():Number
  538. {
  539. return _volume;
  540. }
  541. /**
  542. * @private
  543. */
  544. static public function set volume(Volume:Number):void
  545. {
  546. _volume = Volume;
  547. if(_volume < 0)
  548. _volume = 0;
  549. else if(_volume > 1)
  550. _volume = 1;
  551. if(volumeHandler != null)
  552. volumeHandler(FlxG.mute?0:_volume);
  553. }
  554. /**
  555. * Called by FlxGame on state changes to stop and destroy sounds.
  556. *
  557. * @param ForceDestroy Kill sounds even if they're flagged <code>survive</code>.
  558. */
  559. static internal function destroySounds(ForceDestroy:Boolean=false):void
  560. {
  561. if((music != null) && (ForceDestroy || !music.survive))
  562. {
  563. music.destroy();
  564. music = null;
  565. }
  566. var i:uint = 0;
  567. var sound:FlxSound;
  568. var l:uint = sounds.members.length;
  569. while(i < l)
  570. {
  571. sound = sounds.members[i++] as FlxSound;
  572. if((sound != null) && (ForceDestroy || !sound.survive))
  573. sound.destroy();
  574. }
  575. }
  576. /**
  577. * Called by the game loop to make sure the sounds get updated each frame.
  578. */
  579. static internal function updateSounds():void
  580. {
  581. if((music != null) && music.active)
  582. music.update();
  583. if((sounds != null) && sounds.active)
  584. sounds.update();
  585. }
  586. /**
  587. * Pause all sounds currently playing.
  588. */
  589. static public function pauseSounds():void
  590. {
  591. if((music != null) && music.exists && music.active)
  592. music.pause();
  593. var i:uint = 0;
  594. var sound:FlxSound;
  595. var l:uint = sounds.length;
  596. while(i < l)
  597. {
  598. sound = sounds.members[i++] as FlxSound;
  599. if((sound != null) && sound.exists && sound.active)
  600. sound.pause();
  601. }
  602. }
  603. /**
  604. * Resume playing existing sounds.
  605. */
  606. static public function resumeSounds():void
  607. {
  608. if((music != null) && music.exists)
  609. music.play();
  610. var i:uint = 0;
  611. var sound:FlxSound;
  612. var l:uint = sounds.length;
  613. while(i < l)
  614. {
  615. sound = sounds.members[i++] as FlxSound;
  616. if((sound != null) && sound.exists)
  617. sound.resume();
  618. }
  619. }
  620. /**
  621. * Check the local bitmap cache to see if a bitmap with this key has been loaded already.
  622. *
  623. * @param Key The string key identifying the bitmap.
  624. *
  625. * @return Whether or not this file can be found in the cache.
  626. */
  627. static public function checkBitmapCache(Key:String):Boolean
  628. {
  629. return (_cache[Key] != undefined) && (_cache[Key] != null);
  630. }
  631. /**
  632. * Generates a new <code>BitmapData</code> object (a colored square) and caches it.
  633. *
  634. * @param Width How wide the square should be.
  635. * @param Height How high the square should be.
  636. * @param Color What color the square should be (0xAARRGGBB)
  637. * @param Unique Ensures that the bitmap data uses a new slot in the cache.
  638. * @param Key Force the cache to use a specific Key to index the bitmap.
  639. *
  640. * @return The <code>BitmapData</code> we just created.
  641. */
  642. static public function createBitmap(Width:uint, Height:uint, Color:uint, Unique:Boolean=false, Key:String=null):BitmapData
  643. {
  644. if(Key == null)
  645. {
  646. Key = Width+"x"+Height+":"+Color;
  647. if(Unique && checkBitmapCache(Key))
  648. {
  649. var inc:uint = 0;
  650. var ukey:String;
  651. do
  652. {
  653. ukey = Key + inc++;
  654. } while(checkBitmapCache(ukey));
  655. Key = ukey;
  656. }
  657. }
  658. if(!checkBitmapCache(Key))
  659. _cache[Key] = new BitmapData(Width,Height,true,Color);
  660. return _cache[Key];
  661. }
  662. /**
  663. * Loads a bitmap from a file, caches it, and generates a horizontally flipped version if necessary.
  664. *
  665. * @param Graphic The image file that you want to load.
  666. * @param Reverse Whether to generate a flipped version.
  667. * @param Unique Ensures that the bitmap data uses a new slot in the cache.
  668. * @param Key Force the cache to use a specific Key to index the bitmap.
  669. *
  670. * @return The <code>BitmapData</code> we just created.
  671. */
  672. static public function addBitmap(Graphic:Class, Reverse:Boolean=false, Unique:Boolean=false, Key:String=null):BitmapData
  673. {
  674. var needReverse:Boolean = false;
  675. if(Key == null)
  676. {
  677. Key = String(Graphic)+(Reverse?"_REVERSE_":"");
  678. if(Unique && checkBitmapCache(Key))
  679. {
  680. var inc:uint = 0;
  681. var ukey:String;
  682. do
  683. {
  684. ukey = Key + inc++;
  685. } while(checkBitmapCache(ukey));
  686. Key = ukey;
  687. }
  688. }
  689. //If there is no data for this key, generate the requested graphic
  690. if(!checkBitmapCache(Key))
  691. {
  692. _cache[Key] = (new Graphic).bitmapData;
  693. if(Reverse)
  694. needReverse = true;
  695. }
  696. var pixels:BitmapData = _cache[Key];
  697. if(!needReverse && Reverse && (pixels.width == (new Graphic).bitmapData.width))
  698. needReverse = true;
  699. if(needReverse)
  700. {
  701. var newPixels:BitmapData = new BitmapData(pixels.width<<1,pixels.height,true,0x00000000);
  702. newPixels.draw(pixels);
  703. var mtx:Matrix = new Matrix();
  704. mtx.scale(-1,1);
  705. mtx.translate(newPixels.width,0);
  706. newPixels.draw(pixels,mtx);
  707. pixels = newPixels;
  708. _cache[Key] = pixels;
  709. }
  710. return pixels;
  711. }
  712. /**
  713. * Dumps the cache's image references.
  714. */
  715. static public function clearBitmapCache():void
  716. {
  717. _cache = new Object();
  718. }
  719. /**
  720. * Read-only: retrieves the Flash stage object (required for event listeners)
  721. * Will be null if it's not safe/useful yet.
  722. */
  723. static public function get stage():Stage
  724. {
  725. if(_game.root != null)
  726. return _game.stage;
  727. return null;
  728. }
  729. /**
  730. * Read-only: access the current game state from anywhere.
  731. */
  732. static public function get state():FlxState
  733. {
  734. return _game._state;
  735. }
  736. /**
  737. * Switch from the current game state to the one specified here.
  738. */
  739. static public function switchState(State:FlxState):void
  740. {
  741. _game._requestedState = State;
  742. }
  743. /**
  744. * Change the way the debugger's windows are laid out.
  745. *
  746. * @param Layout See the presets above (e.g. <code>DEBUGGER_MICRO</code>, etc).
  747. */
  748. static public function setDebuggerLayout(Layout:uint):void
  749. {
  750. if(_game._debugger != null)
  751. _game._debugger.setLayout(Layout);
  752. }
  753. /**
  754. * Just resets the debugger windows to whatever the last selected layout was (<code>DEBUGGER_STANDARD</code> by default).
  755. */
  756. static public function resetDebuggerLayout():void
  757. {
  758. if(_game._debugger != null)
  759. _game._debugger.resetLayout();
  760. }
  761. /**
  762. * Add a new camera object to the game.
  763. * Handy for PiP, split-screen, etc.
  764. *
  765. * @param NewCamera The camera you want to add.
  766. *
  767. * @return This <code>FlxCamera</code> instance.
  768. */
  769. static public function addCamera(NewCamera:FlxCamera):FlxCamera
  770. {
  771. FlxG._game.addChildAt(NewCamera._flashSprite,FlxG._game.getChildIndex(FlxG._game._mouse));
  772. FlxG.cameras.push(NewCamera);
  773. return NewCamera;
  774. }
  775. /**
  776. * Remove a camera from the game.
  777. *
  778. * @param Camera The camera you want to remove.
  779. * @param Destroy Whether to call destroy() on the camera, default value is true.
  780. */
  781. static public function removeCamera(Camera:FlxCamera,Destroy:Boolean=true):void
  782. {
  783. try
  784. {
  785. FlxG._game.removeChild(Camera._flashSprite);
  786. }
  787. catch(E:Error)
  788. {
  789. FlxG.log("Error removing camera, not part of game.");
  790. }
  791. if(Destroy)
  792. Camera.destroy();
  793. }
  794. /**
  795. * Dumps all the current cameras and resets to just one camera.
  796. * Handy for doing split-screen especially.
  797. *
  798. * @param NewCamera Optional; specify a specific camera object to be the new main camera.
  799. */
  800. static public function resetCameras(NewCamera:FlxCamera=null):void
  801. {
  802. var cam:FlxCamera;
  803. var i:uint = 0;
  804. var l:uint = cameras.length;
  805. while(i < l)
  806. {
  807. cam = FlxG.cameras[i++] as FlxCamera;
  808. FlxG._game.removeChild(cam._flashSprite);
  809. cam.destroy();
  810. }
  811. FlxG.cameras.length = 0;
  812. if(NewCamera == null)
  813. NewCamera = new FlxCamera(0,0,FlxG.width,FlxG.height)
  814. FlxG.camera = FlxG.addCamera(NewCamera);
  815. }
  816. /**
  817. * All screens are filled with this color and gradually return to normal.
  818. *
  819. * @param Color The color you want to use.
  820. * @param Duration How long it takes for the flash to fade.
  821. * @param OnComplete A function you want to run when the flash finishes.
  822. * @param Force Force the effect to reset.
  823. */
  824. static public function flash(Color:uint=0xffffffff, Duration:Number=1, OnComplete:Function=null, Force:Boolean=false):void
  825. {
  826. var i:uint = 0;
  827. var l:uint = FlxG.cameras.length;
  828. while(i < l)
  829. (FlxG.cameras[i++] as FlxCamera).flash(Color,Duration,OnComplete,Force);
  830. }
  831. /**
  832. * The screen is gradually filled with this color.
  833. *
  834. * @param Color The color you want to use.
  835. * @param Duration How long it takes for the fade to finish.
  836. * @param OnComplete A function you want to run when the fade finishes.
  837. * @param Force Force the effect to reset.
  838. */
  839. static public function fade(Color:uint=0xff000000, Duration:Number=1, OnComplete:Function=null, Force:Boolean=false):void
  840. {
  841. var i:uint = 0;
  842. var l:uint = FlxG.cameras.length;
  843. while(i < l)
  844. (FlxG.cameras[i++] as FlxCamera).fade(Color,Duration,OnComplete,Force);
  845. }
  846. /**
  847. * A simple screen-shake effect.
  848. *
  849. * @param Intensity Percentage of screen size representing the maximum distance that the screen can move while shaking.
  850. * @param Duration The length in seconds that the shaking effect should last.
  851. * @param OnComplete A function you want to run when the shake effect finishes.
  852. * @param Force Force the effect to reset (default = true, unlike flash() and fade()!).
  853. * @param Direction Whether to shake on both axes, just up and down, or just side to side (use class constants SHAKE_BOTH_AXES, SHAKE_VERTICAL_ONLY, or SHAKE_HORIZONTAL_ONLY). Default value is SHAKE_BOTH_AXES (0).
  854. */
  855. static public function shake(Intensity:Number=0.05, Duration:Number=0.5, OnComplete:Function=null, Force:Boolean=true, Direction:uint=0):void
  856. {
  857. var i:uint = 0;
  858. var l:uint = FlxG.cameras.length;
  859. while(i < l)
  860. (FlxG.cameras[i++] as FlxCamera).shake(Intensity,Duration,OnComplete,Force,Direction);
  861. }
  862. /**
  863. * Get and set the background color of the game.
  864. * Get functionality is equivalent to FlxG.camera.bgColor.
  865. * Set functionality sets the background color of all the current cameras.
  866. */
  867. static public function get bgColor():uint
  868. {
  869. if(FlxG.camera == null)
  870. return 0xff000000;
  871. else
  872. return FlxG.camera.bgColor;
  873. }
  874. static public function set bgColor(Color:uint):void
  875. {
  876. var i:uint = 0;
  877. var l:uint = FlxG.cameras.length;
  878. while(i < l)
  879. (FlxG.cameras[i++] as FlxCamera).bgColor = Color;
  880. }
  881. /**
  882. * Call this function to see if one <code>FlxObject</code> overlaps another.
  883. * Can be called with one object and one group, or two groups, or two objects,
  884. * whatever floats your boat! For maximum performance try bundling a lot of objects
  885. * together using a <code>FlxGroup</code> (or even bundling groups together!).
  886. *
  887. * <p>NOTE: does NOT take objects' scrollfactor into account, all overlaps are checked in world space.</p>
  888. *
  889. * @param ObjectOrGroup1 The first object or group you want to check.
  890. * @param ObjectOrGroup2 The second object or group you want to check. If it is the same as the first, flixel knows to just do a comparison within that group.
  891. * @param NotifyCallback A function with two <code>FlxObject</code> parameters - e.g. <code>myOverlapFunction(Object1:FlxObject,Object2:FlxObject)</code> - that is called if those two objects overlap.
  892. * @param ProcessCallback A function with two <code>FlxObject</code> parameters - e.g. <code>myOverlapFunction(Object1:FlxObject,Object2:FlxObject)</code> - that is called if those two objects overlap. If a ProcessCallback is provided, then NotifyCallback will only be called if ProcessCallback returns true for those objects!
  893. *
  894. * @return Whether any oevrlaps were detected.
  895. */
  896. static public function overlap(ObjectOrGroup1:FlxBasic=null,ObjectOrGroup2:FlxBasic=null,NotifyCallback:Function=null,ProcessCallback:Function=null):Boolean
  897. {
  898. if(ObjectOrGroup1 == null)
  899. ObjectOrGroup1 = FlxG.state;
  900. if(ObjectOrGroup2 === ObjectOrGroup1)
  901. ObjectOrGroup2 = null;
  902. FlxQuadTree.divisions = FlxG.worldDivisions;
  903. var quadTree:FlxQuadTree = new FlxQuadTree(FlxG.worldBounds.x,FlxG.worldBounds.y,FlxG.worldBounds.width,FlxG.worldBounds.height);
  904. quadTree.load(ObjectOrGroup1,ObjectOrGroup2,NotifyCallback,ProcessCallback);
  905. var result:Boolean = quadTree.execute();
  906. quadTree.destroy();
  907. return result;
  908. }
  909. /**
  910. * Call this function to see if one <code>FlxObject</code> collides with another.
  911. * Can be called with one object and one group, or two groups, or two objects,
  912. * whatever floats your boat! For maximum performance try bundling a lot of objects
  913. * together using a <code>FlxGroup</code> (or even bundling groups together!).
  914. *
  915. * <p>This function just calls FlxG.overlap and presets the ProcessCallback parameter to FlxObject.separate.
  916. * To create your own collision logic, write your own ProcessCallback and use FlxG.overlap to set it up.</p>
  917. *
  918. * <p>NOTE: does NOT take objects' scrollfactor into account, all overlaps are checked in world space.</p>
  919. *
  920. * @param ObjectOrGroup1 The first object or group you want to check.
  921. * @param ObjectOrGroup2 The second object or group you want to check. If it is the same as the first, flixel knows to just do a comparison within that group.
  922. * @param NotifyCallback A function with two <code>FlxObject</code> parameters - e.g. <code>myOverlapFunction(Object1:FlxObject,Object2:FlxObject)</code> - that is called if those two objects overlap.
  923. *
  924. * @return Whether any objects were successfully collided/separated.
  925. */
  926. static public function collide(ObjectOrGroup1:FlxBasic=null, ObjectOrGroup2:FlxBasic=null, NotifyCallback:Function=null):Boolean
  927. {
  928. return overlap(ObjectOrGroup1,ObjectOrGroup2,NotifyCallback,FlxObject.separate);
  929. }
  930. /**
  931. * Adds a new plugin to the global plugin array.
  932. *
  933. * @param Plugin Any object that extends FlxBasic. Useful for managers and other things. See org.flixel.plugin for some examples!
  934. *
  935. * @return The same <code>FlxBasic</code>-based plugin you passed in.
  936. */
  937. static public function addPlugin(Plugin:FlxBasic):FlxBasic
  938. {
  939. //Don't add repeats
  940. var pluginList:Array = FlxG.plugins;
  941. var i:uint = 0;
  942. var l:uint = pluginList.length;
  943. while(i < l)
  944. {
  945. if(pluginList[i++].toString() == Plugin.toString())
  946. return Plugin;
  947. }
  948. //no repeats! safe to add a new instance of this plugin
  949. pluginList.push(Plugin);
  950. return Plugin;
  951. }
  952. /**
  953. * Retrieves a plugin based on its class name from the global plugin array.
  954. *
  955. * @param ClassType The class name of the plugin you want to retrieve. See the <code>FlxPath</code> or <code>FlxTimer</code> constructors for example usage.
  956. *
  957. * @return The plugin object, or null if no matching plugin was found.
  958. */
  959. static public function getPlugin(ClassType:Class):FlxBasic
  960. {
  961. var pluginList:Array = FlxG.plugins;
  962. var i:uint = 0;
  963. var l:uint = pluginList.length;
  964. while(i < l)
  965. {
  966. if(pluginList[i] is ClassType)
  967. return plugins[i];
  968. i++;
  969. }
  970. return null;
  971. }
  972. /**
  973. * Removes an instance of a plugin from the global plugin array.
  974. *
  975. * @param Plugin The plugin instance you want to remove.
  976. *
  977. * @return The same <code>FlxBasic</code>-based plugin you passed in.
  978. */
  979. static public function removePlugin(Plugin:FlxBasic):FlxBasic
  980. {
  981. //Don't add repeats
  982. var pluginList:Array = FlxG.plugins;
  983. var i:int = pluginList.length-1;
  984. while(i >= 0)
  985. {
  986. if(pluginList[i] == Plugin)
  987. pluginList.splice(i,1);
  988. i--;
  989. }
  990. return Plugin;
  991. }
  992. /**
  993. * Removes an instance of a plugin from the global plugin array.
  994. *
  995. * @param ClassType The class name of the plugin type you want removed from the array.
  996. *
  997. * @return Whether or not at least one instance of this plugin type was removed.
  998. */
  999. static public function removePluginType(ClassType:Class):Boolean
  1000. {
  1001. //Don't add repeats
  1002. var results:Boolean = false;
  1003. var pluginList:Array = FlxG.plugins;
  1004. var i:int = pluginList.length-1;
  1005. while(i >= 0)
  1006. {
  1007. if(pluginList[i] is ClassType)
  1008. {
  1009. pluginList.splice(i,1);
  1010. results = true;
  1011. }
  1012. i--;
  1013. }
  1014. return results;
  1015. }
  1016. /**
  1017. * Called by <code>FlxGame</code> to set up <code>FlxG</code> during <code>FlxGame</code>'s constructor.
  1018. */
  1019. static internal function init(Game:FlxGame,Width:uint,Height:uint,Zoom:Number):void
  1020. {
  1021. FlxG._game = Game;
  1022. FlxG.width = Width;
  1023. FlxG.height = Height;
  1024. FlxG.mute = false;
  1025. FlxG._volume = 0.5;
  1026. FlxG.sounds = new FlxGroup();
  1027. FlxG.volumeHandler = null;
  1028. FlxG.clearBitmapCache();
  1029. if(flashGfxSprite == null)
  1030. {
  1031. flashGfxSprite = new Sprite();
  1032. flashGfx = flashGfxSprite.graphics;
  1033. }
  1034. FlxCamera.defaultZoom = Zoom;
  1035. FlxG._cameraRect = new Rectangle();
  1036. FlxG.cameras = new Array();
  1037. useBufferLocking = false;
  1038. plugins = new Array();
  1039. addPlugin(new DebugPathDisplay());
  1040. addPlugin(new TimerManager());
  1041. FlxG.mouse = new Mouse(FlxG._game._mouse);
  1042. FlxG.keys = new Keyboard();
  1043. FlxG.mobile = false;
  1044. FlxG.levels = new Array();
  1045. FlxG.scores = new Array();
  1046. FlxG.visualDebug = false;
  1047. }
  1048. /**
  1049. * Called whenever the game is reset, doesn't have to do quite as much work as the basic initialization stuff.
  1050. */
  1051. static internal function reset():void
  1052. {
  1053. FlxG.clearBitmapCache();
  1054. FlxG.resetInput();
  1055. FlxG.destroySounds(true);
  1056. FlxG.levels.length = 0;
  1057. FlxG.scores.length = 0;
  1058. FlxG.level = 0;
  1059. FlxG.score = 0;
  1060. FlxG.paused = false;
  1061. FlxG.timeScale = 1.0;
  1062. FlxG.elapsed = 0;
  1063. FlxG.globalSeed = Math.random();
  1064. FlxG.worldBounds = new FlxRect(-10,-10,FlxG.width+20,FlxG.height+20);
  1065. FlxG.worldDivisions = 6;
  1066. var debugPathDisplay:DebugPathDisplay = FlxG.getPlugin(DebugPathDisplay) as DebugPathDisplay;
  1067. if(debugPathDisplay != null)
  1068. debugPathDisplay.clear();
  1069. }
  1070. /**
  1071. * Called by the game object to update the keyboard and mouse input tracking objects.
  1072. */
  1073. static internal function updateInput():void
  1074. {
  1075. FlxG.keys.update();
  1076. if(!_game._debuggerUp || !_game._debugger.hasMouse)
  1077. FlxG.mouse.update(FlxG._game.mouseX,FlxG._game.mouseY);
  1078. }
  1079. /**
  1080. * Called by the game object to lock all the camera buffers and clear them for the next draw pass.
  1081. */
  1082. static internal function lockCameras():void
  1083. {
  1084. var cam:FlxCamera;
  1085. var cams:Array = FlxG.cameras;
  1086. var i:uint = 0;
  1087. var l:uint = cams.length;
  1088. while(i < l)
  1089. {
  1090. cam = cams[i++] as FlxCamera;
  1091. if((cam == null) || !cam.exists || !cam.visible)
  1092. continue;
  1093. if(useBufferLocking)
  1094. cam.buffer.lock();
  1095. cam.fill(cam.bgColor);
  1096. cam.screen.dirty = true;
  1097. }
  1098. }
  1099. /**
  1100. * Called by the game object to draw the special FX and unlock all the camera buffers.
  1101. */
  1102. static internal function unlockCameras():void
  1103. {
  1104. var cam:FlxCamera;
  1105. var cams:Array = FlxG.cameras;
  1106. var i:uint = 0;
  1107. var l:uint = cams.length;
  1108. while(i < l)
  1109. {
  1110. cam = cams[i++] as FlxCamera;
  1111. if((cam == null) || !cam.exists || !cam.visible)
  1112. continue;
  1113. cam.drawFX();
  1114. if(useBufferLocking)
  1115. cam.buffer.unlock();
  1116. }
  1117. }
  1118. /**
  1119. * Called by the game object to update the cameras and their tracking/special effects logic.
  1120. */
  1121. static internal function updateCameras():void
  1122. {
  1123. var cam:FlxCamera;
  1124. var cams:Array = FlxG.cameras;
  1125. var i:uint = 0;
  1126. var l:uint = cams.length;
  1127. while(i < l)
  1128. {
  1129. cam = cams[i++] as FlxCamera;
  1130. if((cam != null) && cam.exists)
  1131. {
  1132. if(cam.active)
  1133. cam.update();
  1134. cam._flashSprite.x = cam.x + cam._flashOffsetX;
  1135. cam._flashSprite.y = cam.y + cam._flashOffsetY;
  1136. cam._flashSprite.visible = cam.visible;
  1137. }
  1138. }
  1139. }
  1140. /**
  1141. * Used by the game object to call <code>update()</code> on all the plugins.
  1142. */
  1143. static internal function updatePlugins():void
  1144. {
  1145. var plugin:FlxBasic;
  1146. var pluginList:Array = FlxG.plugins;
  1147. var i:uint = 0;
  1148. var l:uint = pluginList.length;
  1149. while(i < l)
  1150. {
  1151. plugin = pluginList[i++] as FlxBasic;
  1152. if(plugin.exists && plugin.active)
  1153. plugin.update();
  1154. }
  1155. }
  1156. /**
  1157. * Used by the game object to call <code>draw()</code> on all the plugins.
  1158. */
  1159. static internal function drawPlugins():void
  1160. {
  1161. var plugin:FlxBasic;
  1162. var pluginList:Array = FlxG.plugins;
  1163. var i:uint = 0;
  1164. var l:uint = pluginList.length;
  1165. while(i < l)
  1166. {
  1167. plugin = pluginList[i++] as FlxBasic;
  1168. if(plugin.exists && plugin.visible)
  1169. plugin.draw();
  1170. }
  1171. }
  1172. }
  1173. }