PageRenderTime 77ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/src/de/nulldesign/nd2d/display/World2D.as

https://github.com/tonkoh/nd2d
ActionScript | 303 lines | 172 code | 50 blank | 81 comment | 25 complexity | 38ad141ac393c1d202092f1ba419ef2f MD5 | raw file
  1. /*
  2. * ND2D - A Flash Molehill GPU accelerated 2D engine
  3. *
  4. * Author: Lars Gerckens
  5. * Copyright (c) nulldesign 2011
  6. * Repository URL: http://github.com/nulldesign/nd2d
  7. * Getting started: https://github.com/nulldesign/nd2d/wiki
  8. *
  9. *
  10. * Licence Agreement
  11. *
  12. * Permission is hereby granted, free of charge, to any person obtaining a copy
  13. * of this software and associated documentation files (the "Software"), to deal
  14. * in the Software without restriction, including without limitation the rights
  15. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  16. * copies of the Software, and to permit persons to whom the Software is
  17. * furnished to do so, subject to the following conditions:
  18. *
  19. * The above copyright notice and this permission notice shall be included in
  20. * all copies or substantial portions of the Software.
  21. *
  22. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  23. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  24. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  25. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  26. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  27. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  28. * THE SOFTWARE.
  29. */
  30. package de.nulldesign.nd2d.display {
  31. import flash.display.Sprite;
  32. import flash.display3D.Context3D;
  33. import flash.display3D.Context3DCompareMode;
  34. import flash.display3D.Context3DTriangleFace;
  35. import flash.events.ErrorEvent;
  36. import flash.events.Event;
  37. import flash.events.MouseEvent;
  38. import flash.events.TimerEvent;
  39. import flash.geom.Rectangle;
  40. import flash.geom.Vector3D;
  41. import flash.utils.Timer;
  42. import flash.utils.getTimer;
  43. import net.hires.debug.Stats;
  44. /**
  45. * Dispatched when the World2D is initialized and the context3D is available. The flag 'isHardwareAccelerated' is available then
  46. * @eventType flash.events.Event.INIT
  47. */
  48. [Event(name="init", type="flash.events.Event")]
  49. /**
  50. * <p>Baseclass for ND2D</p>
  51. * Extend this class and add your own scenes and sprites
  52. *
  53. * Set up your project like this:
  54. * <ul>
  55. * <li>MyGameWorld2D</li>
  56. * <li>- MyStartScene2D</li>
  57. * <li>-- StartButtonSprite2D</li>
  58. * <li>-- ...</li>
  59. * <li>- MyGameScene2D</li>
  60. * <li>-- GameSprites2D</li>
  61. * <li>-- ...</li>
  62. * </ul>
  63. * <p>Put your game logic in the step() method of each scene / node</p>
  64. *
  65. * You can switch between scenes with the setActiveScene method of World2D.
  66. * There can be only one active scene.
  67. *
  68. * NOTICE: API change. You have to call start once to initialize the world
  69. *
  70. */ public class World2D extends Sprite {
  71. protected var camera:Camera2D = new Camera2D(1, 1);
  72. protected var context3D:Context3D;
  73. protected var stageID:uint;
  74. protected var scene:Scene2D;
  75. protected var frameRate:uint;
  76. protected var isPaused:Boolean = false;
  77. protected var bounds:Rectangle;
  78. protected var frameBased:Boolean;
  79. protected var lastFramesTime:Number = 0.0;
  80. protected var enableErrorChecking:Boolean = false;
  81. private var renderTimer:Timer;
  82. private var renderMode:String;
  83. private var mousePosition:Vector3D = new Vector3D(0.0, 0.0, 0.0);
  84. private var antialiasing:uint = 2;
  85. private var deviceInitialized:Boolean = false;
  86. private var deviceWasLost:Boolean = false;
  87. private var initializeNodesAfterStartUp:Boolean = false;
  88. public static var isHardwareAccelerated:Boolean;
  89. /**
  90. * Constructor of class world
  91. * @param renderMode Context3DRenderMode (auto, software)
  92. * @param frameRate timer and the swf will be set to this framerate
  93. * @param frameBased whether to use a timer or a enterFrame to step()
  94. * @param bounds the worlds boundaries
  95. * @param stageID
  96. */
  97. public function World2D(renderMode:String, frameRate:uint, frameBased:Boolean, bounds:Rectangle = null, stageID:uint = 0) {
  98. this.renderMode = renderMode;
  99. this.frameRate = frameRate;
  100. this.bounds = bounds;
  101. this.frameBased = frameBased;
  102. this.stageID = stageID;
  103. addEventListener(Event.ADDED_TO_STAGE, addedToStage);
  104. }
  105. protected function addedToStage(event:Event):void {
  106. removeEventListener(Event.ADDED_TO_STAGE, addedToStage);
  107. stage.addEventListener(Event.RESIZE, resizeStage);
  108. stage.frameRate = frameRate;
  109. stage.stage3Ds[stageID].addEventListener(Event.CONTEXT3D_CREATE, context3DCreated);
  110. stage.stage3Ds[stageID].addEventListener(ErrorEvent.ERROR, context3DError);
  111. stage.stage3Ds[stageID].requestContext3D(renderMode);
  112. stage.addEventListener(MouseEvent.CLICK, mouseEventHandler);
  113. stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseEventHandler);
  114. stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseEventHandler);
  115. stage.addEventListener(MouseEvent.MOUSE_UP, mouseEventHandler);
  116. }
  117. protected function context3DError(e:ErrorEvent):void {
  118. throw new Error("The SWF is not embedded properly. The 3D context can't be created. Wrong WMODE? Set it to 'direct'.");
  119. }
  120. protected function context3DCreated(e:Event):void {
  121. context3D = stage.stage3Ds[stageID].context3D;
  122. context3D.enableErrorChecking = enableErrorChecking;
  123. context3D.setCulling(Context3DTriangleFace.NONE);
  124. context3D.setDepthTest(false, Context3DCompareMode.ALWAYS);
  125. isHardwareAccelerated = context3D.driverInfo.toLowerCase().indexOf("software") == -1;
  126. resizeStage();
  127. // means we got the Event.CONTEXT3D_CREATE for the second time, the device was lost. reinit everything
  128. if(deviceInitialized) {
  129. deviceWasLost = true;
  130. }
  131. deviceInitialized = true;
  132. if(initializeNodesAfterStartUp) {
  133. doInitializeNodes();
  134. }
  135. dispatchEvent(new Event(Event.INIT));
  136. }
  137. protected function mouseEventHandler(event:MouseEvent):void {
  138. if(scene && scene.mouseEnabled && stage && camera) {
  139. var mouseEventType:String = event.type;
  140. // transformation of normalized coordinates between -1 and 1
  141. mousePosition.x = (stage.mouseX - 0.0) / camera.sceneWidth * 2.0 - 1.0;
  142. mousePosition.y = -((stage.mouseY - 0.0) / camera.sceneHeight * 2.0 - 1.0);
  143. mousePosition.z = 0.0;
  144. mousePosition.w = 1.0;
  145. scene.processMouseEvents(mousePosition, mouseEventType, camera.getViewProjectionMatrix());
  146. }
  147. }
  148. protected function resizeStage(e:Event = null):void {
  149. if(!context3D) return;
  150. var rect:Rectangle = bounds ? bounds : new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);
  151. stage.stage3Ds[stageID].x = rect.x;
  152. stage.stage3Ds[stageID].y = rect.y;
  153. context3D.configureBackBuffer(rect.width, rect.height, antialiasing, false);
  154. camera.resizeCameraStage(rect.width, rect.height);
  155. }
  156. protected function mainLoop(e:Event):void {
  157. var t:Number = getTimer() / 1000.0;
  158. var elapsed:Number = t - lastFramesTime;
  159. if(scene) {
  160. context3D.clear(scene.br, scene.bg, scene.bb, 1.0);
  161. if(!isPaused) {
  162. scene.timeSinceStartInSeconds = t;
  163. scene.stepNode(elapsed);
  164. }
  165. if(deviceWasLost) {
  166. scene.handleDeviceLoss();
  167. deviceWasLost = false;
  168. }
  169. scene.drawNode(context3D, camera, false);
  170. context3D.present();
  171. }
  172. lastFramesTime = t;
  173. }
  174. protected function setActiveScene(value:Scene2D):void {
  175. if(scene) {
  176. scene.setStageRef(null);
  177. scene.setCameraRef(null);
  178. }
  179. this.scene = value;
  180. if(scene) {
  181. scene.setCameraRef(camera);
  182. scene.setStageRef(stage);
  183. }
  184. }
  185. public function start():void {
  186. if(!renderTimer && !frameBased) {
  187. renderTimer = new Timer(1000 / frameRate);
  188. renderTimer.addEventListener(TimerEvent.TIMER, mainLoop);
  189. }
  190. wakeUp();
  191. }
  192. /**
  193. * Pause all movement in your game. The drawing loop will still fire
  194. */
  195. public function pause():void {
  196. isPaused = true;
  197. }
  198. /**
  199. * Resume movement in your game.
  200. */
  201. public function resume():void {
  202. isPaused = false;
  203. }
  204. /**
  205. * Put everything to sleep, no drawing and step loop will be fired
  206. */
  207. public function sleep():void {
  208. if(frameBased) {
  209. removeEventListener(Event.ENTER_FRAME, mainLoop);
  210. } else {
  211. if(renderTimer.running)
  212. renderTimer.stop();
  213. }
  214. if(context3D) {
  215. context3D.clear(scene.br, scene.bg, scene.bb, 1.0);
  216. context3D.present();
  217. }
  218. }
  219. /**
  220. * wake up from sleep. draw / step loops will start to fire again
  221. */
  222. public function wakeUp():void {
  223. if(frameBased) {
  224. removeEventListener(Event.ENTER_FRAME, mainLoop);
  225. addEventListener(Event.ENTER_FRAME, mainLoop);
  226. } else {
  227. if(!renderTimer.running)
  228. renderTimer.start();
  229. }
  230. }
  231. /**
  232. * optionally you can call this method to initialize all your object in the active scene
  233. * an event will be dispatched when the initializing is done
  234. */
  235. public function initializeNodes():void {
  236. if(deviceInitialized) {
  237. doInitializeNodes();
  238. } else {
  239. initializeNodesAfterStartUp = true;
  240. }
  241. }
  242. private function doInitializeNodes():void {
  243. // TODO traverse through displaylist and initialize nodes in a seperate thread / loop? dispatch event when ready, etc...
  244. trace("TODO! Implement initializeNodes");
  245. }
  246. public function destroy():void {
  247. sleep();
  248. if(context3D) {
  249. context3D.dispose();
  250. }
  251. }
  252. }
  253. }