PageRenderTime 63ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/src/com/mikechambers/pewpew/engine/GameArea.as

https://github.com/mikechambers/pewpew
ActionScript | 943 lines | 424 code | 204 blank | 315 comment | 34 complexity | 3126e205b02ecfd4b4c9cbc9456e4dac MD5 | raw file
  1. /*
  2. The MIT License
  3. Copyright (c) 2010 Mike Chambers
  4. Permission is hereby granted, free of charge, to any person obtaining a copy
  5. of this software and associated documentation files (the "Software"), to deal
  6. in the Software without restriction, including without limitation the rights
  7. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. copies of the Software, and to permit persons to whom the Software is
  9. furnished to do so, subject to the following conditions:
  10. The above copyright notice and this permission notice shall be included in
  11. all copies or substantial portions of the Software.
  12. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  14. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  15. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  16. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  17. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  18. THE SOFTWARE.
  19. */
  20. package com.mikechambers.pewpew.engine
  21. {
  22. import com.mikechambers.pewpew.engine.events.FireEvent;
  23. import com.mikechambers.pewpew.engine.events.GameEvent;
  24. import com.mikechambers.pewpew.engine.events.GameObjectEvent;
  25. import com.mikechambers.pewpew.engine.gameobjects.BasicEnemy;
  26. import com.mikechambers.pewpew.engine.gameobjects.ChaserEnemy;
  27. import com.mikechambers.pewpew.engine.gameobjects.Enemy;
  28. import com.mikechambers.pewpew.engine.gameobjects.Explosion;
  29. import com.mikechambers.pewpew.engine.gameobjects.Missile;
  30. import com.mikechambers.pewpew.engine.gameobjects.Ship;
  31. import com.mikechambers.pewpew.engine.gameobjects.UFOEnemy;
  32. import com.mikechambers.pewpew.ui.GameController;
  33. import com.mikechambers.pewpew.ui.ScoreBar;
  34. import com.mikechambers.pewpew.ui.WaveCompletedView;
  35. import com.mikechambers.pewpew.ui.events.ScreenControlEvent;
  36. import com.mikechambers.sgf.events.TickEvent;
  37. import com.mikechambers.sgf.time.TickManager;
  38. import com.mikechambers.sgf.utils.DisplayObjectUtil;
  39. import com.mikechambers.sgf.pools.GameObjectPool;
  40. import com.mikechambers.sgf.gameobjects.GameObject;
  41. import flash.display.BitmapData;
  42. import flash.display.Sprite;
  43. import flash.events.Event;
  44. import flash.events.TimerEvent;
  45. import flash.geom.Point;
  46. import flash.geom.Rectangle;
  47. import flash.system.System;
  48. import flash.utils.Dictionary;
  49. import flash.utils.Timer;
  50. //class that handles game play logic, and manages all
  51. //game play items
  52. public class GameArea extends Sprite
  53. {
  54. //default starting number of lives
  55. private static const DEFAULT_LIVES:uint = 2;
  56. //default number of starting enemies per level
  57. private static const DEFAULT_NUMBER_ENEMIES:uint = 10;
  58. //interval in seconds to do special game checks
  59. private static const GAME_CHECK_INTERVAL:Number = 7;
  60. //instantiated within FLA
  61. public var scoreBar:ScoreBar;
  62. //player controlled ship
  63. private var ship:Ship;
  64. //game play bounds
  65. private var bounds:Rectangle;
  66. //current score
  67. private var score:uint;
  68. //current number of lives
  69. private var lives:int;
  70. //current level / wave
  71. private var wave:uint = 1;
  72. //vector of all active enemies
  73. private var enemies:Vector.<Enemy>;
  74. //vector of all active ship missiles
  75. private var missiles:Vector.<Missile>;
  76. //view displayed when a wave / level is completed
  77. private var waveCompletedView:WaveCompletedView;
  78. //tickManager instance to manage game play time
  79. private var tickManager:TickManager;
  80. //current tick count
  81. private var tickCount:uint = 0;
  82. //game controller / thumb paddle
  83. public var gameController:GameController;
  84. //object pool for game
  85. //todo: change this to use pool from SGF
  86. private var gameObjectPool:GameObjectPool;
  87. //Whether there is already a UFOEnemy in the game area
  88. private var ufoOnStage:Boolean = false;
  89. /*************** initialization *************/
  90. //constructor for instance
  91. public function GameArea()
  92. {
  93. //initialize the enemies vector
  94. enemies = new Vector.<Enemy>();
  95. //initialize the missiles vector
  96. missiles = new Vector.<Missile>();
  97. //listen for when the instance is added to the stage
  98. addEventListener(Event.ADDED_TO_STAGE, onStageAdded, false, 0,
  99. true);
  100. //disable all mouse events since we dont need them here
  101. //this is done for performance reasons
  102. mouseEnabled = false;
  103. mouseChildren = false;
  104. }
  105. /************** Flash engine Events **************/
  106. //called when instance is added to stage
  107. private function onStageAdded(e:Event):void
  108. {
  109. //dont need to listen for this anymore
  110. removeEventListener(Event.ADDED_TO_STAGE, onStageAdded);
  111. //get an instance of the game object pool
  112. gameObjectPool = GameObjectPool.getInstance();
  113. //set the game area bounds
  114. bounds = new Rectangle(0,scoreBar.height, stage.stageWidth,
  115. stage.stageHeight - scoreBar.height);
  116. //position the game controller / thumb paddle
  117. gameController.x = bounds.width - (gameController.width / 2);
  118. gameController.y = bounds.height - (gameController.height / 2);
  119. //listen for when the instance is removed from the stage
  120. addEventListener(Event.REMOVED_FROM_STAGE, onStageRemoved, false,
  121. 0, true);
  122. }
  123. //called when the instance is removed from the stage
  124. private function onStageRemoved(e:Event):void
  125. {
  126. //remove listener, since we are already removed
  127. removeEventListener(Event.REMOVED_FROM_STAGE, onStageRemoved);
  128. //stop listening to the tickManager events
  129. tickManager.removeEventListener(TickEvent.TICK, onTick);
  130. }
  131. /************ controll APIS ****************/
  132. //starts the game
  133. public function start():void
  134. {
  135. //check if we have an instance of tickManager
  136. if(!tickManager)
  137. {
  138. //if not, create one and start it
  139. tickManager = TickManager.getInstance();
  140. //todo: look into why start is called inside the if statement
  141. tickManager.start();
  142. }
  143. //reset level
  144. reset();
  145. //initialize player ship
  146. initShip();
  147. //add enemies
  148. addEnemies();
  149. }
  150. //reset game state
  151. private function reset():void
  152. {
  153. //todo: need to be more consitent on how we listen for events / weak
  154. //listen for the onTick event from TickManager
  155. tickManager.addEventListener(TickEvent.TICK, onTick, false, 0, true);
  156. //reset tickCount
  157. tickCount = 0;
  158. //remove all existing enemies
  159. removeAllEnemies();
  160. //remove all existing missiles
  161. removeAllMissiles();
  162. //result current lives
  163. lives = DEFAULT_LIVES;
  164. //result score
  165. score = 0;
  166. //reset wave / level
  167. wave = 1;
  168. //todo: move this to a setter so we can set it in one place
  169. //update scorebar view
  170. scoreBar.score = score;
  171. scoreBar.lives = lives;
  172. scoreBar.wave = wave;
  173. }
  174. //removes all of the enemies from the game play area
  175. private function removeAllEnemies():void
  176. {
  177. var len:int = enemies.length;
  178. for(var i:int = len - 1; i >= 0; i--)
  179. {
  180. //note that removeEnemy does a slice to remove the specified
  181. //enemy.
  182. //for removing all enemies, we could refactor to just set enemies.length = 0
  183. //but would have to include code from removeEnemy
  184. //given the fact that we never have more that 12 or so enemies at once,
  185. //we are fine as is. However, if we added tons of enemies, it might be something
  186. //worth considering
  187. removeEnemy(enemies[i]);
  188. }
  189. }
  190. //removes all missiles from the gameplay area
  191. private function removeAllMissiles():void
  192. {
  193. var len:int = missiles.length;
  194. for(var i:int = len - 1; i >= 0; i--)
  195. {
  196. //see comment above in removeAllEnemies, for possible
  197. //optimization
  198. removeMissile(missiles[i]);
  199. }
  200. }
  201. //resets all enemies and removes them from the game area
  202. private function resetEnemies():void
  203. {
  204. for each(var e:Enemy in enemies)
  205. {
  206. gameObjectPool.returnGameObject(e);
  207. }
  208. }
  209. //reinitializes all enemies
  210. private function restartEnemies():void
  211. {
  212. //make sure there are not any stray missiles that could
  213. //collide when the enemy spawns
  214. removeAllMissiles();
  215. for each(var e:Enemy in enemies)
  216. {
  217. //reinitialize
  218. e.target = ship;
  219. e.initialize(bounds, ship, wave);
  220. //add to stage
  221. addGameObject(e);
  222. }
  223. }
  224. //initializes players ship
  225. private function initShip():void
  226. {
  227. //get a ship instance from the object pool
  228. ship = Ship(gameObjectPool.getGameObject(Ship));
  229. //reinitialize it
  230. ship.initialize(bounds, null, 1);
  231. //set the controller for the ship
  232. ship.gameController = gameController;
  233. //listen for when the ship fires
  234. ship.addEventListener(FireEvent.FIRE, onShipFire, false, 0, true);
  235. //add ship to stage
  236. addGameObject(ship);
  237. //position on stage
  238. ship.x = bounds.width / 2;
  239. ship.y = bounds.height / 2;
  240. }
  241. //add an initialize a new wave of enemies
  242. private function addEnemies():void
  243. {
  244. //make sure there are no stray missiles
  245. removeAllMissiles();
  246. var enemy:Enemy;
  247. //todo: should refactor to add ALL enemies (basic and advanced)
  248. //at same time.
  249. //loop through and create the enemies
  250. for(var i:int = 0; i < DEFAULT_NUMBER_ENEMIES; i++)
  251. {
  252. //get enemy instance from object pool
  253. enemy = BasicEnemy(gameObjectPool.getGameObject(BasicEnemy));
  254. //initialize
  255. enemy.initialize(bounds, null, 1 + (wave/5));
  256. //listen for when it gets destroyed
  257. enemy.addEventListener(GameObjectEvent.DESTROYED, onEnemyDestroyed,
  258. false, 0, true);
  259. //add object to stage
  260. addGameObject(enemy);
  261. //added to enemies vector
  262. enemies.push(enemy);
  263. }
  264. //check if we are at wave 4 or higher
  265. if(wave > 3)
  266. {
  267. var len:int = 1;
  268. // some logic to add more advanced enemies at high levels
  269. if(wave >= 9)
  270. {
  271. //wave 9 or higher, add 3
  272. len = 3;
  273. }
  274. else if(wave > 6)
  275. {
  276. //wave 7 or higher, add 2
  277. len = 2;
  278. }
  279. //otherwise add 1
  280. while(len-- != 0)
  281. {
  282. //add chaser enemies
  283. enemy = ChaserEnemy(gameObjectPool.getGameObject(ChaserEnemy));
  284. //initialize
  285. enemy.initialize(bounds, ship, wave);
  286. //listen for when it gets destroyed
  287. enemy.addEventListener(GameObjectEvent.DESTROYED, onEnemyDestroyed,
  288. false, 0, true);
  289. //add object to stage
  290. addGameObject(enemy);
  291. //added to enemies vector
  292. enemies.push(enemy);
  293. }
  294. }
  295. }
  296. /********** game events *************/
  297. //tick event, called on each game time interval
  298. private function onTick(e:TickEvent):void
  299. {
  300. //stop propogation of event for performance reasons
  301. e.stopPropagation();
  302. //check and see if there are any game object collisions
  303. checkCollisions();
  304. //update overall tick count
  305. tickCount++;
  306. //check if tick count is evenly divided by FPS (one second)
  307. if(!(tickCount % TickManager.FPS_RATE))
  308. {
  309. //see if it is time to do a game check to potentially
  310. //change game state
  311. //GAME_CHECK_INTERVAL is in seconds
  312. if(!(tickCount % GAME_CHECK_INTERVAL * TickManager.FPS_RATE))
  313. {
  314. gameCheck();
  315. }
  316. }
  317. }
  318. //called when it is time to potentially change the game state during
  319. //a game
  320. private function gameCheck():void
  321. {
  322. //if we are on wave one, do nothing
  323. if(wave < 2)
  324. {
  325. return;
  326. }
  327. //randomly dont do anyting (odds depend on the current wave)
  328. if((Math.random() * 100) + wave < 50)
  329. {
  330. return;
  331. }
  332. //check to see if a UFOEnemy is already on stage
  333. if(!ufoOnStage)
  334. {
  335. //get an instance of the UFOEnemy
  336. var enemy:UFOEnemy = UFOEnemy(gameObjectPool.getGameObject(UFOEnemy));
  337. //todo: we could move code below into its own function. This is done in a couple
  338. //of different places
  339. //initialize it
  340. enemy.initialize(bounds, ship, 1 + (wave/5));
  341. //list for destroyed event
  342. enemy.addEventListener(GameObjectEvent.DESTROYED, onEnemyDestroyed,
  343. false, 0, true);
  344. //listen for REMOVE event (when it goes off stage)
  345. enemy.addEventListener(GameObjectEvent.REMOVE, onRemoveItem, false,
  346. 0, true);
  347. //set that there is a UFOEnemy on stage
  348. ufoOnStage = true;
  349. //add to stage
  350. addGameObject(enemy);
  351. //add to enemies vector
  352. enemies.push(enemy);
  353. }
  354. }
  355. //adds a game object to the stage (if it is not already on the stage)
  356. private function addGameObject(go:GameObject, setToBottom:Boolean = false):void
  357. {
  358. //check and see if it is already on the display list
  359. if(!contains(go))
  360. {
  361. //if not, add it
  362. addChild(go);
  363. //check if we want to set the item to the bottom of the z order
  364. if(setToBottom)
  365. {
  366. //if so, set it
  367. setChildIndex(go, 0);
  368. }
  369. }
  370. //tell the game object to start
  371. go.start();
  372. }
  373. /********* game engine APIs **********/
  374. //creates and positions an explosion object
  375. private function createExplosion(px:Number, py:Number):void
  376. {
  377. //get an explosion instance
  378. var exp:Explosion = Explosion(gameObjectPool.getGameObject(Explosion));
  379. //initialize it
  380. exp.initialize(bounds);
  381. //set position
  382. exp.x = px;
  383. exp.y = py;
  384. //listen for its complete event
  385. exp.addEventListener(GameEvent.EXPLOSION_COMPLETE,
  386. onExplosionComplete,
  387. false, 0, true);
  388. //add to game area
  389. addGameObject(exp);
  390. }
  391. //check collisions between game objects
  392. //specifically, missiles and enemies
  393. //and enemies and the player's ship
  394. private function checkCollisions():void
  395. {
  396. /*
  397. Note, collision detection has been one of the areas
  398. where there has been extesnive optimizations and refactoring
  399. for performance reasons.
  400. The current version does a simple cirlce bounds test, which offers
  401. a good balance between performance, and visual accuracy.
  402. You can see a summary of various collision detection methods (most
  403. tried here at one point or another) at:
  404. http://www.mikechambers.com/blog/2009/06/26/relative-performance-for-collision-detection-techniques-in-actionscript-3/
  405. The most accurate detection used was doing pixel perfect collision detection:
  406. http://www.mikechambers.com/blog/2009/06/24/using-bitmapdata-hittest-for-collision-detection/
  407. http://www.mikechambers.com/blog/2009/06/25/strategies-for-optimizing-collision-detection-with-bitmapdata-hittest/
  408. however, this was removed to improve performance on iphone.
  409. I had also implimented pixel perfect collision detection with a grid based
  410. system for pairing down the tests that needed to be run. Again, this didnt perform great
  411. on iphone.
  412. http://www.mikechambers.com/blog/tag/as3dtc1/
  413. However, the current android based devices seem to run AIR / Flash content
  414. very well, and it may be possible to reimpliment pixel perfect collision detection with
  415. a grid based checkl.
  416. */
  417. //frameCount++;
  418. //check 1 out of every 3 frames
  419. //this is done for performance reasons.
  420. //can adjust depending on platform, and its performance
  421. //profile that the game is running on
  422. if((tickCount % 3) != 0)
  423. {
  424. return;
  425. }
  426. //if for some reason there is no ship, then dont do anything
  427. if(!ship)
  428. {
  429. return;
  430. }
  431. //get the bounds for the ship.
  432. var shipBounds:Rectangle = ship.getBounds(this);
  433. //loop through all of the enemies and check for collisions with missiles
  434. //and ships
  435. for each(var enemy:Enemy in enemies)
  436. {
  437. //get the bounds of the current enemy
  438. var enemyBounds:Rectangle = enemy.getBounds(this);
  439. //loop through all of the missiles
  440. for each(var missile:Missile in missiles)
  441. {
  442. //do a simple circle hit test check between thie missile and enemy bounds
  443. if(DisplayObjectUtil.hitTestCircle(enemyBounds,missile.getBounds(this)))
  444. {
  445. //if they hit, remove the missile
  446. removeMissile(missile);
  447. // do damage to the enemy. This hit API is here so an enemy could have
  448. //different levels of hits points or conditions for being destroyed.
  449. //right now, all enemies will be killed by a single shot, and will be removed
  450. //from the stage immediately
  451. enemy.hit(missile.damage);
  452. //if there are no more enemies, then stop looping
  453. if(enemies.length == 0)
  454. {
  455. return;
  456. }
  457. }
  458. }
  459. //todo: might be an issue here where an enemy could be destroyed by a missile above (and
  460. //removed) but it would still be checked for collision against the ship here.
  461. //check and see if an enemy is colliding with the player's ship
  462. if(DisplayObjectUtil.hitTestCircle(shipBounds,enemyBounds))
  463. {
  464. //if so, destroy the ship
  465. destroyShip();
  466. //remove the enemy
  467. removeEnemy(enemy);
  468. return;
  469. }
  470. }
  471. }
  472. //called when a wave / level is completed
  473. private function waveCompleted():void
  474. {
  475. //there is a pause in the action, so lets call the
  476. //garbage collector.
  477. //probably not really necessary anymore
  478. System.gc();
  479. //create a new instance of the WaveCompletedView. We are not caching it
  480. //since it content changes everytime (level #)
  481. waveCompletedView = new WaveCompletedView();
  482. //listen for then the wave view is done being display
  483. waveCompletedView.addEventListener(GameEvent.WAVE_VIEW_COMPLETE,
  484. onWaveViewCompleted,
  485. false, 0, true);
  486. //add the view to the game area
  487. addChild(waveCompletedView);
  488. //tell the view what wave was just completed
  489. waveCompletedView.display(wave);
  490. //position it in the center of the stage.
  491. waveCompletedView.x = bounds.width / 2 -
  492. (waveCompletedView.width / 2);
  493. waveCompletedView.y = bounds.height / 2 - waveCompletedView.height;
  494. //reset tickCount
  495. tickCount = 0;
  496. }
  497. //todo: use a third party libary for this event chaining
  498. //timer used to track time after a ship it hit
  499. private var deathPauseTimer:Timer;
  500. //called when the player's ship should be destroyed
  501. //i.e. when it is hit by an enemy
  502. private function destroyShip():void
  503. {
  504. //get the ships bounds
  505. var b:Rectangle = ship.getBounds(this);
  506. //create an explosion in the position that the ship was
  507. createExplosion(b.x + (b.width *.5),
  508. b.y + (b.height * .5));
  509. //remove the fire event listener from the ship
  510. ship.removeEventListener(FireEvent.FIRE, onShipFire);
  511. //return the ship to the object pool
  512. gameObjectPool.returnGameObject(ship);
  513. ship = null;
  514. //decrement the number of player / ship lives
  515. lives--;
  516. //null out the target for all of the enemies
  517. for each(var enm:Enemy in enemies)
  518. {
  519. enm.target = null;
  520. }
  521. //check and see if there are no more lives
  522. if(lives < 0)
  523. {
  524. //if not, call GC
  525. System.gc();
  526. //dispatch a game over event
  527. var e:ScreenControlEvent =
  528. new ScreenControlEvent(ScreenControlEvent.GAME_OVER);
  529. dispatchEvent(e);
  530. }
  531. else
  532. {
  533. //update scoreboard with new number of lives
  534. scoreBar.lives = lives;
  535. //if there are not more enemies (last one hit the ship)
  536. if(enemies.length < 1)
  537. {
  538. //complete the wave
  539. waveCompleted();
  540. return;
  541. }
  542. //start the death pause timer
  543. deathPauseTimer = new Timer(2000);
  544. deathPauseTimer.addEventListener(TimerEvent.TIMER,
  545. onDeathPauseTimer,
  546. false, 0, true);
  547. deathPauseTimer.start();
  548. //stop listening for tick events
  549. tickManager.removeEventListener(TickEvent.TICK, onTick);
  550. }
  551. }
  552. //removes the specified enemy from the game area
  553. private function removeEnemy(s:GameObject):void
  554. {
  555. //remove event listeners
  556. s.removeEventListener(GameObjectEvent.DESTROYED, onEnemyDestroyed);
  557. s.removeEventListener(GameObjectEvent.REMOVE, onRemoveItem);
  558. //return the enemy to the object pool
  559. gameObjectPool.returnGameObject(s);
  560. //if the enemy is a UFOEnemy
  561. if(s is UFOEnemy)
  562. {
  563. //set that there are not UFOEnemies on stage
  564. ufoOnStage = false;
  565. }
  566. //find the index of the enemies in the enemies vector
  567. var index:int = enemies.indexOf(s);
  568. //remove it
  569. enemies.splice(index, 1);
  570. //check to see if there are anymore enemies
  571. if(enemies.length < 1 && lives > -1)
  572. {
  573. waveCompleted();
  574. }
  575. }
  576. //removes the specified missile from the game area
  577. private function removeMissile(missile:Missile):void
  578. {
  579. //return the missile to the object pool
  580. gameObjectPool.returnGameObject(missile);
  581. //remove the listeners from the missile
  582. missile.removeEventListener(GameObjectEvent.REMOVE_MISSILE, onRemoveMissile);
  583. //find the index of the missile in the missiles vector
  584. var index:int = missiles.indexOf(missile);
  585. //remove the missile
  586. missiles.splice(index, 1);
  587. }
  588. /*********** game engine events ***********/
  589. //called when an explosion has completed its anaimation
  590. private function onExplosionComplete(e:GameEvent):void
  591. {
  592. //stop the event propagation for performance reasons
  593. e.stopImmediatePropagation();
  594. //get a reference to the explosion
  595. var explosion:Explosion = Explosion(e.target);
  596. //remove the event listeners
  597. explosion.removeEventListener(GameEvent.EXPLOSION_COMPLETE,
  598. onExplosionComplete);
  599. //return the explosion to the object pool
  600. gameObjectPool.returnGameObject(explosion);
  601. }
  602. //called when the wave view is done being displayed
  603. private function onWaveViewCompleted(e:GameEvent):void
  604. {
  605. //stop the event propagation for performance reasons
  606. e.stopImmediatePropagation();
  607. //remove the wave completed view from the display list
  608. removeChild(waveCompletedView);
  609. //stop listening for the event
  610. waveCompletedView.removeEventListener(GameEvent.WAVE_VIEW_COMPLETE,
  611. onWaveViewCompleted);
  612. //clear the reference
  613. waveCompletedView = null;
  614. //if there are no ships
  615. if(!ship)
  616. {
  617. //initialize a new ship
  618. initShip();
  619. }
  620. //increment the wave / level counter
  621. wave++;
  622. //update scorebar
  623. scoreBar.wave = wave;
  624. //add the enemies
  625. addEnemies();
  626. //listen for tick events
  627. tickManager.addEventListener(TickEvent.TICK, onTick, false, 0, true);
  628. }
  629. //called when the time interval after a ship is destroyed is up
  630. private function onDeathPauseTimer(e:TimerEvent):void
  631. {
  632. //stop event propagation for performance reasons
  633. e.stopImmediatePropagation();
  634. //reset all of the enemies
  635. resetEnemies();
  636. //initialize a new ship
  637. initShip();
  638. //stop the timer
  639. deathPauseTimer.stop();
  640. //remove listener
  641. deathPauseTimer.removeEventListener(TimerEvent.TIMER,
  642. onDeathPauseTimer);
  643. //add a new listener
  644. deathPauseTimer.addEventListener(TimerEvent.TIMER,
  645. onSpawnShipTimer, false,
  646. 0, true);
  647. //set the intervale to 2 seconds
  648. deathPauseTimer.delay = 2000;
  649. //start the timer again. This gives the player 2 seconds to react to the
  650. //ship respawning before the enemies reappear
  651. deathPauseTimer.start();
  652. }
  653. //called after a ship has been destroyed and respawned
  654. private function onSpawnShipTimer(e:TimerEvent):void
  655. {
  656. //stop event propagation for performance reasons
  657. e.stopImmediatePropagation();
  658. //todo: should we reuse this?
  659. //stop timer
  660. deathPauseTimer.stop();
  661. //remove listener
  662. deathPauseTimer.removeEventListener(TimerEvent.TIMER,
  663. onSpawnShipTimer);
  664. //clear reference to timer
  665. deathPauseTimer = null;
  666. //restart all of the enemies
  667. restartEnemies();
  668. //reset tick count
  669. tickCount = 0;
  670. //start listening for tick events
  671. tickManager.addEventListener(TickEvent.TICK, onTick, false, 0, true);
  672. }
  673. //called when an enemy is destroyed
  674. private function onEnemyDestroyed(e:GameObjectEvent):void
  675. {
  676. //stop event propagation for performance reasons
  677. e.stopImmediatePropagation();
  678. //get a reference to the enemy being destroyed
  679. var enemy:Enemy = Enemy(e.target);
  680. //get the enemy bounds
  681. var b:Rectangle = enemy.getBounds(this);
  682. //create an explosion in the place of the enemy
  683. createExplosion(b.x + (b.width * .5), b.y + (b.height * .5));
  684. //update the score value
  685. score += enemy.pointValue;
  686. //update the score display
  687. scoreBar.score = score;
  688. //remove the enemy
  689. removeEnemy(enemy);
  690. }
  691. //called when a ship fires a missles
  692. private function onShipFire(e:FireEvent):void
  693. {
  694. //stop event propagation for performance reasons
  695. e.stopImmediatePropagation();
  696. //get a reference to the missile
  697. var m:Missile = e.projectile;
  698. //position it
  699. m.x = ship.x;
  700. m.y = ship.y;
  701. //listen for then the missile needs to be removed (i.e. goes off stage)
  702. m.addEventListener(GameObjectEvent.REMOVE_MISSILE, onRemoveMissile, false, 0, true);
  703. //add the missile to the game area
  704. addGameObject(m, true);
  705. //add the missile to the vector of all missiles
  706. missiles.push(m);
  707. }
  708. //called when a missile should be removed (probably because it went off
  709. //of the game area).
  710. private function onRemoveMissile(e:GameObjectEvent):void
  711. {
  712. //stop event propagation for performance reasons
  713. e.stopImmediatePropagation();
  714. //remove the missile
  715. removeMissile(Missile(e.target));
  716. }
  717. //called when an item needs to be removed from the game area
  718. private function onRemoveItem(e:GameObjectEvent):void
  719. {
  720. //stop event propagation for performance reasons
  721. e.stopImmediatePropagation();
  722. //remove the item from the game area
  723. removeEnemy(GameObject(e.target));
  724. }
  725. }
  726. }