Coverage Summary for Class: TileMapGraph (com.mygdx.game.AI)
| Class | Class, % | Method, % | Line, % |
|---|---|---|---|
| TileMapGraph | 0% (0/1) | 0% (0/12) | 0% (0/57) |
1 package com.mygdx.game.AI; 2 3 import com.badlogic.gdx.ai.pfa.Connection; 4 import com.badlogic.gdx.ai.pfa.indexed.IndexedGraph; 5 import com.badlogic.gdx.maps.MapLayer; 6 import com.badlogic.gdx.maps.MapLayers; 7 import com.badlogic.gdx.maps.tiled.TiledMap; 8 import com.badlogic.gdx.maps.tiled.TiledMapTileLayer; 9 import com.badlogic.gdx.math.Vector2; 10 import com.badlogic.gdx.utils.Array; 11 import com.badlogic.gdx.utils.ObjectMap; 12 13 import static com.mygdx.utils.TileMapCells.OBSTACLE; 14 import static com.mygdx.utils.TileMapCells.PASSABLE; 15 16 /** 17 * The Graphical representation of the tilemap with each cell being bidirectionally to the adjacent nodes. 18 */ 19 public class TileMapGraph implements IndexedGraph<Node> { 20 //private final NodeHeuristic heuristic; - commented out for Assessment 2 because heuristic functionality was removed due to redundancy 21 private final Array<Node> nodes; 22 private final Array<Path> paths; 23 private final Vector2 mapDim; 24 25 private final ObjectMap<Node, Array<Connection<Node>>> nodePaths; 26 27 private TileMapGraph() { 28 //heuristic = new NodeHeuristic(); - commented out for Assessment 2 because heuristic functionality was removed due to redundancy 29 nodes = new Array<>(); 30 paths = new Array<>(); 31 nodePaths = new ObjectMap<>(); 32 mapDim = new Vector2(); 33 } 34 35 /** 36 * Creates a Graph from the given tilemap 37 * @param map the source tilemap 38 */ 39 public TileMapGraph(TiledMap map) { 40 this(); 41 42 MapLayers layers = map.getLayers(); 43 TiledMapTileLayer layer = null; 44 45 // find the collision layer 46 for (MapLayer l : layers) { 47 if (l.getName().equals("Collision")) { 48 layer = (TiledMapTileLayer) l; 49 } 50 } 51 // if there is no collision layer 52 if (layer == null) { 53 return; 54 } 55 // the map dimensions 56 mapDim.set(layer.getWidth(), layer.getHeight()); 57 58 nodes.ensureCapacity((int) mapDim.x * (int) mapDim.y); 59 60 // create all the nodes 61 for (int i = 0; i < mapDim.x * mapDim.y; i++) { 62 nodes.add(new Node(0, 0)); 63 } 64 65 // for each column 66 for (int x = 0; x < layer.getWidth(); x++) { 67 // for each row 68 for (int y = 0; y < layer.getHeight(); y++) { 69 TiledMapTileLayer.Cell center = layer.getCell(x, y); 70 71 if (getType(center) == OBSTACLE) { 72 continue; 73 } 74 // the central node 75 addNode(x, y); 76 77 // all surrounding nodes 78 for (int i = -1; i < 2; i++) { 79 for (int j = -1; j < 2; j++) { 80 81 // prevents the node pathing to its self 82 if (i == 0 && j == 0) { 83 continue; 84 } 85 86 TiledMapTileLayer.Cell cell = layer.getCell(x + i, y + j); 87 // is cell outside the map 88 if (cell == null) { 89 continue; 90 } 91 92 // is the cell passable 93 if (cell.getTile().getId() == PASSABLE) { 94 95 addNode(x + i, y + j); 96 addPath(x, y, x + i, y + j); 97 } 98 } 99 } 100 } 101 } 102 } 103 104 /** 105 * Node a position (x, y) 106 * @param x co-ord 107 * @param y co-ord 108 * @return Node at (x, y) or null 109 */ 110 public Node getNode(float x, float y) { 111 Node n = nodes.get(getIndex(x, y)); 112 if (n.cost == -1) { 113 return null; 114 } 115 return n; 116 } 117 118 /** 119 * Find index of a position (x, y) 120 * @param x co-ord 121 * @param y co-ord 122 * @return the index of the parsed co-ordinate 123 */ 124 private int getIndex(float x, float y) { 125 return (int) (mapDim.x * y + x); 126 } 127 128 /** 129 * @return type of cell as far as the tile map is condensed 130 */ 131 private int getType(TiledMapTileLayer.Cell c) { 132 return c.getTile().getId(); 133 } 134 135 /** 136 * Find index of a position (x, y) 137 * @param x co-ord 138 * @param y co-ord 139 * @return the index of the parsed co-ordinate 140 */ 141 private int getIndex(int x, int y) { 142 return (int) mapDim.x * y + x; 143 } 144 145 /** 146 * adds Node unless node is already present 147 * @param x x pos 148 * @param y y pos 149 */ 150 private void addNode(float x, float y) { 151 Node n = nodes.get(getIndex((int) x, (int) y)); 152 if (n.cost > 0) { 153 return; 154 } 155 n.set(x, y); 156 n.cost = 1; 157 } 158 159 /** 160 * Adds path to map (doesn't check for duplicates) 161 * @param a src 162 * @param b dst 163 */ 164 private void addPath(Node a, Node b) { 165 Path path = new Path(a, b); 166 167 if (!nodePaths.containsKey(a)) { 168 nodePaths.put(a, new Array<>()); 169 } 170 nodePaths.get(a).add(path); 171 paths.add(path); 172 } 173 174 /** 175 * Adds path to map (doesn't check for duplicates) 176 * @param x1 src.x 177 * @param y1 src.y 178 * @param x2 dst.x 179 * @param y2 dst.y 180 */ 181 private void addPath(float x1, float y1, float x2, float y2) { 182 Node a = getNode(x1, y1); 183 Node b = getNode(x2, y2); 184 185 addPath(a, b); 186 } 187 188 /** 189 * @param node the node being queried 190 * @return the index of the parsed node 191 */ 192 @Override 193 public int getIndex(Node node) { 194 return getIndex(node.getPosition().x, node.getPosition().y); 195 } 196 197 /** 198 * @return the amount of nodes present in the map 199 */ 200 @Override 201 public int getNodeCount() { 202 return (int) (mapDim.x * mapDim.y); 203 } 204 205 /** 206 * @param fromNode the node being queried 207 * @return the list of connections present starting from the parsed node 208 */ 209 @Override 210 public Array<Connection<Node>> getConnections(Node fromNode) { 211 if (nodePaths.containsKey(fromNode)) { 212 return nodePaths.get(fromNode); 213 } 214 215 return new Array<>(); 216 } 217 218 //public GraphPath<Node> findPath(Node start, Node goal) { 219 // if (start == null || goal == null) { 220 // return null; 221 // } 222 // GraphPath<Node> path = new DefaultGraphPath<>(); 223 // new IndexedAStarPathFinder<>(this).searchNodePath(start, goal, heuristic, path); 224 // return path; 225 // } 226 227 //public QueueFIFO<Vector2> findOptimisedPath(Node a, Node b) { 228 // GraphPath<Node> path = findPath(a, b); 229 // QueueFIFO<Vector2> res = new QueueFIFO<>(); 230 // Vector2 delta = new Vector2(); 231 // float sequenceLength = 0; // the amount of times a 232 // Vector2 cur = new Vector2(); 233 // 234 // Vector2 prev = path.get(0).getPosition(); 235 // for (int i = 1; i < path.getCount(); i++) { 236 // Node n = path.get(i); 237 // cur.set(n.getPosition()); 238 // // d contains the current vector between the current pos and prev 239 // Vector2 d = cur.cpy(); 240 // d.sub(prev); 241 // 242 // 243 // if (delta.x == d.x && delta.y == d.y) { 244 // sequenceLength++; 245 // } else { 246 // res.add(delta.scl(sequenceLength)); 247 // delta = d; 248 // sequenceLength = 1; 249 // } 250 // prev.set(cur); 251 // } 252 // res.remove(0); 253 // res.add(delta.scl(sequenceLength)); 254 // return res; 255 // } 256 257 //public QueueFIFO<Vector2> findOptimisedPath(Vector2 a, Vector2 b) { 258 // Node n1 = getNode(a.x, a.y); 259 // Node n2 = getNode(b.x, b.y); 260 // return findOptimisedPath(n1, n2); 261 // } 262 263 //public QueueFIFO<Vector2> findOptimisedPath(float x1, float y1, float x2, float y2) { 264 // Node a = getNode(x1, y1); 265 // Node b = getNode(x2, y2); 266 // return findOptimisedPath(a, b); 267 // } 268 }