PageRenderTime 117ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/src/com/chasekernan/hxnova/client/mapviewer/MapImage.hx

http://hxnova.googlecode.com/
Haxe | 374 lines | 266 code | 64 blank | 44 comment | 65 complexity | 6c4bb8d6e1e3327a3a0e44e7ed502a77 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /**
  2. * Copyright (C) 2008 Chase Kernan
  3. * chase.kernan@gmail.com
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. **/
  19. package com.chasekernan.hxnova.client.mapviewer;
  20. import com.chasekernan.hxnova.core.dataholders.FleetHolder;
  21. import com.chasekernan.hxnova.core.dataholders.StarsHolder;
  22. import com.chasekernan.hxnova.core.dataholders.Global;
  23. import com.chasekernan.hxnova.core.players.Player;
  24. import com.chasekernan.hxnova.core.players.PlayerRelations;
  25. import com.chasekernan.hxnova.utils.Utils;
  26. import com.chasekernan.hxnova.core.races.Race;
  27. import com.chasekernan.hxnova.core.stars.Star;
  28. import flash.display.DisplayObject;
  29. import flash.display.Sprite;
  30. import flash.events.KeyboardEvent;
  31. import flash.events.MouseEvent;
  32. import flash.events.Event;
  33. import flash.events.MouseEvent;
  34. import flash.Lib;
  35. import flash.display.Bitmap;
  36. import flash.display.BitmapData;
  37. import flash.geom.Rectangle;
  38. import flash.text.TextField;
  39. import flash.text.TextFormat;
  40. import flash.text.TextFormatAlign;
  41. import com.chasekernan.hxnova.utils.Vector;
  42. typedef RGB = {
  43. var rb : Int;
  44. var gb : Int;
  45. var bb : Int;
  46. }
  47. typedef ScanPoint = {
  48. var location : Vector;
  49. var radius : Int;
  50. }
  51. class MapImage extends Sprite {
  52. public static var DEFAULT_WIDTH = 700;
  53. public static var DEFAULT_HIEGHT = 600;
  54. public static var DEFAULT_BACKGROUND_COLOR = 0x111111;
  55. public static var INHERENT_ZOOM = 1.5;
  56. public static var GRID_COLOR = 0xFFFFFF;
  57. public static var GRID_SPACING = 100;
  58. public static var MAX_GREEN_STAR = 0x00FF00;
  59. public static var MIN_GREEN_STAR = 0x787a50;
  60. public static var MAX_RED_STAR = 0xff0000;
  61. public static var MIN_RED_STAR = 0xff8000;
  62. public static var NORMAL_SCAN_COLOR = 0x661c1c;
  63. public static var PENETRATING_SCAN_COLOR = 0x656300;
  64. public static var UNKNOWN_STAR = 0x999999;
  65. public static var MAX_RADIUS = 5;
  66. public static var MIN_POP_RADIUS = 2;
  67. public static var HW_RADIUS = 6;
  68. public static var MIN_RADIUS = 1;
  69. public static var LINE_THICKNESS = 1.25;
  70. public static var GREEN_ADDED_THICKNESS = 0.25;
  71. public static var FLAG_LINE = 0.25;
  72. public static var NORMAL_ZOOM_FACTOR = 10;
  73. public static var NORMAL_CAMERA_ZOOM = 3.0;
  74. public static var FRIENDLY_COLOR = 0xcccc00;
  75. public static var NUETRAL_COLOR = 0x999999;
  76. public static var ENEMY_COLOR = 0xcc0000;
  77. public static var SELF_COLOR = 0x0066ff;
  78. private static var options : MapOptions;
  79. private static var dimensions : Vector;
  80. private static var map : Sprite;
  81. private static var normalScans : Sprite;
  82. private static var penScans : Sprite;
  83. private static var image : Sprite;
  84. private static var player : Player;
  85. private static var starNames : Array<TextField>;
  86. private static var namesHolder : Sprite;
  87. /**
  88. Draws the map from the given player's perspective, using the given
  89. options.
  90. This relies on the data being held in [Global].
  91. **/
  92. public static function getImage(mapOptions : MapOptions, pointOfView : Player) : Sprite {
  93. options = mapOptions;
  94. player = pointOfView;
  95. image = new Sprite();
  96. map = new Sprite();
  97. normalScans = new Sprite();
  98. penScans = new Sprite();
  99. namesHolder = new Sprite();
  100. image.addChild(normalScans);
  101. image.addChild(penScans);
  102. image.addChild(map);
  103. image.addChild(namesHolder);
  104. dimensions = new Vector(0, 0);
  105. for (star in Global.stars) {
  106. if (star.location.x > dimensions.x) dimensions.x = star.location.x;
  107. if (star.location.y > dimensions.y) dimensions.y = star.location.y;
  108. }
  109. starNames = new Array();
  110. renderBackground();
  111. handleScanners();
  112. renderGrid();
  113. for (star in Global.stars) renderStar(star, player);
  114. }
  115. private static inline function renderBackground() {
  116. image.graphics.beginFill(DEFAULT_BACKGROUND_COLOR);
  117. image.graphics.drawRect(0, 0, dimensions.x, dimensions.y);
  118. image.graphics.endFill();
  119. }
  120. private static inline function renderGrid() {
  121. if (options.drawGrid) {
  122. map.graphics.lineStyle(0.25, GRID_COLOR, 0.1);
  123. for (i in 1...Math.ceil(dimensions.x / GRID_SPACING)) {
  124. map.graphics.moveTo(i * GRID_SPACING, 0);
  125. map.graphics.lineTo(i * GRID_SPACING, dimensions.y);
  126. }
  127. for (j in 1...Math.ceil(dimensions.y / GRID_SPACING)) {
  128. map.graphics.moveTo(0, j * GRID_SPACING);
  129. map.graphics.lineTo(dimensions.x, j * GRID_SPACING);
  130. }
  131. }
  132. }
  133. private static function renderScans(points : Array<ScanPoint>, normal : Bool) {
  134. var maskSprite = new Sprite();
  135. var colorSprite = if (normal) normalScans else penScans;
  136. colorSprite.graphics.beginFill(if (normal) NORMAL_SCAN_COLOR else
  137. PENETRATING_SCAN_COLOR);
  138. colorSprite.graphics.drawRect(0, 0, mapWidth, mapHeight);
  139. colorSprite.graphics.endFill();
  140. maskSprite.graphics.lineStyle(0);
  141. for (point in points) {
  142. maskSprite.graphics.beginFill(0xFFFFFF);
  143. maskSprite.graphics.drawCircle(point.location.x, point.location.y,
  144. point.radius);
  145. maskSprite.graphics.endFill();
  146. }
  147. colorSprite.mask = maskSprite;
  148. image.addChild(maskSprite);
  149. maskSprite.visible = false;
  150. }
  151. private static inline function renderStar(s : Star, p : Player) {
  152. var zoomFactor = options.zoom;
  153. if (s.concentrations == null || s.environment == null) {
  154. map.graphics.lineStyle(LINE_THICKNESS, UNKNOWN_STAR);
  155. map.graphics.drawCircle(s.location.x, s.location.y, MIN_RADIUS);
  156. } else {
  157. var habPercent = s.getHabPercent(p.race);
  158. var color =
  159. if (habPercent < 0)
  160. Utils.mixColors(MIN_RED_STAR, MAX_RED_STAR, habPercent / -0.45)
  161. else
  162. Utils.mixColors(MIN_GREEN_STAR, MAX_GREEN_STAR, habPercent);
  163. var thickness = LINE_THICKNESS;
  164. //if (habPercent > 0) thickness += GREEN_ADDED_THICKNESS;
  165. map.graphics.lineStyle(thickness, color);
  166. var size =
  167. if (s.isHomeworld != null && s.isHomeworld)
  168. HW_RADIUS
  169. else if (s.population != null || s.population == 0)
  170. MIN_RADIUS
  171. else
  172. Math.max(MIN_POP_RADIUS,
  173. MAX_RADIUS * (s.population / Star.MAX_POPULATION));
  174. map.graphics.drawCircle(s.location.x, s.location.y, size);
  175. map.graphics.lineStyle(0.25, color);
  176. map.graphics.drawCircle(s.location.x, s.location.y, 0.1);
  177. //draw in the name
  178. var name = new TextField();
  179. name.width = 100;
  180. name.height = 30;
  181. name.selectable = false;
  182. name.textColor = 0xFFFFFF;
  183. name.text = s.name;
  184. var format = new TextFormat();
  185. format.align = TextFormatAlign.CENTER;
  186. format.size = 6;
  187. name.setTextFormat(format);
  188. name.x = s.location.x - 100 / 2;
  189. name.y = s.location.y + size;
  190. namesHolder.addChild(name);
  191. starNames.push(name);
  192. if (s.owner != null && s.owner.id != null && s.owner.id != -1) {
  193. if (s.owner.id == p.id) {
  194. drawSelfFlag(s.location.x, s.location.y);
  195. } else if (p.relations != null) {
  196. drawOtherFlag(s.location.x, s.location.y,
  197. p.relations.getRelationTo(s.owner));
  198. }
  199. }
  200. }
  201. }
  202. private static inline function drawFlag(x : Float, y : Float, color : Int) {
  203. x = Math.round(x);
  204. y = Math.round(y);
  205. map.graphics.lineStyle(FLAG_LINE, color);
  206. map.graphics.moveTo(x, y);
  207. map.graphics.lineTo(x, y - 13);
  208. map.graphics.drawRect(x + 1.5, y - 13, 10, 5);
  209. }
  210. private static inline function drawOtherFlag(x : Float, y : Float,
  211. relation : Relation) {
  212. drawFlag(x, y, switch (relation) {
  213. case Relation.Friend: FRIENDLY_COLOR;
  214. case Relation.Nuetral: NUETRAL_COLOR;
  215. case Relation.Enemy: ENEMY_COLOR;
  216. });
  217. }
  218. private static inline function drawSelfFlag(x : Float, y : Float) {
  219. drawFlag(x, y, SELF_COLOR);
  220. }
  221. private static inline function handleScanners(stars : StarsHolder,
  222. fleets : FleetHolder,
  223. player : Player) {
  224. if (!options.drawScanners) return;
  225. //mostly a copy from [Scanning]
  226. var penPoints = new Array<ScanPoint>();
  227. var normalPoints = new Array<ScanPoint>();
  228. normalPoints.push({radius : 70, location : new Vector(50, 50)});
  229. normalPoints.push({radius : 40, location : new Vector(70, 90)});
  230. //add star points
  231. var scanner = player.starScanner;
  232. if(scanner != null) {
  233. var nRadius = scanner.range;
  234. var pRadius = scanner.penetratingRange;
  235. if (scanner.isPenetrating()) {
  236. for (star in stars) {
  237. if (star == null) continue;
  238. if (star.owner.id != player.id) continue;
  239. if (star.hasScanner == null || !star.hasScanner) continue;
  240. penPoints.push(
  241. {radius : pRadius,
  242. location : star.location.clone()} );
  243. normalPoints.push(
  244. {radius : nRadius,
  245. location : star.location.clone()} );
  246. }
  247. } else {
  248. for (star in stars) {
  249. if (star == null) continue;
  250. if (star.owner == null ||
  251. star.owner.id != player.id) continue;
  252. if (star.hasScanner == null || !star.hasScanner) continue;
  253. normalPoints.push( {radius : nRadius,
  254. location : star.location.clone()} );
  255. }
  256. }
  257. }
  258. //add fleet points
  259. for (fleet in fleets) {
  260. if (fleet.owner.id != player.id) continue;
  261. var pRadius = fleet.getPenetratingScanningRange();
  262. var nRadius = fleet.getNormalScanningRange();
  263. if (pRadius > 0) {
  264. penPoints.push( {radius : pRadius, location : fleet.location} );
  265. }
  266. if (nRadius > 0) {
  267. normalPoints.push(
  268. {radius : pRadius, location : fleet.location} );
  269. }
  270. }
  271. renderScans(penPoints, false);
  272. renderScans(normalPoints, true);
  273. }
  274. }
  275. /**
  276. Pass an instance of this to [MapImage.getImage].
  277. **/
  278. class MapOptions {
  279. public var zoom : Float;
  280. public var drawStarNames : Bool;
  281. public var drawFleets : Bool;
  282. public var drawFleetNames : Bool;
  283. public var drawGrid : Bool;
  284. public var drawStarOwner : Bool;
  285. public var drawFleetAmounts : Bool;
  286. public var drawScanners : Bool;
  287. /**
  288. Creates a new set of options.
  289. Defaults:
  290. zoom = 1.0
  291. drawStarNames = true
  292. drawFleets = true
  293. drawFleetNames = false
  294. drawFleetAmounts = true
  295. drawGrid = true
  296. drawStarOwner = true
  297. drawScanners = true
  298. **/
  299. public function new() {
  300. zoom = 1.0;
  301. drawStarNames = true;
  302. drawFleets = true;
  303. drawFleetNames = false;
  304. drawFleetAmounts = true;
  305. drawGrid = true;
  306. drawStarOwner = true;
  307. drawScanners = true;
  308. }
  309. }