@Override public void render(Graphics g) { if (map.needsToBeRendered() || reRender) { Graphics g1 = cachedViewport.getGraphics(); // Draw a black background g1.setColor(Color.BLACK); g1.fillRect(0, 0, viewportWidth, viewportHeight); // Get the avatar's location. This location will be shown in the center of the viewport. Point logicalPoint = avatar.getLocation(); Point pixelPoint = new Point(viewportWidth / 2, viewportHeight / 2); // Create a 2D graphcis obj Graphics2D g2 = (Graphics2D) g1.create(); // Clear the existing status bar locations this.entityLocationTuples.clear(); breadthFirstRender(logicalPoint, pixelPoint, g2); map.setNeedsToBeRendered(false); reRender = false; g1.dispose(); } // draws the viewport g.drawImage(cachedViewport, 0, 0, viewportWidth, viewportHeight, getDisplay()); for (EntityLocationTuple et : this.entityLocationTuples) { drawEntityHealthBar(g, et); } if (displayDebugInformation) { g.setColor(Color.WHITE); g.drawString( avatar.getLocation().toString(), viewportWidth - g.getFontMetrics().stringWidth(avatar.getLocation().toString()) - 50, 25); } }
// This will be used in the BF traversal to get the list of adjacent tiles. private ArrayList<TileNode> getAdjacentTiles(TileNode tile) { ArrayList<TileNode> adjacentTiles = new ArrayList<>(); // Get the tile adjacent to the north. Point northLogicalPoint = new Point(tile.logicalPoint); // Get the tiles logical point northLogicalPoint.translate(0, -1); Point northPixelPoint = new Point(tile.pixelPoint); // Get the tiles pixel point; northPixelPoint.translate(0, -vertDistanceBtwnTiles); Tile northTile = map.getTileAt(northLogicalPoint); if (northTile != null) { adjacentTiles.add(new TileNode(northTile, northLogicalPoint, northPixelPoint)); } // Get the tile to the south of the current position. Point southLogicalPoint = new Point(tile.logicalPoint); southLogicalPoint.translate(0, 1); Point southPixelPoint = new Point(tile.pixelPoint); southPixelPoint.translate(0, vertDistanceBtwnTiles); Tile southTile = map.getTileAt(southLogicalPoint); if (southTile != null) { adjacentTiles.add(new TileNode(southTile, southLogicalPoint, southPixelPoint)); } // Get the tile to the north west of the current position. Point northWestLogicalPoint = new Point(tile.logicalPoint); northWestLogicalPoint.translate(-1, 0); Point northWestPixelPoint = new Point(tile.pixelPoint); northWestPixelPoint.translate(-horizDistanceBtwnTiles, -vertDistanceBtwnTiles / 2); Tile northWestTile = map.getTileAt(northWestLogicalPoint); if (northWestTile != null) { adjacentTiles.add(new TileNode(northWestTile, northWestLogicalPoint, northWestPixelPoint)); } // Get the tile to the south east of the current position. Point southEastLogicalPoint = new Point(tile.logicalPoint); southEastLogicalPoint.translate(1, 0); Point southEastPixelPoint = new Point(tile.pixelPoint); southEastPixelPoint.translate(horizDistanceBtwnTiles, vertDistanceBtwnTiles / 2); Tile southEastTile = map.getTileAt(southEastLogicalPoint); if (southEastTile != null) { adjacentTiles.add(new TileNode(southEastTile, southEastLogicalPoint, southEastPixelPoint)); } // Get the tile to the north east of the current position. Point northEastLogicaPoint = new Point(tile.logicalPoint); northEastLogicaPoint.translate(1, -1); Point northEastPixelPoint = new Point(tile.pixelPoint); northEastPixelPoint.translate(horizDistanceBtwnTiles, -vertDistanceBtwnTiles / 2); Tile northEastTile = map.getTileAt(northEastLogicaPoint); if (northEastTile != null) { adjacentTiles.add(new TileNode(northEastTile, northEastLogicaPoint, northEastPixelPoint)); } // Get the tile to the south west of the current position. Point southWestLogicalPoint = new Point(tile.logicalPoint); southWestLogicalPoint.translate(-1, 1); Point southWestPixelPoint = new Point(tile.pixelPoint); southWestPixelPoint.translate(-horizDistanceBtwnTiles, vertDistanceBtwnTiles / 2); Tile southWestTile = map.getTileAt(southWestLogicalPoint); if (southWestTile != null) { adjacentTiles.add(new TileNode(southWestTile, southWestLogicalPoint, southWestPixelPoint)); } return adjacentTiles; }
// This will traverse through all the tiles using a breadth first search. It will then render that // tile. private void breadthFirstRender(Point logicalPoint, Point pixelPoint, Graphics2D g) { // Get the radius of visibliity. int radiusOfVisibility = avatar.getRadiusOfVisiblility(); // This hashmap will keep track of what we have already renderred in our traversal. HashMap<Point, Boolean> hasBeenRendered = new HashMap<>(); // Create an empty queue of tile nodes. Queue<TileNode> tileQueue = new LinkedList<>(); // Convert the first tile into a TileNode and push it into the queue. TileNode root = new TileNode(map.getTileAt(logicalPoint), logicalPoint, pixelPoint); root.distanceFromAvatar = 0; // Offset the root based upon the offset ammound root.pixelPoint.translate((int) viewportOffset.getX(), (int) viewportOffset.getY()); tileQueue.offer(root); // offer is analogous to push (or enqueue). while (!tileQueue.isEmpty()) { // Pop the current tile off the queue. TileNode currentTileNode = tileQueue.poll(); // poll is analogous to pop (or dequeue). // Check to see if the tile has already been renderred. if ((hasBeenRendered.get(currentTileNode.logicalPoint) == null) || !hasBeenRendered.get(currentTileNode.logicalPoint) && isInRangeOfViewport(currentTileNode.pixelPoint)) { hasBeenRendered.put( currentTileNode.logicalPoint, true); // Mark the tile as having been renderred. // Render the current Tile if (!displayDebugInformation) { if (currentTileNode.distanceFromAvatar < radiusOfVisibility) { // Mark this tile as having been seen. seenTiles.put(new Point(currentTileNode.logicalPoint), new Tile(currentTileNode.tile)); // Set the opacity based on the distance from the avatar. float opacity = 1.0f - (1 - MIN_OPACITY) * (currentTileNode.distanceFromAvatar / (float) radiusOfVisibility); opacity = opacity < MIN_OPACITY ? MIN_OPACITY : opacity; renderTile(currentTileNode, g, opacity); // Render the tile. } else if (seenTiles.get(currentTileNode.logicalPoint) != null) { currentTileNode.tile = seenTiles.get( currentTileNode.logicalPoint); // Switch out the actual tile with the seen tile. renderTile(currentTileNode, g, SEEN_OPACITY); } } else { // Yes, Austin put this in. You can tell by the spacing. renderTile(currentTileNode, g, 1f); } // Push all the adjacent nodes onto the queue for (TileNode tileNode : getAdjacentTiles(currentTileNode)) { tileNode.distanceFromAvatar = currentTileNode.distanceFromAvatar + 1; tileQueue.offer(tileNode); } } } }