PageRenderTime 62ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/org/flixel/FlxGame.as

http://github.com/AdamAtomic/flixel
ActionScript | 801 lines | 529 code | 56 blank | 216 comment | 125 complexity | 6e704ba2c4f7600af95539d26b48923c MD5 | raw file
  1. package org.flixel
  2. {
  3. import flash.display.Bitmap;
  4. import flash.display.BitmapData;
  5. import flash.display.Graphics;
  6. import flash.display.Sprite;
  7. import flash.display.StageAlign;
  8. import flash.display.StageScaleMode;
  9. import flash.events.*;
  10. import flash.geom.Point;
  11. import flash.text.AntiAliasType;
  12. import flash.text.GridFitType;
  13. import flash.text.TextField;
  14. import flash.text.TextFormat;
  15. import flash.ui.Mouse;
  16. import flash.utils.Timer;
  17. import flash.utils.getTimer;
  18. import org.flixel.plugin.TimerManager;
  19. import org.flixel.system.FlxDebugger;
  20. import org.flixel.system.FlxReplay;
  21. /**
  22. * FlxGame is the heart of all flixel games, and contains a bunch of basic game loops and things.
  23. * It is a long and sloppy file that you shouldn't have to worry about too much!
  24. * It is basically only used to create your game object in the first place,
  25. * after that FlxG and FlxState have all the useful stuff you actually need.
  26. *
  27. * @author Adam Atomic
  28. */
  29. public class FlxGame extends Sprite
  30. {
  31. [Embed(source="data/nokiafc22.ttf",fontFamily="system",embedAsCFF="false")] protected var junk:String;
  32. [Embed(source="data/beep.mp3")] protected var SndBeep:Class;
  33. [Embed(source="data/logo.png")] protected var ImgLogo:Class;
  34. /**
  35. * Sets 0, -, and + to control the global volume sound volume.
  36. * @default true
  37. */
  38. public var useSoundHotKeys:Boolean;
  39. /**
  40. * Tells flixel to use the default system mouse cursor instead of custom Flixel mouse cursors.
  41. * @default false
  42. */
  43. public var useSystemCursor:Boolean;
  44. /**
  45. * Initialize and allow the flixel debugger overlay even in release mode.
  46. * Also useful if you don't use FlxPreloader!
  47. * @default false
  48. */
  49. public var forceDebugger:Boolean;
  50. /**
  51. * Current game state.
  52. */
  53. internal var _state:FlxState;
  54. /**
  55. * Mouse cursor.
  56. */
  57. internal var _mouse:Sprite;
  58. /**
  59. * Class type of the initial/first game state for the game, usually MenuState or something like that.
  60. */
  61. protected var _iState:Class;
  62. /**
  63. * Whether the game object's basic initialization has finished yet.
  64. */
  65. protected var _created:Boolean;
  66. /**
  67. * Total number of milliseconds elapsed since game start.
  68. */
  69. protected var _total:uint;
  70. /**
  71. * Total number of milliseconds elapsed since last update loop.
  72. * Counts down as we step through the game loop.
  73. */
  74. protected var _accumulator:int;
  75. /**
  76. * Whether the Flash player lost focus.
  77. */
  78. protected var _lostFocus:Boolean;
  79. /**
  80. * Milliseconds of time per step of the game loop. FlashEvent.g. 60 fps = 16ms.
  81. */
  82. internal var _step:uint;
  83. /**
  84. * Framerate of the Flash player (NOT the game loop). Default = 30.
  85. */
  86. internal var _flashFramerate:uint;
  87. /**
  88. * Max allowable accumulation (see _accumulator).
  89. * Should always (and automatically) be set to roughly 2x the flash player framerate.
  90. */
  91. internal var _maxAccumulation:uint;
  92. /**
  93. * If a state change was requested, the new state object is stored here until we switch to it.
  94. */
  95. internal var _requestedState:FlxState;
  96. /**
  97. * A flag for keeping track of whether a game reset was requested or not.
  98. */
  99. internal var _requestedReset:Boolean;
  100. /**
  101. * The "focus lost" screen (see <code>createFocusScreen()</code>).
  102. */
  103. protected var _focus:Sprite;
  104. /**
  105. * The sound tray display container (see <code>createSoundTray()</code>).
  106. */
  107. protected var _soundTray:Sprite;
  108. /**
  109. * Helps us auto-hide the sound tray after a volume change.
  110. */
  111. protected var _soundTrayTimer:Number;
  112. /**
  113. * Helps display the volume bars on the sound tray.
  114. */
  115. protected var _soundTrayBars:Array;
  116. /**
  117. * The debugger overlay object.
  118. */
  119. internal var _debugger:FlxDebugger;
  120. /**
  121. * A handy boolean that keeps track of whether the debugger exists and is currently visible.
  122. */
  123. internal var _debuggerUp:Boolean;
  124. /**
  125. * Container for a game replay object.
  126. */
  127. internal var _replay:FlxReplay;
  128. /**
  129. * Flag for whether a playback of a recording was requested.
  130. */
  131. internal var _replayRequested:Boolean;
  132. /**
  133. * Flag for whether a new recording was requested.
  134. */
  135. internal var _recordingRequested:Boolean;
  136. /**
  137. * Flag for whether a replay is currently playing.
  138. */
  139. internal var _replaying:Boolean;
  140. /**
  141. * Flag for whether a new recording is being made.
  142. */
  143. internal var _recording:Boolean;
  144. /**
  145. * Array that keeps track of keypresses that can cancel a replay.
  146. * Handy for skipping cutscenes or getting out of attract modes!
  147. */
  148. internal var _replayCancelKeys:Array;
  149. /**
  150. * Helps time out a replay if necessary.
  151. */
  152. internal var _replayTimer:int;
  153. /**
  154. * This function, if set, is triggered when the callback stops playing.
  155. */
  156. internal var _replayCallback:Function;
  157. /**
  158. * Instantiate a new game object.
  159. *
  160. * @param GameSizeX The width of your game in game pixels, not necessarily final display pixels (see Zoom).
  161. * @param GameSizeY The height of your game in game pixels, not necessarily final display pixels (see Zoom).
  162. * @param InitialState The class name of the state you want to create and switch to first (e.g. MenuState).
  163. * @param Zoom The default level of zoom for the game's cameras (e.g. 2 = all pixels are now drawn at 2x). Default = 1.
  164. * @param GameFramerate How frequently the game should update (default is 60 times per second).
  165. * @param FlashFramerate Sets the actual display framerate for Flash player (default is 30 times per second).
  166. * @param UseSystemCursor Whether to use the default OS mouse pointer, or to use custom flixel ones.
  167. */
  168. public function FlxGame(GameSizeX:uint,GameSizeY:uint,InitialState:Class,Zoom:Number=1,GameFramerate:uint=60,FlashFramerate:uint=30,UseSystemCursor:Boolean=false)
  169. {
  170. //super high priority init stuff (focus, mouse, etc)
  171. _lostFocus = false;
  172. _focus = new Sprite();
  173. _focus.visible = false;
  174. _soundTray = new Sprite();
  175. _mouse = new Sprite()
  176. //basic display and update setup stuff
  177. FlxG.init(this,GameSizeX,GameSizeY,Zoom);
  178. FlxG.framerate = GameFramerate;
  179. FlxG.flashFramerate = FlashFramerate;
  180. _accumulator = _step;
  181. _total = 0;
  182. _state = null;
  183. useSoundHotKeys = true;
  184. useSystemCursor = UseSystemCursor;
  185. if(!useSystemCursor)
  186. flash.ui.Mouse.hide();
  187. forceDebugger = false;
  188. _debuggerUp = false;
  189. //replay data
  190. _replay = new FlxReplay();
  191. _replayRequested = false;
  192. _recordingRequested = false;
  193. _replaying = false;
  194. _recording = false;
  195. //then get ready to create the game object for real
  196. _iState = InitialState;
  197. _requestedState = null;
  198. _requestedReset = true;
  199. _created = false;
  200. addEventListener(Event.ENTER_FRAME, create);
  201. }
  202. /**
  203. * Makes the little volume tray slide out.
  204. *
  205. * @param Silent Whether or not it should beep.
  206. */
  207. internal function showSoundTray(Silent:Boolean=false):void
  208. {
  209. if(!Silent)
  210. FlxG.play(SndBeep);
  211. _soundTrayTimer = 1;
  212. _soundTray.y = 0;
  213. _soundTray.visible = true;
  214. var globalVolume:uint = Math.round(FlxG.volume*10);
  215. if(FlxG.mute)
  216. globalVolume = 0;
  217. for (var i:uint = 0; i < _soundTrayBars.length; i++)
  218. {
  219. if(i < globalVolume) _soundTrayBars[i].alpha = 1;
  220. else _soundTrayBars[i].alpha = 0.5;
  221. }
  222. }
  223. /**
  224. * Internal event handler for input and focus.
  225. *
  226. * @param FlashEvent Flash keyboard event.
  227. */
  228. protected function onKeyUp(FlashEvent:KeyboardEvent):void
  229. {
  230. if(_debuggerUp && _debugger.watch.editing)
  231. return;
  232. if(!FlxG.mobile)
  233. {
  234. if((_debugger != null) && ((FlashEvent.keyCode == 192) || (FlashEvent.keyCode == 220)))
  235. {
  236. _debugger.visible = !_debugger.visible;
  237. _debuggerUp = _debugger.visible;
  238. if(_debugger.visible)
  239. flash.ui.Mouse.show();
  240. else if(!useSystemCursor)
  241. flash.ui.Mouse.hide();
  242. //_console.toggle();
  243. return;
  244. }
  245. if(useSoundHotKeys)
  246. {
  247. var c:int = FlashEvent.keyCode;
  248. var code:String = String.fromCharCode(FlashEvent.charCode);
  249. switch(c)
  250. {
  251. case 48:
  252. case 96:
  253. FlxG.mute = !FlxG.mute;
  254. if(FlxG.volumeHandler != null)
  255. FlxG.volumeHandler(FlxG.mute?0:FlxG.volume);
  256. showSoundTray();
  257. return;
  258. case 109:
  259. case 189:
  260. FlxG.mute = false;
  261. FlxG.volume = FlxG.volume - 0.1;
  262. showSoundTray();
  263. return;
  264. case 107:
  265. case 187:
  266. FlxG.mute = false;
  267. FlxG.volume = FlxG.volume + 0.1;
  268. showSoundTray();
  269. return;
  270. default:
  271. break;
  272. }
  273. }
  274. }
  275. if(_replaying)
  276. return;
  277. FlxG.keys.handleKeyUp(FlashEvent);
  278. }
  279. /**
  280. * Internal event handler for input and focus.
  281. *
  282. * @param FlashEvent Flash keyboard event.
  283. */
  284. protected function onKeyDown(FlashEvent:KeyboardEvent):void
  285. {
  286. if(_debuggerUp && _debugger.watch.editing)
  287. return;
  288. if(_replaying && (_replayCancelKeys != null) && (_debugger == null) && (FlashEvent.keyCode != 192) && (FlashEvent.keyCode != 220))
  289. {
  290. var cancel:Boolean = false;
  291. var replayCancelKey:String;
  292. var i:uint = 0;
  293. var l:uint = _replayCancelKeys.length;
  294. while(i < l)
  295. {
  296. replayCancelKey = _replayCancelKeys[i++];
  297. if((replayCancelKey == "ANY") || (FlxG.keys.getKeyCode(replayCancelKey) == FlashEvent.keyCode))
  298. {
  299. if(_replayCallback != null)
  300. {
  301. _replayCallback();
  302. _replayCallback = null;
  303. }
  304. else
  305. FlxG.stopReplay();
  306. break;
  307. }
  308. }
  309. return;
  310. }
  311. FlxG.keys.handleKeyDown(FlashEvent);
  312. }
  313. /**
  314. * Internal event handler for input and focus.
  315. *
  316. * @param FlashEvent Flash mouse event.
  317. */
  318. protected function onMouseDown(FlashEvent:MouseEvent):void
  319. {
  320. if(_debuggerUp)
  321. {
  322. if(_debugger.hasMouse)
  323. return;
  324. if(_debugger.watch.editing)
  325. _debugger.watch.submit();
  326. }
  327. if(_replaying && (_replayCancelKeys != null))
  328. {
  329. var replayCancelKey:String;
  330. var i:uint = 0;
  331. var l:uint = _replayCancelKeys.length;
  332. while(i < l)
  333. {
  334. replayCancelKey = _replayCancelKeys[i++] as String;
  335. if((replayCancelKey == "MOUSE") || (replayCancelKey == "ANY"))
  336. {
  337. if(_replayCallback != null)
  338. {
  339. _replayCallback();
  340. _replayCallback = null;
  341. }
  342. else
  343. FlxG.stopReplay();
  344. break;
  345. }
  346. }
  347. return;
  348. }
  349. FlxG.mouse.handleMouseDown(FlashEvent);
  350. }
  351. /**
  352. * Internal event handler for input and focus.
  353. *
  354. * @param FlashEvent Flash mouse event.
  355. */
  356. protected function onMouseUp(FlashEvent:MouseEvent):void
  357. {
  358. if((_debuggerUp && _debugger.hasMouse) || _replaying)
  359. return;
  360. FlxG.mouse.handleMouseUp(FlashEvent);
  361. }
  362. /**
  363. * Internal event handler for input and focus.
  364. *
  365. * @param FlashEvent Flash mouse event.
  366. */
  367. protected function onMouseWheel(FlashEvent:MouseEvent):void
  368. {
  369. if((_debuggerUp && _debugger.hasMouse) || _replaying)
  370. return;
  371. FlxG.mouse.handleMouseWheel(FlashEvent);
  372. }
  373. /**
  374. * Internal event handler for input and focus.
  375. *
  376. * @param FlashEvent Flash event.
  377. */
  378. protected function onFocus(FlashEvent:Event=null):void
  379. {
  380. if(!_debuggerUp && !useSystemCursor)
  381. flash.ui.Mouse.hide();
  382. FlxG.resetInput();
  383. _lostFocus = _focus.visible = false;
  384. stage.frameRate = _flashFramerate;
  385. FlxG.resumeSounds();
  386. }
  387. /**
  388. * Internal event handler for input and focus.
  389. *
  390. * @param FlashEvent Flash event.
  391. */
  392. protected function onFocusLost(FlashEvent:Event=null):void
  393. {
  394. if((x != 0) || (y != 0))
  395. {
  396. x = 0;
  397. y = 0;
  398. }
  399. flash.ui.Mouse.show();
  400. _lostFocus = _focus.visible = true;
  401. stage.frameRate = 10;
  402. FlxG.pauseSounds();
  403. }
  404. /**
  405. * Handles the onEnterFrame call and figures out how many updates and draw calls to do.
  406. *
  407. * @param FlashEvent Flash event.
  408. */
  409. protected function onEnterFrame(FlashEvent:Event=null):void
  410. {
  411. var mark:uint = getTimer();
  412. var elapsedMS:uint = mark-_total;
  413. _total = mark;
  414. updateSoundTray(elapsedMS);
  415. if(!_lostFocus)
  416. {
  417. if((_debugger != null) && _debugger.vcr.paused)
  418. {
  419. if(_debugger.vcr.stepRequested)
  420. {
  421. _debugger.vcr.stepRequested = false;
  422. step();
  423. }
  424. }
  425. else
  426. {
  427. _accumulator += elapsedMS;
  428. if(_accumulator > _maxAccumulation)
  429. _accumulator = _maxAccumulation;
  430. while(_accumulator >= _step)
  431. {
  432. step();
  433. _accumulator = _accumulator - _step;
  434. }
  435. }
  436. FlxBasic._VISIBLECOUNT = 0;
  437. draw();
  438. if(_debuggerUp)
  439. {
  440. _debugger.perf.flash(elapsedMS);
  441. _debugger.perf.visibleObjects(FlxBasic._VISIBLECOUNT);
  442. _debugger.perf.update();
  443. _debugger.watch.update();
  444. }
  445. }
  446. }
  447. /**
  448. * If there is a state change requested during the update loop,
  449. * this function handles actual destroying the old state and related processes,
  450. * and calls creates on the new state and plugs it into the game object.
  451. */
  452. protected function switchState():void
  453. {
  454. //Basic reset stuff
  455. FlxG.resetCameras();
  456. FlxG.resetInput();
  457. FlxG.destroySounds();
  458. FlxG.clearBitmapCache();
  459. //Clear the debugger overlay's Watch window
  460. if(_debugger != null)
  461. _debugger.watch.removeAll();
  462. //Clear any timers left in the timer manager
  463. var timerManager:TimerManager = FlxTimer.manager;
  464. if(timerManager != null)
  465. timerManager.clear();
  466. //Destroy the old state (if there is an old state)
  467. if(_state != null)
  468. _state.destroy();
  469. //Finally assign and create the new state
  470. _state = _requestedState;
  471. _state.create();
  472. }
  473. /**
  474. * This is the main game update logic section.
  475. * The onEnterFrame() handler is in charge of calling this
  476. * the appropriate number of times each frame.
  477. * This block handles state changes, replays, all that good stuff.
  478. */
  479. protected function step():void
  480. {
  481. //handle game reset request
  482. if(_requestedReset)
  483. {
  484. _requestedReset = false;
  485. _requestedState = new _iState();
  486. _replayTimer = 0;
  487. _replayCancelKeys = null;
  488. FlxG.reset();
  489. }
  490. //handle replay-related requests
  491. if(_recordingRequested)
  492. {
  493. _recordingRequested = false;
  494. _replay.create(FlxG.globalSeed);
  495. _recording = true;
  496. if(_debugger != null)
  497. {
  498. _debugger.vcr.recording();
  499. FlxG.log("FLIXEL: starting new flixel gameplay record.");
  500. }
  501. }
  502. else if(_replayRequested)
  503. {
  504. _replayRequested = false;
  505. _replay.rewind();
  506. FlxG.globalSeed = _replay.seed;
  507. if(_debugger != null)
  508. _debugger.vcr.playing();
  509. _replaying = true;
  510. }
  511. //handle state switching requests
  512. if(_state != _requestedState)
  513. switchState();
  514. //finally actually step through the game physics
  515. FlxBasic._ACTIVECOUNT = 0;
  516. if(_replaying)
  517. {
  518. _replay.playNextFrame();
  519. if(_replayTimer > 0)
  520. {
  521. _replayTimer -= _step;
  522. if(_replayTimer <= 0)
  523. {
  524. if(_replayCallback != null)
  525. {
  526. _replayCallback();
  527. _replayCallback = null;
  528. }
  529. else
  530. FlxG.stopReplay();
  531. }
  532. }
  533. if(_replaying && _replay.finished)
  534. {
  535. FlxG.stopReplay();
  536. if(_replayCallback != null)
  537. {
  538. _replayCallback();
  539. _replayCallback = null;
  540. }
  541. }
  542. if(_debugger != null)
  543. _debugger.vcr.updateRuntime(_step);
  544. }
  545. else
  546. FlxG.updateInput();
  547. if(_recording)
  548. {
  549. _replay.recordFrame();
  550. if(_debugger != null)
  551. _debugger.vcr.updateRuntime(_step);
  552. }
  553. update();
  554. FlxG.mouse.wheel = 0;
  555. if(_debuggerUp)
  556. _debugger.perf.activeObjects(FlxBasic._ACTIVECOUNT);
  557. }
  558. /**
  559. * This function just updates the soundtray object.
  560. */
  561. protected function updateSoundTray(MS:Number):void
  562. {
  563. //animate stupid sound tray thing
  564. if(_soundTray != null)
  565. {
  566. if(_soundTrayTimer > 0)
  567. _soundTrayTimer -= MS/1000;
  568. else if(_soundTray.y > -_soundTray.height)
  569. {
  570. _soundTray.y -= (MS/1000)*FlxG.height*2;
  571. if(_soundTray.y <= -_soundTray.height)
  572. {
  573. _soundTray.visible = false;
  574. //Save sound preferences
  575. var soundPrefs:FlxSave = new FlxSave();
  576. if(soundPrefs.bind("flixel"))
  577. {
  578. if(soundPrefs.data.sound == null)
  579. soundPrefs.data.sound = new Object;
  580. soundPrefs.data.sound.mute = FlxG.mute;
  581. soundPrefs.data.sound.volume = FlxG.volume;
  582. soundPrefs.close();
  583. }
  584. }
  585. }
  586. }
  587. }
  588. /**
  589. * This function is called by step() and updates the actual game state.
  590. * May be called multiple times per "frame" or draw call.
  591. */
  592. protected function update():void
  593. {
  594. var mark:uint = getTimer();
  595. FlxG.elapsed = FlxG.timeScale*(_step/1000);
  596. FlxG.updateSounds();
  597. FlxG.updatePlugins();
  598. _state.update();
  599. FlxG.updateCameras();
  600. if(_debuggerUp)
  601. _debugger.perf.flixelUpdate(getTimer()-mark);
  602. }
  603. /**
  604. * Goes through the game state and draws all the game objects and special effects.
  605. */
  606. protected function draw():void
  607. {
  608. var mark:uint = getTimer();
  609. FlxG.lockCameras();
  610. _state.draw();
  611. FlxG.drawPlugins();
  612. FlxG.unlockCameras();
  613. if(_debuggerUp)
  614. _debugger.perf.flixelDraw(getTimer()-mark);
  615. }
  616. /**
  617. * Used to instantiate the guts of the flixel game object once we have a valid reference to the root.
  618. *
  619. * @param FlashEvent Just a Flash system event, not too important for our purposes.
  620. */
  621. protected function create(FlashEvent:Event):void
  622. {
  623. if(root == null)
  624. return;
  625. removeEventListener(Event.ENTER_FRAME, create);
  626. _total = getTimer();
  627. //Set up the view window and double buffering
  628. stage.scaleMode = StageScaleMode.NO_SCALE;
  629. stage.align = StageAlign.TOP_LEFT;
  630. stage.frameRate = _flashFramerate;
  631. //Add basic input event listeners and mouse container
  632. stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
  633. stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
  634. stage.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);
  635. stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
  636. stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
  637. addChild(_mouse);
  638. //Let mobile devs opt out of unnecessary overlays.
  639. if(!FlxG.mobile)
  640. {
  641. //Debugger overlay
  642. if(FlxG.debug || forceDebugger)
  643. {
  644. _debugger = new FlxDebugger(FlxG.width*FlxCamera.defaultZoom,FlxG.height*FlxCamera.defaultZoom);
  645. addChild(_debugger);
  646. }
  647. //Volume display tab
  648. createSoundTray();
  649. //Focus gained/lost monitoring
  650. stage.addEventListener(Event.DEACTIVATE, onFocusLost);
  651. stage.addEventListener(Event.ACTIVATE, onFocus);
  652. createFocusScreen();
  653. }
  654. //Finally, set up an event for the actual game loop stuff.
  655. addEventListener(Event.ENTER_FRAME, onEnterFrame);
  656. }
  657. /**
  658. * Sets up the "sound tray", the little volume meter that pops down sometimes.
  659. */
  660. protected function createSoundTray():void
  661. {
  662. _soundTray.visible = false;
  663. _soundTray.scaleX = 2;
  664. _soundTray.scaleY = 2;
  665. var tmp:Bitmap = new Bitmap(new BitmapData(80,30,true,0x7F000000));
  666. _soundTray.x = (FlxG.width/2)*FlxCamera.defaultZoom-(tmp.width/2)*_soundTray.scaleX;
  667. _soundTray.addChild(tmp);
  668. var text:TextField = new TextField();
  669. text.width = tmp.width;
  670. text.height = tmp.height;
  671. text.multiline = true;
  672. text.wordWrap = true;
  673. text.selectable = false;
  674. text.embedFonts = true;
  675. text.antiAliasType = AntiAliasType.NORMAL;
  676. text.gridFitType = GridFitType.PIXEL;
  677. text.defaultTextFormat = new TextFormat("system",8,0xffffff,null,null,null,null,null,"center");;
  678. _soundTray.addChild(text);
  679. text.text = "VOLUME";
  680. text.y = 16;
  681. var bx:uint = 10;
  682. var by:uint = 14;
  683. _soundTrayBars = new Array();
  684. var i:uint = 0;
  685. while(i < 10)
  686. {
  687. tmp = new Bitmap(new BitmapData(4,++i,false,0xffffff));
  688. tmp.x = bx;
  689. tmp.y = by;
  690. _soundTrayBars.push(_soundTray.addChild(tmp));
  691. bx += 6;
  692. by--;
  693. }
  694. _soundTray.y = -_soundTray.height;
  695. _soundTray.visible = false;
  696. addChild(_soundTray);
  697. //load saved sound preferences for this game if they exist
  698. var soundPrefs:FlxSave = new FlxSave();
  699. if(soundPrefs.bind("flixel") && (soundPrefs.data.sound != null))
  700. {
  701. if(soundPrefs.data.sound.volume != null)
  702. FlxG.volume = soundPrefs.data.sound.volume;
  703. if(soundPrefs.data.sound.mute != null)
  704. FlxG.mute = soundPrefs.data.sound.mute;
  705. soundPrefs.destroy();
  706. }
  707. }
  708. /**
  709. * Sets up the darkened overlay with the big white "play" button that appears when a flixel game loses focus.
  710. */
  711. protected function createFocusScreen():void
  712. {
  713. var gfx:Graphics = _focus.graphics;
  714. var screenWidth:uint = FlxG.width*FlxCamera.defaultZoom;
  715. var screenHeight:uint = FlxG.height*FlxCamera.defaultZoom;
  716. //draw transparent black backdrop
  717. gfx.moveTo(0,0);
  718. gfx.beginFill(0,0.5);
  719. gfx.lineTo(screenWidth,0);
  720. gfx.lineTo(screenWidth,screenHeight);
  721. gfx.lineTo(0,screenHeight);
  722. gfx.lineTo(0,0);
  723. gfx.endFill();
  724. //draw white arrow
  725. var halfWidth:uint = screenWidth/2;
  726. var halfHeight:uint = screenHeight/2;
  727. var helper:uint = FlxU.min(halfWidth,halfHeight)/3;
  728. gfx.moveTo(halfWidth-helper,halfHeight-helper);
  729. gfx.beginFill(0xffffff,0.65);
  730. gfx.lineTo(halfWidth+helper,halfHeight);
  731. gfx.lineTo(halfWidth-helper,halfHeight+helper);
  732. gfx.lineTo(halfWidth-helper,halfHeight-helper);
  733. gfx.endFill();
  734. var logo:Bitmap = new ImgLogo();
  735. logo.scaleX = int(helper/10);
  736. if(logo.scaleX < 1)
  737. logo.scaleX = 1;
  738. logo.scaleY = logo.scaleX;
  739. logo.x -= logo.scaleX;
  740. logo.alpha = 0.35;
  741. _focus.addChild(logo);
  742. addChild(_focus);
  743. }
  744. }
  745. }