PageRenderTime 47ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/org/flixel/FlxGame.hx

http://flixel-haxelib.googlecode.com/
Haxe | 803 lines | 524 code | 59 blank | 220 comment | 124 complexity | ab2a9a71b26a3c1852a0c5667e006e7e MD5 | raw file
  1. package org.flixel;
  2. import flash.display.Bitmap;
  3. import flash.display.BitmapData;
  4. import flash.display.Graphics;
  5. import flash.display.Sprite;
  6. import flash.display.StageAlign;
  7. import flash.display.StageScaleMode;
  8. import flash.events.Event;
  9. import flash.events.KeyboardEvent;
  10. import flash.events.MouseEvent;
  11. import flash.geom.Point;
  12. import flash.text.AntiAliasType;
  13. import flash.text.GridFitType;
  14. import flash.text.TextField;
  15. import flash.text.TextFormat;
  16. import flash.ui.Mouse;
  17. import flash.utils.Timer;
  18. import flash.Lib;
  19. import org.flixel.plugin.TimerManager;
  20. import org.flixel.system.FlxDebugger;
  21. import org.flixel.system.FlxReplay;
  22. //[Embed(source="data/nokiafc22.ttf",fontFamily="system",embedAsCFF="false")] private var junk:String;
  23. //[Embed(source="data/beep.mp3")] private var SndBeep:Class;
  24. @:bitmap ("data/logo.png") class ImgLogo extends BitmapData {}
  25. /**
  26. * FlxGame is the heart of all flixel games, and contains a bunch of basic game loops and things.
  27. * It is a long and sloppy file that you shouldn't have to worry about too much!
  28. * It is basically only used to create your game object in the first place,
  29. * after that FlxG and FlxState have all the useful stuff you actually need.
  30. *
  31. * @author Adam Atomic
  32. */
  33. class FlxGame extends Sprite
  34. {
  35. /**
  36. * Sets 0, -, and + to control the global volume sound volume.
  37. * @default true
  38. */
  39. public var useSoundHotKeys:Bool;
  40. /**
  41. * Tells flixel to use the default system mouse cursor instead of custom Flixel mouse cursors.
  42. * @default false
  43. */
  44. public var useSystemCursor:Bool;
  45. /**
  46. * Initialize and allow the flixel debugger overlay even in release mode.
  47. * Also useful if you don't use FlxPreloader!
  48. * @default false
  49. */
  50. public var forceDebugger:Bool;
  51. /**
  52. * Current game state.
  53. */
  54. public var _state:FlxState;
  55. /**
  56. * Mouse cursor.
  57. */
  58. public var _mouse:Sprite;
  59. /**
  60. * Class type of the initial/first game state for the game, usually MenuState or something like that.
  61. */
  62. private var _iState:Class <Dynamic>;
  63. /**
  64. * Whether the game object's basic initialization has finished yet.
  65. */
  66. private var _created:Bool;
  67. /**
  68. * Total number of milliseconds elapsed since game start.
  69. */
  70. private var _total:Int;
  71. /**
  72. * Total number of milliseconds elapsed since last update loop.
  73. * Counts down as we step through the game loop.
  74. */
  75. private var _accumulator:Int;
  76. /**
  77. * Whether the Flash player lost focus.
  78. */
  79. private var _lostFocus:Bool;
  80. /**
  81. * Milliseconds of time per step of the game loop. FlashEvent.g. 60 fps = 16ms.
  82. */
  83. public var _step:Int;
  84. /**
  85. * Framerate of the Flash player (NOT the game loop). Default = 30.
  86. */
  87. public var _flashFramerate:Int;
  88. /**
  89. * Max allowable accumulation (see _accumulator).
  90. * Should always (and automatically) be set to roughly 2x the flash player framerate.
  91. */
  92. public var _maxAccumulation:Int;
  93. /**
  94. * If a state change was requested, the new state object is stored here until we switch to it.
  95. */
  96. public var _requestedState:FlxState;
  97. /**
  98. * A flag for keeping track of whether a game reset was requested or not.
  99. */
  100. public var _requestedReset:Bool;
  101. /**
  102. * The "focus lost" screen (see <code>createFocusScreen()</code>).
  103. */
  104. private var _focus:Sprite;
  105. /**
  106. * The sound tray display container (see <code>createSoundTray()</code>).
  107. */
  108. private var _soundTray:Sprite;
  109. /**
  110. * Helps us auto-hide the sound tray after a volume change.
  111. */
  112. private var _soundTrayTimer:Float;
  113. /**
  114. * Helps display the volume bars on the sound tray.
  115. */
  116. private var _soundTrayBars:Array <Int>;
  117. /**
  118. * The debugger overlay object.
  119. */
  120. public var _debugger:FlxDebugger;
  121. /**
  122. * A handy boolean that keeps track of whether the debugger exists and is currently visible.
  123. */
  124. public var _debuggerUp:Bool;
  125. /**
  126. * Container for a game replay object.
  127. */
  128. public var _replay:FlxReplay;
  129. /**
  130. * Flag for whether a playback of a recording was requested.
  131. */
  132. public var _replayRequested:Bool;
  133. /**
  134. * Flag for whether a new recording was requested.
  135. */
  136. public var _recordingRequested:Bool;
  137. /**
  138. * Flag for whether a replay is currently playing.
  139. */
  140. public var _replaying:Bool;
  141. /**
  142. * Flag for whether a new recording is being made.
  143. */
  144. public var _recording:Bool;
  145. /**
  146. * Array that keeps track of keypresses that can cancel a replay.
  147. * Handy for skipping cutscenes or getting out of attract modes!
  148. */
  149. public var _replayCancelKeys:Array <String>;
  150. /**
  151. * Helps time out a replay if necessary.
  152. */
  153. public var _replayTimer:Int;
  154. /**
  155. * This function, if set, is triggered when the callback stops playing.
  156. */
  157. public var _replayCallback:Dynamic;
  158. /**
  159. * Instantiate a new game object.
  160. *
  161. * @param GameSizeX The width of your game in game pixels, not necessarily final display pixels (see Zoom).
  162. * @param GameSizeY The height of your game in game pixels, not necessarily final display pixels (see Zoom).
  163. * @param InitialState The class name of the state you want to create and switch to first (e.g. MenuState).
  164. * @param Zoom The default level of zoom for the game's cameras (e.g. 2 = all pixels are now drawn at 2x). Default = 1.
  165. * @param GameFramerate How frequently the game should update (default is 60 times per second).
  166. * @param FlashFramerate Sets the actual display framerate for Flash player (default is 30 times per second).
  167. * @param UseSystemCursor Whether to use the default OS mouse pointer, or to use custom flixel ones.
  168. */
  169. public function new (GameSizeX:Int,GameSizeY:Int,InitialState:Class <Dynamic>,Zoom:Float=1,GameFramerate:Int=60,FlashFramerate:Int=30,UseSystemCursor:Bool=false)
  170. {
  171. //super high priority init stuff (focus, mouse, etc)
  172. _lostFocus = false;
  173. _focus = new Sprite();
  174. _focus.visible = false;
  175. _soundTray = new Sprite();
  176. _mouse = new Sprite();
  177. //basic display and update setup stuff
  178. FlxG.init(this,GameSizeX,GameSizeY,Zoom);
  179. FlxG.framerate = GameFramerate;
  180. FlxG.flashFramerate = FlashFramerate;
  181. _accumulator = _step;
  182. _total = 0;
  183. _state = null;
  184. useSoundHotKeys = true;
  185. useSystemCursor = UseSystemCursor;
  186. if(!useSystemCursor)
  187. flash.ui.Mouse.hide();
  188. forceDebugger = false;
  189. _debuggerUp = false;
  190. //replay data
  191. _replay = new FlxReplay();
  192. _replayRequested = false;
  193. _recordingRequested = false;
  194. _replaying = false;
  195. _recording = false;
  196. //then get ready to create the game object for real
  197. _iState = InitialState;
  198. _requestedState = null;
  199. _requestedReset = true;
  200. _created = false;
  201. addEventListener(Event.ENTER_FRAME, create);
  202. }
  203. /**
  204. * Makes the little volume tray slide out.
  205. *
  206. * @param Silent Whether or not it should beep.
  207. */
  208. public function showSoundTray(Silent:Bool=false):Void
  209. {
  210. //if(!Silent)
  211. //FlxG.play(SndBeep);
  212. _soundTrayTimer = 1;
  213. _soundTray.y = 0;
  214. _soundTray.visible = true;
  215. var globalVolume:Int = Math.round(FlxG.volume*10);
  216. if(FlxG.mute)
  217. globalVolume = 0;
  218. for (i in 0..._soundTrayBars.length)
  219. {
  220. if(i < globalVolume) _soundTrayBars[i].alpha = 1;
  221. else _soundTrayBars[i].alpha = 0.5;
  222. }
  223. }
  224. /**
  225. * Internal event handler for input and focus.
  226. *
  227. * @param FlashEvent Flash keyboard event.
  228. */
  229. private function onKeyUp(FlashEvent:KeyboardEvent):Void
  230. {
  231. if(_debuggerUp && _debugger.watch.editing)
  232. return;
  233. if(!FlxG.mobile)
  234. {
  235. if((_debugger != null) && ((FlashEvent.keyCode == 192) || (FlashEvent.keyCode == 220)))
  236. {
  237. _debugger.visible = !_debugger.visible;
  238. _debuggerUp = _debugger.visible;
  239. if(_debugger.visible)
  240. flash.ui.Mouse.show();
  241. else if(!useSystemCursor)
  242. flash.ui.Mouse.hide();
  243. //_console.toggle();
  244. return;
  245. }
  246. if(useSoundHotKeys)
  247. {
  248. var c:Int = FlashEvent.keyCode;
  249. var code:String = String.fromCharCode(FlashEvent.charCode);
  250. switch(c)
  251. {
  252. case 48:
  253. case 96:
  254. FlxG.mute = !FlxG.mute;
  255. if(FlxG.volumeHandler != null)
  256. FlxG.volumeHandler(FlxG.mute?0:FlxG.volume);
  257. showSoundTray();
  258. return;
  259. case 109:
  260. case 189:
  261. FlxG.mute = false;
  262. FlxG.volume = FlxG.volume - 0.1;
  263. showSoundTray();
  264. return;
  265. case 107:
  266. case 187:
  267. FlxG.mute = false;
  268. FlxG.volume = FlxG.volume + 0.1;
  269. showSoundTray();
  270. return;
  271. default:
  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. private 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:Bool = false;
  291. var replayCancelKey:String;
  292. var i:Int = 0;
  293. var l:Int = _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. private 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:Int = 0;
  331. var l:Int = _replayCancelKeys.length;
  332. while(i < l)
  333. {
  334. replayCancelKey = _replayCancelKeys[i++];
  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. private 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. private 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. private 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. private 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. private function onEnterFrame(FlashEvent:Event=null):Void
  410. {
  411. var mark:Int = Lib.getTimer();
  412. var elapsedMS:Int = 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. private 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. private function step():Void
  480. {
  481. //handle game reset request
  482. if(_requestedReset)
  483. {
  484. _requestedReset = false;
  485. _requestedState = Type.createEmptyInstance (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. private function updateSoundTray(MS:Float):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 = {};
  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. private function update():Void
  593. {
  594. var mark:Int = Lib.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(Lib.getTimer()-mark);
  602. }
  603. /**
  604. * Goes through the game state and draws all the game objects and special effects.
  605. */
  606. private function draw():Void
  607. {
  608. var mark:Int = Lib.getTimer();
  609. FlxG.lockCameras();
  610. _state.draw();
  611. FlxG.drawPlugins();
  612. FlxG.unlockCameras();
  613. if(_debuggerUp)
  614. _debugger.perf.flixelDraw(Lib.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. private function create(FlashEvent:Event):Void
  622. {
  623. if(root == null)
  624. return;
  625. removeEventListener(Event.ENTER_FRAME, create);
  626. _total = Lib.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. private 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:Int = 10;
  682. var by:Int = 14;
  683. _soundTrayBars = new Array();
  684. var i:Int = 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. private function createFocusScreen():Void
  712. {
  713. var gfx:Graphics = _focus.graphics;
  714. var screenWidth:Int = FlxG.width*FlxCamera.defaultZoom;
  715. var screenHeight:Int = 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:Int = screenWidth/2;
  726. var halfHeight:Int = screenHeight/2;
  727. var helper:Int = 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 = Std.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. }