/ActionScript3/de/softgames/iso/display/IsoDisplayObject.as

https://github.com/dogeroski/CodeReview · ActionScript · 566 lines · 435 code · 97 blank · 34 comment · 20 complexity · 74c4a9aed309b34794a1b3651b37eb44 MD5 · raw file

  1. package de.softgames.iso.display
  2. {
  3. import de.softgames.display.BitmapMovieClip;
  4. import de.softgames.iso.IsoScene;
  5. import de.softgames.iso.geom.IsoPoint;
  6. import de.softgames.model.iso.IsoItemModel;
  7. import flash.display.DisplayObject;
  8. import flash.display.Graphics;
  9. import flash.display.MovieClip;
  10. import flash.display.Sprite;
  11. import flash.events.Event;
  12. import flash.events.MouseEvent;
  13. import flash.geom.Rectangle;
  14. public class IsoDisplayObject extends Sprite
  15. {
  16. protected var _asset : DisplayObject;
  17. private var _bitmapAsset : BitmapMovieClip;
  18. private var _cacheAsBitmap : Boolean;
  19. private var _positionPoint : IsoPoint;
  20. private var _width : Number;
  21. private var _length : Number;
  22. private var _height : Number;
  23. private var _scene : IsoScene;
  24. private var _debugSprite : Sprite;
  25. private var _drawDebugBounds : Boolean;
  26. private var _rotation : uint = 1;
  27. private var _model : IsoItemModel;
  28. private var _depth : uint = 0;
  29. private var _isDynamic : Boolean;
  30. private var _renderBounds : Rectangle;
  31. private var _animated : Boolean;
  32. private var _zoom : Number = 1;
  33. public function IsoDisplayObject()
  34. {
  35. super();
  36. _renderBounds = new Rectangle();
  37. _positionPoint = new IsoPoint();
  38. addEventListener(MouseEvent.CLICK, _clickHandler);
  39. addEventListener(Event.ADDED_TO_STAGE, _addedToStageHandler);
  40. addEventListener(Event.REMOVED_FROM_STAGE, _removedFromStageHandler);
  41. }
  42. private function _clickHandler(event : MouseEvent) : void
  43. {
  44. dispatchEvent(new Event(Event.SELECT, true));
  45. }
  46. private function _stopMC(mc : MovieClip) : void
  47. {
  48. for each(var child : MovieClip in mc)
  49. if(child) _stopMC(mc);
  50. if(mc) mc.gotoAndStop(1);
  51. }
  52. protected function _addedToStageHandler(event : Event) : void
  53. {
  54. }
  55. protected function _removedFromStageHandler(event : Event) : void
  56. {
  57. }
  58. protected function _updateSorter() : void
  59. {
  60. }
  61. protected function _drawBounds() : void
  62. {
  63. var p : IsoPoint = new IsoPoint();
  64. var g : Graphics = debugSprite.graphics;
  65. p.x = 0;
  66. p.y = 0;
  67. g.moveTo(p.cartesianX, p.cartesianY);
  68. g.lineStyle(1, 0xff0000, 1);
  69. p.x = 0;
  70. p.y = 0;
  71. p.z = height;
  72. g.moveTo(p.cartesianX, p.cartesianY);
  73. p.x = 0 + width;
  74. p.y = 0;
  75. p.z = height;
  76. g.lineTo(p.cartesianX, p.cartesianY);
  77. p.x = 0 + width;
  78. p.y = 0;
  79. p.z = 0;
  80. g.lineTo(p.cartesianX, p.cartesianY);
  81. p.x = 0 + width;
  82. p.y = 0 + length;
  83. p.z = 0;
  84. g.lineTo(p.cartesianX, p.cartesianY);
  85. p.x = 0;
  86. p.y = 0 + length;
  87. p.z = 0;
  88. g.lineTo(p.cartesianX, p.cartesianY);
  89. p.x = 0;
  90. p.y = 0 + length;
  91. p.z = height;
  92. g.lineTo(p.cartesianX, p.cartesianY);
  93. p.x = 0;
  94. p.y = 0;
  95. p.z = height;
  96. g.lineTo(p.cartesianX, p.cartesianY);
  97. g.endFill();
  98. p.x = width;
  99. p.y = 0;
  100. p.z = height;
  101. g.moveTo(p.cartesianX, p.cartesianY);
  102. p.x = width;
  103. p.y = length;
  104. p.z = height;
  105. g.lineTo(p.cartesianX, p.cartesianY);
  106. p.x = 0;
  107. p.y = length;
  108. p.z = height;
  109. g.lineTo(p.cartesianX, p.cartesianY);
  110. p.x = width;
  111. p.y = length;
  112. p.z = height;
  113. g.moveTo(p.cartesianX, p.cartesianY);
  114. p.x = width;
  115. p.y = length;
  116. p.z = 0;
  117. g.lineTo(p.cartesianX, p.cartesianY);
  118. }
  119. /**
  120. * Updates on screen (2d) position according to isometric position.
  121. */
  122. public function updatePosition() : void
  123. {
  124. screenX = _positionPoint.cartesianX;
  125. screenY = _positionPoint.cartesianY;
  126. _updateSorter();
  127. }
  128. /**
  129. * Moves object to cordinates in isometric perspective.
  130. */
  131. public function moveTo(x : Number, y : Number, z : Number) : void
  132. {
  133. positionPoint.x = x;
  134. positionPoint.y = y;
  135. positionPoint.z = z;
  136. updatePosition();
  137. }
  138. public function setSize(width : Number, length : Number, height : Number) : void
  139. {
  140. _width = width;
  141. _length = length;
  142. _height = height;
  143. if(drawDebugBounds) _drawBounds();
  144. }
  145. public function getRenderBounds() : Rectangle
  146. {
  147. _renderBounds.x = viewportTopLeftX;
  148. _renderBounds.y = viewportTopY;
  149. _renderBounds.width = Math.abs(_renderBounds.x - viewportTopRightX);
  150. _renderBounds.height = Math.abs(_renderBounds.y - viewportBottomY);
  151. return _renderBounds;
  152. }
  153. /**
  154. * Checks if object is in viewport bounds and therefore should be displayed.
  155. * If object is outside bounds than it is removed from display list.
  156. */
  157. public function checkIfItemIsInViewportBounds() : void
  158. {
  159. var viewportBounds : Rectangle = scene.viewport.renderBounds.clone();
  160. var itemBounds : Rectangle = getRenderBounds().clone();
  161. viewportBounds.x = viewportBounds.x - (viewportBounds.width * (1 / scene.zoom) - viewportBounds.width) / 2;
  162. viewportBounds.y = viewportBounds.y - (viewportBounds.height * (1 / scene.zoom) - viewportBounds.height) / 2;
  163. viewportBounds.width *= 1 / scene.zoom;
  164. viewportBounds.height *= 1 / scene.zoom;
  165. viewportBounds.offset(scene.viewport.itemsContainerOffset.x, scene.viewport.itemsContainerOffset.y);
  166. viewportBounds.offset(-scene.viewport.width / 2, -scene.viewport.height / 2);
  167. if(itemBounds.intersects(viewportBounds))
  168. {
  169. if(stage == null) scene.viewport.addIsoItem(this);
  170. }
  171. else
  172. {
  173. if(stage) scene.viewport.removeIsoItem(this);
  174. }
  175. }
  176. /**
  177. * Disposes object.
  178. */
  179. public function dispose() : void
  180. {
  181. disposeAsset();
  182. }
  183. /**
  184. * Disposes object asset.
  185. */
  186. public function disposeAsset() : void
  187. {
  188. if(asset is MovieClip)
  189. _stopMC(asset as MovieClip);
  190. }
  191. /**
  192. * Calculates object depth for depth sorting algorithm.
  193. */
  194. public static function getDepth(x : Number, y : Number, z : Number) : Number
  195. {
  196. return Math.round(x + y) * 0.866 + Math.round(z) * 0.707 + Math.round(x) * 0.707;
  197. }
  198. override public function get x() : Number
  199. {
  200. return _positionPoint.x;
  201. }
  202. override public function set x(value : Number) : void
  203. {
  204. _positionPoint.x = value;
  205. updatePosition();
  206. }
  207. override public function get y() : Number
  208. {
  209. return _positionPoint.y;
  210. }
  211. override public function set y(value : Number) : void
  212. {
  213. _positionPoint.y = value;
  214. updatePosition();
  215. }
  216. override public function get z() : Number
  217. {
  218. return _positionPoint.z;
  219. }
  220. override public function set z(value : Number) : void
  221. {
  222. _positionPoint.z = value;
  223. updatePosition();
  224. }
  225. public function get positionPoint() : IsoPoint
  226. {
  227. return _positionPoint;
  228. }
  229. public function set positionPoint(value : IsoPoint) : void
  230. {
  231. _positionPoint = value;
  232. updatePosition();
  233. }
  234. /**
  235. * Onscreen x position (in local cordinates system).
  236. */
  237. public function get screenX() : Number
  238. {
  239. return super.x;
  240. }
  241. public function set screenX(value : Number) : void
  242. {
  243. super.x = value;
  244. }
  245. /**
  246. * Onscreen y position (in local cordinates system).
  247. */
  248. public function get screenY() : Number
  249. {
  250. return super.y;
  251. }
  252. public function set screenY(value : Number) : void
  253. {
  254. super.y = value;
  255. }
  256. override public function get width() : Number
  257. {
  258. return _width;
  259. }
  260. override public function set width(value : Number) : void
  261. {
  262. _width = value;
  263. if(drawDebugBounds) _drawBounds();
  264. }
  265. public function get length() : Number
  266. {
  267. return _length;
  268. }
  269. public function set length(value : Number) : void
  270. {
  271. _length = value;
  272. if(drawDebugBounds) _drawBounds();
  273. }
  274. override public function get height() : Number
  275. {
  276. return _height;
  277. }
  278. override public function set height(value : Number) : void
  279. {
  280. _height = value;
  281. if(drawDebugBounds) _drawBounds();
  282. }
  283. public function get scene() : IsoScene
  284. {
  285. return _scene;
  286. }
  287. public function set scene(value : IsoScene) : void
  288. {
  289. _scene = value;
  290. }
  291. /**
  292. * Asset applied to this object.
  293. */
  294. public function get asset() : DisplayObject
  295. {
  296. return _asset;
  297. }
  298. public function set asset(value : DisplayObject) : void
  299. {
  300. _asset = value;
  301. while(numChildren)
  302. removeChildAt(0);
  303. if(cacheAsBitmap)
  304. {
  305. _bitmapAsset = new BitmapMovieClip(asset, animated);
  306. _bitmapAsset.smoothing = false;
  307. addChild(_bitmapAsset);
  308. }else
  309. {
  310. addChild(asset);
  311. }
  312. rotation = this.rotation;
  313. }
  314. public function get debugSprite() : Sprite
  315. {
  316. if(!_debugSprite)
  317. {
  318. _debugSprite = new Sprite();
  319. addChild(_debugSprite);
  320. }
  321. return _debugSprite;
  322. }
  323. /**
  324. * If <code>true</code> than debugger will draw object isometric bounds.
  325. */
  326. public function get drawDebugBounds() : Boolean
  327. {
  328. return _drawDebugBounds;
  329. }
  330. public function set drawDebugBounds(value : Boolean) : void
  331. {
  332. _drawDebugBounds = value;
  333. if(drawDebugBounds) _drawBounds();
  334. }
  335. override public function get rotation() : Number
  336. {
  337. return _rotation;
  338. }
  339. override public function set rotation(value : Number) : void
  340. {
  341. _rotation = value;
  342. if(asset)
  343. {
  344. if(cacheAsBitmap)
  345. MovieClip(_bitmapAsset.asset).gotoAndStop(rotation);
  346. else
  347. MovieClip(asset).gotoAndStop(rotation);
  348. }
  349. }
  350. override public function set cacheAsBitmap(value : Boolean) : void
  351. {
  352. _cacheAsBitmap = value;
  353. }
  354. override public function get cacheAsBitmap() : Boolean
  355. {
  356. return _cacheAsBitmap;
  357. }
  358. public function get model() : IsoItemModel
  359. {
  360. return _model;
  361. }
  362. public function set model(value : IsoItemModel) : void
  363. {
  364. _model = value;
  365. }
  366. public function set depth(value : uint) : void
  367. {
  368. _depth = value;
  369. }
  370. public function get depth() : uint
  371. {
  372. return _depth;
  373. }
  374. public function get viewportTopLeftX() : Number
  375. {
  376. return IsoPoint.calculateCartesianX(x, y + length, z + height);
  377. }
  378. public function get viewportTopLeftY() : Number
  379. {
  380. return IsoPoint.calculateCartesianY(x, y + length, z + height);
  381. }
  382. public function get viewportTopX() : Number
  383. {
  384. return IsoPoint.calculateCartesianX(x, y, z + height);
  385. }
  386. public function get viewportTopY() : Number
  387. {
  388. return IsoPoint.calculateCartesianY(x, y, z + height);
  389. }
  390. public function get viewportTopRightX() : Number
  391. {
  392. return IsoPoint.calculateCartesianX(x + width, y, z + height);
  393. }
  394. public function get viewportTopRightY() : Number
  395. {
  396. return IsoPoint.calculateCartesianY(x + width, y, z + height);
  397. }
  398. public function get viewportBottomLeftX() : Number
  399. {
  400. return IsoPoint.calculateCartesianX(x, y + length, z);
  401. }
  402. public function get viewportBottomLeftY() : Number
  403. {
  404. return IsoPoint.calculateCartesianY(x, y + length, z);
  405. }
  406. public function get viewportBottomX() : Number
  407. {
  408. return IsoPoint.calculateCartesianX(x + width, y + length, z);
  409. }
  410. public function get viewportBottomY() : Number
  411. {
  412. return IsoPoint.calculateCartesianY(x + width, y + length, z);
  413. }
  414. public function get viewportBottomRightX() : Number
  415. {
  416. return IsoPoint.calculateCartesianX(x + width, y, z);
  417. }
  418. public function get viewportBottomRightY() : Number
  419. {
  420. return IsoPoint.calculateCartesianY(x + width, y, z);
  421. }
  422. public function get tileX() : uint
  423. {
  424. return Math.round(x / scene.tileSize);
  425. }
  426. public function get tileY() : uint
  427. {
  428. return Math.round(x / scene.tileSize);
  429. }
  430. /**
  431. * Determines if item is dynamic (need to be resorted every frame or sort cycle).
  432. */
  433. public function get isDynamic() : Boolean
  434. {
  435. return _isDynamic;
  436. }
  437. public function set isDynamic(value : Boolean) : void
  438. {
  439. _isDynamic = value;
  440. }
  441. public function get animated() : Boolean
  442. {
  443. return _animated;
  444. }
  445. public function set animated(value : Boolean) : void
  446. {
  447. _animated = value;
  448. }
  449. public function get zoom() : Number
  450. {
  451. return _zoom;
  452. }
  453. public function set zoom(value : Number) : void
  454. {
  455. if(zoom != value)
  456. {
  457. _zoom = value;
  458. if(_bitmapAsset)
  459. {
  460. _bitmapAsset.asset.scaleX = zoom;
  461. _bitmapAsset.asset.scaleY = zoom;
  462. _bitmapAsset.render();
  463. _bitmapAsset.width = asset.width / zoom;
  464. _bitmapAsset.height = asset.height / zoom;
  465. }
  466. }
  467. }
  468. }
  469. }