/src/com/chasekernan/hxnova/client/mapviewer/MapViewer.hx
http://hxnova.googlecode.com/ · Haxe · 441 lines · 303 code · 71 blank · 67 comment · 61 complexity · 3f3c0277826dfe6e6bf1af898c2f7442 MD5 · raw file
- /**
- * Copyright (C) 2008 Chase Kernan
- * chase.kernan@gmail.com
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- **/
-
- package com.chasekernan.hxnova.client.mapviewer;
-
- import com.chasekernan.hxnova.client.Selection;
- import flash.display.Sprite;
- import flash.filters.GlowFilter;
- import flash.geom.Rectangle;
- import com.chasekernan.hxnova.utils.IntVector;
- import com.chasekernan.hxnova.utils.Vector;
- import com.chasekernan.hxnova.core.dataholders.Global;
- import com.chasekernan.hxnova.core.players.Player;
-
- private typedef ScanPoint = {
- var location : Vector;
- var radius : Int;
- }
-
- class MapViewer extends Sprite {
-
- public static var EPSILON = 10.0;
- public static var EPSILON_SQUARED = EPSILON * EPSILON;
-
- public static var DEFAULT_BACKGROUND_COLOR = 0x000000;//0x111111;
- public static var NORMAL_SCAN_COLOR = 0x770000;//0x661c1c;
- public static var PENETRATING_SCAN_COLOR = 0x444400;
- public static var GRID_COLOR = 0xFFFFFF;
- public static var GRID_SPACING = 100;
- public static var FRIENDLY_COLOR = 0xcccc00;
- public static var NUETRAL_COLOR = 0x999999;
- public static var ENEMY_COLOR = 0xcc0000;
- public static var SELF_COLOR = 0x0066ff;
- public static var SELECTION_COLOR = 0x33ffff;
- public static var SELECTION_GLOW = {
- new GlowFilter(SELECTION_COLOR, 1, 8, 8, 2, 2);
- };
-
- public var stars : Array<StarObject>;
- private var starsHolder : Sprite;
-
- private var fleetsHolder : Sprite;
- public var fleets : Array<FleetObject>;
-
- public var salvage : Array<SalvageObject>;
- private var salvageHolder : Sprite;
-
- public var pointOfView : Player;
-
- private var background : Sprite;
- private var grid : Sprite;
- private var screenSize : IntVector;
- private var options : MapOptions;
- private var bounds : Rectangle;
- private var normalScans : Sprite;
- private var penScans : Sprite;
- private var penMaskSprite : Sprite;
- private var normMaskSprite : Sprite;
- private var oldTopLeft : IntVector;
-
- public function new(screenSize : IntVector, pointOfView : Player) {
- super();
-
- if (pointOfView == null) throw "Point of view cannot be null.";
- this.pointOfView = pointOfView;
-
- setScreenSize(screenSize);
-
- background = new Sprite();
- addChild(background);
-
- normalScans = new Sprite();
- addChild(normalScans);
- normMaskSprite = new Sprite();
- addChild(normMaskSprite);
-
- penScans = new Sprite();
- addChild(penScans);
- penMaskSprite = new Sprite();
- addChild(penMaskSprite);
-
- grid = new Sprite();
- addChild(grid);
-
- salvageHolder = new Sprite();
- addChild(salvageHolder);
- salvage = new Array();
- for (salv in Global.salvage) {
- var obj = new SalvageObject(salv);
- salvageHolder.addChild(obj);
- salvage.push(obj);
- }
-
- starsHolder = new Sprite();
- addChild(starsHolder);
- stars = new Array();
- for (star in Global.stars) {
- var obj = new StarObject(star);
- starsHolder.addChild(obj);
- stars.push(obj);
- }
-
- fleetsHolder = new Sprite();
- addChild(fleetsHolder);
- fleets = new Array();
- for (fleet in Global.fleets) {
- var obj = new FleetObject(fleet);
- fleetsHolder.addChild(obj);
- fleets.push(obj);
- }
-
- var me = this;
- Selection.addListener(function() {
- if (me.oldTopLeft == null) me.oldTopLeft = new IntVector(0, 0);
- me.render(me.oldTopLeft);
- });
- }
-
- public function setScreenSize(to : IntVector) : IntVector {
- if (to == null) throw "Screen size cannot be null.";
-
- screenSize = to.clone();
- return screenSize;
- }
-
- public function getScreenSize() : IntVector {
- return screenSize;
- }
-
- /**
- Renders the map with the top left point being a _game_ point.
- In order for the options to be omitted, [render] needs to have been
- called before with the options given as it uses the previously set
- options.
- **/
- public function render(topLeft : IntVector, ?options : MapOptions) {
- if (options == null) {
- if (this.options == null) {
- throw "Map options must have been set previously in order to" +
- " omit them in future calls.";
- }
- options = this.options;
- } else {
- this.options = options;
- }
-
- oldTopLeft = topLeft.clone();
-
- bounds = new Rectangle(topLeft.x, topLeft.y,
- screenSize.x / options.zoom,
- screenSize.y / options.zoom);
-
- createBackground();
- if (options.drawScanners) {
- normalScans.visible = true;
- penScans.visible = true;
- handleScanners();
- } else {
- normalScans.visible = false;
- penScans.visible = false;
- }
-
- if (options.drawGrid) {
- grid.visible = true;
- renderGrid();
- } else {
- grid.visible = false;
- }
-
- renderStars();
- renderFleets();
-
- scaleX = options.zoom;
- scaleY = options.zoom;
- scrollRect = new Rectangle(0, 0, screenSize.x / options.zoom,
- screenSize.y / options.zoom);
- }
-
- /**
- Returns all of the objects within [EPSILON] units of the given point.
- If there are no objects at the given point, then an empty array is
- returned.
-
- NOTE: The point specified isn't relative to any point such as the
- bounds given to the MapViewer when rendering. Instead it's a physical
- point _affected_ by zoom.
- **/
- public function getObjectsAtPoint(point : Vector, ?zoom = 1.0)
- : Array<IMapObject> {
- var objects = new Array<IMapObject>();
-
- for (obj in getStarsAtPoint(point, zoom)) objects.push(obj);
- for (obj in getFleetsAtPoint(point, zoom)) objects.push(obj);
- for (obj in getSalvageAtPoint(point, zoom)) objects.push(obj);
-
- return objects;
- }
-
- public function getAllObjects() : Array<IMapObject> {
- var objects = new Array<IMapObject>();
-
- for (obj in stars) objects.push(obj);
- for (obj in fleets) objects.push(obj);
- for (obj in salvage) objects.push(obj);
-
- return objects;
- }
-
- /**
- Returns all of the star objects within [EPSILON] units of the given
- point. If there are no stars at the given point, then an empty array is
- returned.
-
- NOTE: The point specified isn't relative to any point such as the
- bounds given to the MapViewer when rendering. Instead it's a physical
- point _affected_ by zoom.
- **/
- public function getStarsAtPoint(point : Vector, ?zoom = 1.0)
- : Array<StarObject> {
- var starObjects = new Array<StarObject>();
- for (obj in stars) {
- if (obj.star.location.getScale(zoom).distanceSquaredTo(point) <
- EPSILON_SQUARED) {
- starObjects.push(obj);
- }
- }
-
- return starObjects;
- }
-
- /**
- Returns all of the fleet objects within [EPSILON] units of the given
- point. If there are no fleets at the given point, then an empty array is
- returned.
-
- NOTE: The point specified isn't relative to any point such as the
- bounds given to the MapViewer when rendering. Instead it's a physical
- point _affected_ by zoom.
- **/
- public function getFleetsAtPoint(point : Vector, ?zoom = 1.0)
- : Array<FleetObject> {
- var fleetObjects = new Array<FleetObject>();
- for (obj in fleets) {
- if (obj.fleet.location.getScale(zoom).distanceSquaredTo(point) <
- EPSILON_SQUARED) {
- fleetObjects.push(obj);
- }
- }
-
- return fleetObjects;
- }
-
- /**
- Returns all of the salvage objects within [EPSILON] units of the given
- point. If there is no salvage at the given point, then an empty array
- is returned.
-
- NOTE: The point specified isn't relative to any point such as the
- bounds given to the MapViewer when rendering. Instead it's a physical
- point _affected_ by zoom.
- **/
- public function getSalvageAtPoint(point : Vector, ?zoom = 1.0)
- : Array<SalvageObject> {
- var salvageObjects = new Array<SalvageObject>();
- for (obj in salvage) {
- if (obj.salvage.location.getScale(zoom).distanceSquaredTo(point) <
- EPSILON_SQUARED) {
- salvageObjects.push(obj);
- }
- }
-
- return salvageObjects;
- }
-
- private inline function renderSelection(obj : IMapObject) {
- untyped obj.filters = if (Selection.isSelected(obj)) [SELECTION_GLOW]
- else [];
- }
-
- private inline function renderStars() {
- for (obj in stars) {
- if (!bounds.contains(obj.star.location.x, obj.star.location.y)) {
- obj.visible = false;
- continue;
- }
-
- obj.visible = true;
- obj.draw(bounds, pointOfView, options);
-
- renderSelection(obj);
- }
- }
-
- private inline function renderFleets() {
- for (obj in fleets) {
- if (!bounds.contains(obj.fleet.location.x, obj.fleet.location.y)) {
- obj.visible = false;
- continue;
- }
-
- obj.visible = true;
- obj.draw(bounds, pointOfView, options);
-
- renderSelection(obj);
- }
- }
-
- private inline function createBackground() {
- background.graphics.clear();
- background.graphics.beginFill(DEFAULT_BACKGROUND_COLOR);
- background.graphics.drawRect(0, 0, screenSize.x / options.zoom,
- screenSize.y / options.zoom);
- background.graphics.endFill();
- }
-
- private inline function renderGrid() {
- grid.graphics.clear();
- grid.graphics.lineStyle(0.25, GRID_COLOR, 0.1);
-
- var fixedScreenWidth = screenSize.x / options.zoom;
- var fixedScreenHeight = screenSize.y / options.zoom;
-
- for (i in 1...Math.ceil(fixedScreenWidth / GRID_SPACING)) {
- grid.graphics.moveTo(i * GRID_SPACING, 0);
- grid.graphics.lineTo(i * GRID_SPACING, fixedScreenHeight);
- }
-
- for (j in 1...Math.ceil(fixedScreenHeight / GRID_SPACING)) {
- grid.graphics.moveTo(0, j * GRID_SPACING);
- grid.graphics.lineTo(fixedScreenWidth, j * GRID_SPACING);
- }
- }
-
- private function renderScans(points : Array<ScanPoint>, normal : Bool) {
- var maskSprite = if (normal) normMaskSprite else penMaskSprite;
-
- var colorSprite = if (normal) normalScans else penScans;
- colorSprite.graphics.clear();
- colorSprite.graphics.beginFill(if (normal) NORMAL_SCAN_COLOR else
- PENETRATING_SCAN_COLOR);
- colorSprite.graphics.drawRect(0, 0, screenSize.x / options.zoom,
- screenSize.y / options.zoom);
- colorSprite.graphics.endFill();
-
- maskSprite.graphics.clear();
- maskSprite.graphics.lineStyle(0);
- for (point in points) {
- //if (!bounds.contains(point.location.x, point.location.y)) continue;
- maskSprite.graphics.beginFill(0xFFFFFF);
- maskSprite.graphics.drawCircle(point.location.x - bounds.x,
- point.location.y - bounds.y,
- point.radius);
- maskSprite.graphics.endFill();
- }
-
- colorSprite.mask = maskSprite;
- maskSprite.visible = false;
- }
-
- private function handleScanners() {
- //mostly a copy from [Scanning]
- //TODO: In [Scanning], instead of having 2 versions of the loop,
- //just use a closure.
-
- var penPoints = new Array<ScanPoint>();
- var normalPoints = new Array<ScanPoint>();
-
- //add star points
- var scanner = pointOfView.starScanner;
-
- if (scanner != null) {
- var nRadius = scanner.range;
- var pRadius = scanner.penetratingRange;
-
- var func =
- if (scanner.isPenetrating()) {
- function (location : Vector) {
- penPoints.push( {radius : pRadius,
- location : location.clone()} );
- normalPoints.push( {radius : nRadius,
- location : location.clone()} );
- }
- } else {
- function (location : Vector) {
- normalPoints.push( {radius : nRadius,
- location : location.clone()} );
- }
- };
-
- for (star in Global.stars) {
- if (star == null || star.owner.id != pointOfView.id ||
- star.hasScanner == null || !star.hasScanner /*||
- !bounds.contains(star.location.x, star.location.y)*/) {
- continue;
- }
-
- func(star.location);
- }
- }
-
- //add fleet points
- for (fleet in Global.fleets) {
- if (fleet.owner.id != pointOfView.id /*||
- !bounds.contains(fleet.location.x,
- fleet.location.y)*/) {
- continue;
- }
-
- var pRadius = fleet.getPenetratingScanningRange();
- var nRadius = fleet.getNormalScanningRange();
-
- if (pRadius > 0) {
- penPoints.push( {radius : pRadius,
- location : fleet.location.clone()} );
- }
- if (nRadius > 0) {
- normalPoints.push( {radius : pRadius,
- location : fleet.location.clone()} );
- }
- }
-
- renderScans(normalPoints, true);
- renderScans(penPoints, false);
- }
- }