PageRenderTime 74ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 1ms

/org/flixel/FlxG.hx

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