PageRenderTime 210ms CodeModel.GetById 136ms RepoModel.GetById 0ms app.codeStats 0ms

/org/haxel/HxlGame.hx

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