package main; import java.io.BufferedReader; import java.io.FileNotFoundException; import utils.Utils; import java.util.HashMap; import java.io.IOException; import java.io.Writer; import java.io.PrintWriter; import java.io.FileWriter; import java.util.Iterator; import java.awt.Graphics; import java.util.Collection; import java.awt.Point; import java.awt.Color; import java.util.TreeSet; import java.util.LinkedList; import astar.AStarMap; public class Map { private Location[][] grid; public AStarMap asMap; public LinkedList creatureList; TreeSet creatures; TreeSet tiles; TreeSet items; int xLow; int xHigh; int yLow; int yHigh; static int count; public String message; public boolean valid; public int startX; public int startY; private static Color redHaze; static { Map.count = 0; Map.redHaze = new Color(255, 0, 0, 100); } public Map(final int x, final int y) { this.grid = new Location[x][y]; this.asMap = new AStarMap(x, y); this.creatureList = new LinkedList(); this.creatures = new TreeSet(); this.tiles = new TreeSet(); this.items = new TreeSet(); this.xLow = 0; this.xHigh = 0; this.yLow = 0; this.yHigh = 0; this.startX = 400; this.startY = 300; this.initBounds(); for (int i = 0; i < this.getWidth(); ++i) { for (int j = 0; j < this.getHeight(); ++j) { this.grid[i][j] = new Location(null); } } this.valid = true; } public Map(final int x, final int y, final Tile defaultTile) { this(x, y); for (int i = 0; i < this.getWidth(); ++i) { for (int j = 0; j < this.getHeight(); ++j) { this.setGround(i, j, new Tile(defaultTile, i * 40, j * 40, 0)); } } this.message = "New map created successfully"; } public Map(final int x, final int y, final Tile defaultTile, final Tile guidelineTile) { this(x, y); for (int i = 0; i < this.getWidth(); ++i) { for (int j = 0; j < this.getHeight(); ++j) { this.setGround(i, j, new Tile(defaultTile, i * 40, j * 40, 0)); } } for (int i = 19; i < this.getWidth(); i += 20) { for (int j = 14; j < this.getHeight(); j += 15) { for (int a = 0; a < 20; ++a) { this.setGround(i - a, j - 14, new Tile(guidelineTile, (i - a) * 40, (j - 14) * 40, 0)); this.setGround(i - a, j, new Tile(guidelineTile, (i - a) * 40, j * 40, 0)); } for (int b = 1; b < 14; ++b) { this.setGround(i - 19, j - b, new Tile(guidelineTile, (i - 19) * 40, (j - b) * 40, 0)); this.setGround(i, j - b, new Tile(guidelineTile, i * 40, (j - b) * 40, 0)); } } } this.message = "New map created successfully"; } public void initBounds() { this.xLow = this.startX / 40 - 12; this.xHigh = this.xLow + 24; this.yLow = this.startY / 40 - 10; this.yHigh = this.yLow + 20; if (this.xLow < 0) { this.xLow = 0; } if (this.xHigh > this.getWidth() - 1) { this.xHigh = this.getWidth() - 1; } if (this.yLow < 0) { this.yLow = 0; } if (this.yHigh > this.getHeight() - 1) { this.yHigh = this.getHeight() - 1; } } public Location getLoc(final int x, final int y) { return this.grid[x][y]; } public void setBounds(final int x1, final int x2, final int y1, final int y2) { this.xLow = x1; this.xHigh = x2; this.yLow = y1; this.yHigh = y2; } public int getWidth() { return this.grid.length; } public int getHeight() { if (this.grid.length > 0) { return this.grid[0].length; } return 0; } public LinkedList getObjectsInVicinity(final Point p, final int xDist, final int yDist) { int lowX = p.x / 40 - xDist; int highX = p.x / 40 + xDist; int lowY = p.y / 40 - yDist; int highY = p.y / 40 + yDist; final LinkedList list = new LinkedList(); if (lowX < 0) { lowX = 0; } if (highX > this.getWidth() - 1) { highX = this.getWidth() - 1; } if (lowY < 0) { lowY = 0; } if (highY > this.getHeight() - 1) { highY = this.getHeight() - 1; } for (int x = lowX; x <= highX; ++x) { for (int y = lowY; y <= highY; ++y) { list.addAll(this.getLoc(x, y).getCreatures()); list.addAll(this.getLoc(x, y).getObjects()); list.add(this.getLoc(x, y).getGround()); } } return list; } public LinkedList getCreaturesInVicinity(final Point p, final int xDist, final int yDist) { int lowX = p.x / 40 - xDist; int highX = p.x / 40 + xDist; int lowY = p.y / 40 - yDist; int highY = p.y / 40 + yDist; final LinkedList list = new LinkedList(); if (lowX < 0) { lowX = 0; } if (highX > this.getWidth() - 1) { highX = this.getWidth() - 1; } if (lowY < 0) { lowY = 0; } if (highY > this.getHeight() - 1) { highY = this.getHeight() - 1; } for (int x = lowX; x <= highX; ++x) { for (int y = lowY; y <= highY; ++y) { list.addAll(this.getLoc(x, y).getCreatures()); } } return list; } public void setGround(final int x, final int y, final Tile o) { if (this.xLow <= x && x <= this.xHigh && this.yLow <= y && y <= this.yHigh) { if (this.getLoc(x, y).getGround() != null) { this.tiles.remove(this.getLoc(x, y).getGround()); } if (this.getLoc(x, y).getBase() != null) { this.tiles.remove(this.getLoc(x, y).getBase()); } this.getLoc(x, y).setGround(o); this.tiles.add(this.getLoc(x, y).getGround()); if (this.getLoc(x, y).getBase() != null) { this.tiles.add(this.getLoc(x, y).getBase()); } } else { this.getLoc(x, y).setGround(o); } this.asMap.addObstacle(o); } public void addCreature(final int x, final int y, final Creature o) { if (this.xLow <= x && x <= this.xHigh && this.yLow <= y && y <= this.yHigh) { this.creatures.add(o); } this.creatureList.add(o); this.getLoc(x, y).addCreature(o); } public void removeCreature(final int x, final int y, final Creature o) { if (this.xLow <= x && x <= this.xHigh && this.yLow <= y && y <= this.yHigh) { this.creatures.remove(o); } this.creatureList.remove(o); this.getLoc(x, y).getCreatures().remove(o); } public void addObject(final int x, final int y, final Tile o) { if (this.xLow <= x && x <= this.xHigh && this.yLow <= y && y <= this.yHigh) { this.tiles.add(o); } this.getLoc(x, y).addObject(o); this.asMap.addObstacle(o); } public void removeObject(final int x, final int y, final Tile o) { if (this.xLow <= x && x <= this.xHigh && this.yLow <= y && y <= this.yHigh) { this.tiles.remove(o); } this.getLoc(x, y).getObjects().remove(o); } public void addItem(final int x, final int y, final Item o) { if (this.xLow <= x && x <= this.xHigh && this.yLow <= y && y <= this.yHigh) { this.items.add(o); } this.getLoc(x, y).addItem(o); } public void removeItem(final int x, final int y, final Item o) { if (this.xLow <= x && x <= this.xHigh && this.yLow <= y && y <= this.yHigh) { this.items.remove(o); } this.getLoc(x, y).getItems().remove(o); } private void addObjectsAt(final int x, final int y) { this.creatures.addAll(this.getLoc(x, y).getCreatures()); this.items.addAll(this.getLoc(x, y).getItems()); this.tiles.addAll(this.getLoc(x, y).getObjects()); this.tiles.add(this.getLoc(x, y).getGround()); if (this.getLoc(x, y).getBase() != null) { this.tiles.add(this.getLoc(x, y).getBase()); } } private void removeObjectsAt(final int x, final int y) { this.creatures.removeAll(this.getLoc(x, y).getCreatures()); this.items.removeAll(this.getLoc(x, y).getItems()); this.tiles.removeAll(this.getLoc(x, y).getObjects()); this.tiles.remove(this.getLoc(x, y).getGround()); if (this.getLoc(x, y).getBase() != null) { this.tiles.remove(this.getLoc(x, y).getBase()); } } private void addColAt(final int x, final int yLower, final int yUpper) { for (int i = yLower; i <= yUpper; ++i) { this.addObjectsAt(x, i); } } private void removeColAt(final int x, final int yLower, final int yUpper) { for (int i = yLower; i <= yUpper; ++i) { this.removeObjectsAt(x, i); } } private void addRowAt(final int y, final int xLower, final int xUpper) { for (int i = xLower; i <= xUpper; ++i) { this.addObjectsAt(i, y); } } private void removeRowAt(final int y, final int xLower, final int xUpper) { for (int i = xLower; i <= xUpper; ++i) { this.removeObjectsAt(i, y); } } private void updateBounds(final int xLow_new, final int xHigh_new, final int yLow_new, final int yHigh_new) { if (xLow_new < this.xLow) { for (int x = xLow_new; x < this.xLow; ++x) { this.addColAt(x, yLow_new, yHigh_new); } } else { for (int x = this.xLow; x < xLow_new; ++x) { this.removeColAt(x, this.yLow, this.yHigh); } } if (xHigh_new > this.xHigh) { for (int x = xHigh_new; x > this.xHigh; --x) { this.addColAt(x, yLow_new, yHigh_new); } } else { for (int x = this.xHigh; x > xHigh_new; --x) { this.removeColAt(x, this.yLow, this.yHigh); } } if (yLow_new < this.yLow) { for (int y = yLow_new; y < this.yLow; ++y) { this.addRowAt(y, xLow_new, xHigh_new); } } else { for (int y = this.yLow; y < yLow_new; ++y) { this.removeRowAt(y, this.xLow, this.xHigh); } } if (yHigh_new > this.yHigh) { for (int y = yHigh_new; y > this.yHigh; --y) { this.addRowAt(y, xLow_new, xHigh_new); } } else { for (int y = this.yHigh; y > yHigh_new; --y) { this.removeRowAt(y, this.xLow, this.xHigh); } } this.xLow = xLow_new; this.xHigh = xHigh_new; this.yLow = yLow_new; this.yHigh = yHigh_new; } public void draw(final Graphics g, final Point p, final boolean bounds, final boolean passable) { int xLow_new = p.x / 40 - 12; int xHigh_new = xLow_new + 24; int yLow_new = p.y / 40 - 10; int yHigh_new = yLow_new + 20; if (xLow_new < 0) { xLow_new = 0; } if (xHigh_new > this.getWidth() - 1) { xHigh_new = this.getWidth() - 1; } if (yLow_new < 0) { yLow_new = 0; } if (yHigh_new > this.getHeight() - 1) { yHigh_new = this.getHeight() - 1; } this.updateBounds(xLow_new, xHigh_new, yLow_new, yHigh_new); final TreeSet tmp = new TreeSet(this.tiles); tmp.addAll(this.creatures); tmp.addAll(this.items); for (final MapObject cur : tmp) { if (cur.z == 0 || !passable) { cur.draw(g, 400 - p.x, 300 - p.y); } } if (bounds) { final Iterator iter = tmp.iterator(); g.setColor(Color.red); while (iter.hasNext()) { final MapObject obj = iter.next(); if (obj.getBound() != null) { obj.getBound().draw(g, 400 - p.x, 300 - p.y, obj); } if (obj.getSelectionBound() != null) { obj.getSelectionBound().draw(g, 400 - p.x, 300 - p.y, obj); } } } if (passable) { g.setColor(Map.redHaze); for (int x = this.xLow; x <= this.xHigh; ++x) { for (int y = this.yLow; y <= this.yHigh; ++y) { this.asMap.map[x][y].drawBlocked(g, 400 - p.x, 300 - p.y); this.asMap.map[x][y].draw(g, 400 - p.x, 300 - p.y, false); } } } } public boolean save(final String fileName) { String strObjects = ""; final TreeSet objSet = new TreeSet(); try { final PrintWriter out = new PrintWriter(new FileWriter("maps/" + fileName)); out.println(String.valueOf(this.getWidth()) + "x" + this.getHeight()); for (int x = 0; x < this.getWidth(); ++x) { String strTiles = ""; for (int y = 0; y < this.getHeight(); ++y) { final Location loc = this.getLoc(x, y); if (loc.getBase() != null) { strTiles = String.valueOf(strTiles) + loc.getBase().getImg().getKey() + loc.getBase().z + "|"; } strTiles = String.valueOf(strTiles) + loc.getGround().getImg().getKey() + loc.getGround().z + ","; objSet.addAll(loc.getObjects()); } out.println(strTiles.substring(0, strTiles.length() - 1)); } for (final Tile curObj : objSet) { strObjects = String.valueOf(strObjects) + curObj.loc.x + "," + curObj.loc.y + "," + curObj.getImg().getKey() + "," + curObj.z + ";"; } if (strObjects.length() == 0) { out.println(); } else { out.println(strObjects.substring(0, strObjects.length() - 1)); } final Iterator iter2 = this.creatureList.iterator(); strObjects = ""; while (iter2.hasNext()) { final Creature curCr = iter2.next(); strObjects = String.valueOf(strObjects) + curCr.loc.x + "," + curCr.loc.y + "," + curCr.id + ";"; } if (strObjects.length() == 0) { out.println(); } else { out.println(strObjects.substring(0, strObjects.length() - 1)); } out.close(); } catch (IOException ioe) { this.message = "There was a problem saving the map"; ioe.printStackTrace(); return false; } this.message = "The map has been saved successfully"; return true; } public static Map load(final String fileName, final Map baseMap, final HashMap imageMap, final HashMap crMap) { Map map = null; try { final BufferedReader in = Utils.loadTextFile("maps/" + fileName); final String sizeStr = in.readLine(); final String xSize = sizeStr.substring(0, sizeStr.indexOf("x")); final String ySize = sizeStr.substring(sizeStr.indexOf("x") + 1); map = new Map(Integer.parseInt(xSize), Integer.parseInt(ySize)); if (baseMap == null) { map.initBounds(); } else { map.setBounds(baseMap.xLow, baseMap.xHigh, baseMap.yLow, baseMap.yHigh); } for (int x = 0; x < map.getWidth(); ++x) { String row = in.readLine(); for (int y = 0; y < map.getHeight(); ++y) { String loc; if (row.indexOf(",") == -1) { loc = row; } else { loc = row.substring(0, row.indexOf(",")); row = row.substring(row.indexOf(",") + 1); } int ground; int groundZ; if (loc.indexOf("|") == -1) { ground = Integer.parseInt(loc) / 10; groundZ = Integer.parseInt(loc) % 10; } else { final int base = Integer.parseInt(loc.substring(0, loc.indexOf("|"))) / 10; final int baseZ = Integer.parseInt(loc.substring(0, loc.indexOf("|"))) % 10; ground = Integer.parseInt(loc.substring(loc.indexOf("|") + 1)) / 10; groundZ = Integer.parseInt(loc.substring(loc.indexOf("|") + 1)) % 10; map.setGround(x, y, new Tile(imageMap.get(base), x * 40, y * 40, baseZ)); } map.setGround(x, y, new Tile(imageMap.get(ground), x * 40, y * 40, groundZ)); } } String objects = in.readLine(); while (!objects.equals("")) { String obj; if (objects.indexOf(";") == -1) { obj = objects; objects = ""; } else { obj = objects.substring(0, objects.indexOf(";")); objects = objects.substring(objects.indexOf(";") + 1); } final int x2 = Integer.parseInt(obj.substring(0, obj.indexOf(","))); obj = obj.substring(obj.indexOf(",") + 1); final int y2 = Integer.parseInt(obj.substring(0, obj.indexOf(","))); obj = obj.substring(obj.indexOf(",") + 1); final int key = Integer.parseInt(obj.substring(0, obj.indexOf(","))); final int z = Integer.parseInt(obj.substring(obj.indexOf(",") + 1)); map.addObject(x2 / 40, y2 / 40, new Tile(imageMap.get(key), x2, y2, z)); } String creatures = in.readLine(); while (!creatures.equals("")) { String cr; if (creatures.indexOf(";") == -1) { cr = creatures; creatures = ""; } else { cr = creatures.substring(0, creatures.indexOf(";")); creatures = creatures.substring(creatures.indexOf(";") + 1); } final int x3 = Integer.parseInt(cr.substring(0, cr.indexOf(","))); cr = cr.substring(cr.indexOf(",") + 1); final int y3 = Integer.parseInt(cr.substring(0, cr.indexOf(","))); final int id = Integer.parseInt(cr.substring(cr.indexOf(",") + 1)); map.addCreature(x3 / 40, y3 / 40, crMap.get(id).copy(new Point(x3, y3))); } in.close(); map.asMap.coalesceQuadTrees(); map.asMap.generateAllNeighbors(); } catch (FileNotFoundException fnfe) { if (map == null) { map = new Map(0, 0); } map.message = "That saved game file does not exists"; map.valid = false; return map; } catch (IOException ioe) { if (map == null) { map = new Map(0, 0); } map.message = "There was a problem loading the map"; ioe.printStackTrace(); map.valid = false; return map; } map.message = "The map has been loaded successfully"; map.valid = true; return map; } }