package com.lucasdnd.ags.map; import java.util.ArrayList; import org.newdawn.slick.GameContainer; import org.newdawn.slick.Graphics; import org.newdawn.slick.SlickException; import org.newdawn.slick.state.StateBasedGame; import org.newdawn.slick.tiled.TiledMap; import org.newdawn.slick.util.pathfinding.AStarPathFinder; import org.newdawn.slick.util.pathfinding.PathFindingContext; import org.newdawn.slick.util.pathfinding.TileBasedMap; import com.lucasdnd.ags.gameplay.Asset; import com.lucasdnd.ags.gameplay.Business; import com.lucasdnd.ags.gameplay.Character; import com.lucasdnd.ags.gameplay.Console; import com.lucasdnd.ags.gameplay.Entity; import com.lucasdnd.ags.gameplay.Misc; import com.lucasdnd.ags.gameplay.Shelf; import com.lucasdnd.ags.gameplay.Table; import com.lucasdnd.ags.gameplay.Tv; import com.lucasdnd.ags.map.terrain.Floor; import com.lucasdnd.ags.map.terrain.Terrain; import com.lucasdnd.ags.map.terrain.Wall; import com.lucasdnd.ags.system.MainState; /** * A TiledMap subclass to extend its functionality, adding a better data structure to manage the maps. * @author tulio * */ public class Map extends TiledMap implements TileBasedMap { private boolean[][] blocked; // Blocked contain an object blocking it or are located outside the store private boolean[][] playable; // Playable are available for the player to buy/use // Layers public static final int FLOOR = 0; public static final int LINES = 1; private GameTile[][] gameTiles; // The Tile Grid that goes on top of the terrain layer private float xOffset; // Map X Offset private float yOffset; // Map Y Offset private int previousXTileAtMouse = -1; // The Tile x that was previously on the player's mouse private int previousYTileAtMouse = -1; // The Tile y that was previously on the player's mouse private int xTileAtMouse; // User's current mouse over private int yTileAtMouse; // User's current mouse over private final int tileWidth = 32; // Tiles dimensions (size of the Tiles, not size of the Map). private final int tileHeight = 16; // It is this way so other objects can use the x/y Position calculations private ArrayList<Wall> walls; private ArrayList<Floor> floors; private Tile spawnPoint; // The spawning Tile private AStarPathFinder pathFinder; /** * Creates the map. Reads from Tiled and sets an offset according to the camera * @param ref * @param tileSetsLocation * @param xOffset * @param yOffset * @throws SlickException */ public Map(String ref, String tileSetsLocation, int xOffset, int yOffset) throws SlickException { // Starts the base Map super(ref, tileSetsLocation); // Defines the X and Y render positions this.xOffset = xOffset; this.yOffset = yOffset; // Creates the Blocked and Playable Tiles blocked = new boolean[getWidth()][getHeight()]; playable = new boolean[getWidth()][getHeight()]; walls = new ArrayList<Wall>(); floors = new ArrayList<Floor>(); // Creates the Game Tiles gameTiles = new GameTile[getWidth()][getHeight()]; // Spawn point spawnPoint = new Tile(13, 13); // These attributes store the tiles the user is pointing at xTileAtMouse = 0; yTileAtMouse = 0; // PathFinding pathFinder = new AStarPathFinder(this, super.getWidth() * super.getHeight(), false); // This will create the map, unblock/block the Tiles and set the polygon Shapes for every Tile for (int xTile = 0; xTile < getWidth(); xTile++) { for(int yTile = 0; yTile < getHeight(); yTile++) { // Read the Tilemap File for Playable Tiles String playableValue = getTileProperty(getTileId(xTile, yTile, FLOOR), "playable", "false"); playable[xTile][yTile] = playableValue.equals("true"); // Blocked? blocked[xTile][yTile] = !playable[xTile][yTile]; // Defines the xi and yi relative positions of each polygon float tileXPos = (tileWidth / 2 * xTile) - (tileWidth / 2 * yTile); float tileYPos = (tileHeight / 2 * xTile) + (tileHeight / 2 * yTile); // Math to form the polygon gameTiles[xTile][yTile] = new GameTile( // Isometric rendering tileXPos, tileYPos + tileHeight / 2, // x0, y0 tileXPos + tileWidth / 2, tileYPos, // x1, y1 tileXPos + tileWidth, tileYPos + tileHeight / 2, // x2, y2 tileXPos + tileWidth / 2, tileYPos + tileHeight); // x3, y3 } } // Generate the Map walls and floor updateMapLimits(); } /** * Called at every update. Updates the Camera Offset and the highlighted tiles according to mouse over. * @param container * @param game * @param delta * @param mouseX * @param mouseY * @throws SlickException */ public void update(int delta, int currentMode, Asset placingAsset, int mouseX, int mouseY, ArrayList<Table> tables, boolean leftMouseClicked, boolean leftMouseDown, Business business) throws SlickException { // Updates the Tiles Layer for(int i = 0; i < getWidth(); i++) { for(int j = 0; j < getHeight(); j++) { // 1. Update the Offset of the Tiles according to the camera offset gameTiles[i][j].setxOffset(xOffset); gameTiles[i][j].setyOffset(yOffset); // 2. Update the Tiles. This will highlight the Tiles the player has the mouse over gameTiles[i][j].update(delta, mouseX, mouseY); // 3. Let the Map know which Tile it is if(gameTiles[i][j].isMouseOver()) { xTileAtMouse = i; yTileAtMouse = j; } } } // Update the position of the Walls for (Wall w : walls) { this.snapToGrid(w); } // If the player changed the Mouse Over tile, unhighlight all of them if(previousXTileAtMouse != xTileAtMouse || previousYTileAtMouse != yTileAtMouse) { unhighlightAll(); } /* If the player is trying to place an object on the Map, other tiles should also be highlighted. / Here, we check for this situation and apply the highlights accordingly. */ if((currentMode == MainState.BUYING_ASSET || currentMode == MainState.MOVING_ASSET) && placingAsset != null) { // At first the placement is valid. Down through the method we're going to set it to false if it runs off // the map or if there's another asset below it. placingAsset.setValidPlacement(true); // The x and y Tiles to Highlight are the amount of Tiles that will be Highlighted in each Axis. int xTilesToHighlight; int yTilesToHighlight; /* Since we don't know where to begin and end the Loops that will go through the soon-to-be Highlighted Tiles, * we need to calculate them beforehand. */ int startingXLoop = 0; int endingXLoop = 0; int startingYLoop = 0; int endingYLoop = 0; // 1. First, we adjust the highlighting according to the facingDirection of the Asset // Here, we apply the sizes in the right direction and set the axis corrections if (placingAsset.getFacingDirection() == Entity.DOWN_RIGHT) { xTilesToHighlight = placingAsset.getxSize(); yTilesToHighlight = placingAsset.getySize(); startingXLoop = 0; endingXLoop = xTilesToHighlight; startingYLoop = 0; endingYLoop = yTilesToHighlight; } else if(placingAsset.getFacingDirection() == Entity.DOWN_LEFT) { xTilesToHighlight = -1 * placingAsset.getySize() + 1; yTilesToHighlight = placingAsset.getxSize(); startingXLoop = xTilesToHighlight; endingXLoop = 0; startingYLoop = 0; endingYLoop = yTilesToHighlight; } else if(placingAsset.getFacingDirection() == Entity.UP_LEFT) { xTilesToHighlight = -1 * placingAsset.getxSize() + 1; yTilesToHighlight = -1 * placingAsset.getySize() + 1; startingXLoop = xTilesToHighlight; endingXLoop = 0; startingYLoop = yTilesToHighlight; endingYLoop = 0; // Workaround to 1x1 objects. Without this, no tiles are highlighted if(xTilesToHighlight == 0) { startingXLoop = 0; endingXLoop = 1; } if(yTilesToHighlight == 0) { startingYLoop = 0; endingYLoop = 1; } } else {//placingMarketAsset.getFacingDirection() == Entity.UP_RIGHT) { xTilesToHighlight = placingAsset.getySize(); yTilesToHighlight = -1 * placingAsset.getxSize() + 1; startingXLoop = 0; endingXLoop = xTilesToHighlight; startingYLoop = yTilesToHighlight; endingYLoop = 0; } // 2. Here we prevent invalid highlighting (highlighting tiles that don't exist on the map (< 0 or > size) if(endingXLoop + xTileAtMouse > getWidthInTiles()) { endingXLoop -= ((xTileAtMouse + xTilesToHighlight) - getWidthInTiles()); placingAsset.setValidPlacement(false); } if(endingYLoop + yTileAtMouse > getHeightInTiles()) { endingYLoop -= ((yTileAtMouse + yTilesToHighlight) - getHeightInTiles()); placingAsset.setValidPlacement(false); } if(xTileAtMouse + startingXLoop < 0) { startingXLoop -= xTilesToHighlight + xTileAtMouse; placingAsset.setValidPlacement(false); } if(yTileAtMouse + startingYLoop < 0) { startingYLoop -= yTilesToHighlight + yTileAtMouse; placingAsset.setValidPlacement(false); } // 3. We check if the Highlighted tiles are intersecting with other solid Entities on the map // or if they're getting outside the playable area // First on the x axis for(int i = startingXLoop; i < endingXLoop; i++) { if(isBlocked(xTileAtMouse + i, yTileAtMouse) || !isPlayable(xTileAtMouse + i, yTileAtMouse)) { placingAsset.setValidPlacement(false); } } // Then on the y axis for(int j = startingYLoop; j < endingYLoop; j++) { if(isBlocked(xTileAtMouse, yTileAtMouse + j) || !isPlayable(xTileAtMouse, yTileAtMouse + j)) { placingAsset.setValidPlacement(false); } } // Lastly in the intersection of the two for(int i = startingXLoop; i < endingXLoop; i++) { for(int j = startingYLoop; j < endingYLoop; j++) { if(isBlocked(xTileAtMouse + i, yTileAtMouse + j) || !isPlayable(xTileAtMouse + i, yTileAtMouse + j)) { placingAsset.setValidPlacement(false); } } } // 4. We loop through those tiles that need highlighting and highlight them // First on the x axis for(int i = startingXLoop; i < endingXLoop; i++) { gameTiles[xTileAtMouse + i][yTileAtMouse].setHighlighted(true); } // Then on the y axis for(int j = startingYLoop; j < endingYLoop; j++) { gameTiles[xTileAtMouse][yTileAtMouse + j].setHighlighted(true); } // Lastly in the intersection of the two for(int i = startingXLoop; i < endingXLoop; i++) { for(int j = startingYLoop; j < endingYLoop; j++) { gameTiles[xTileAtMouse + i][yTileAtMouse + j].setHighlighted(true); } } // 5. In an special case, when the user is trying to place a Tv or a Console, mouse overing // a Table should not result in an Invalid Placement if(placingAsset instanceof Tv || placingAsset instanceof Console) { // Check if the placement has been market as Invalid if(!placingAsset.isValidPlacement()) { // Finally check if the Object below the Mouse is a Table for(Table t : tables) { if(t.tilesGotMouseOvered(xTileAtMouse, yTileAtMouse)) { placingAsset.setValidPlacement(true); } } } } } // Set the previous Tile x and y at Mouse previousXTileAtMouse = xTileAtMouse; previousYTileAtMouse = yTileAtMouse; } /** * Buying a map area (can't buy the borders of the map) * @throws SlickException */ public void buyTile(Business business) throws SlickException { if (xTileAtMouse != 0 && yTileAtMouse != 0 && xTileAtMouse != this.getWidth() -1 && yTileAtMouse != this.getHeight() -1 && playable[xTileAtMouse][yTileAtMouse] == false) { // Haz the money? if (business.getMoney() >= business.getTilePrice()) { business.makeBusiness(-business.getTilePrice(), Business.BUYING_MAP, true); playable[xTileAtMouse][yTileAtMouse] = true; updateMapLimits(); } } } /** * Renders each layer of the Map according to the Camera Offset * @param container * @param game * @param g * @throws SlickException */ public void render(GameContainer container, StateBasedGame game, Graphics g, float cameraSpeed, Asset placingAsset) throws SlickException { // Floor for (Floor f : floors) { f.render(container, game, g); } // Renders the Tile layer for(int i = 0; i < getWidth(); i++) { for(int j = 0; j < getHeight(); j++) { gameTiles[i][j].render(container, game, g, cameraSpeed, placingAsset); } } // Renders the Line layer (blue lines around the Tiles) // It is done this way so that the Polygon selection looks good in the Pixel Art. super.render((int)xOffset, (int)yOffset, LINES); } /** * When the borders of the map change, find out where we need to place walls and floor tiles * @throws SlickException */ public void updateMapLimits() throws SlickException { // Reset our lists walls.clear(); floors.clear(); // Generate Walls boolean isPreviousTilePlayable = false; // First on Y for (int tileX = 0; tileX < getWidth(); tileX++) { for(int tileY = 0; tileY < getHeight(); tileY++) { if (isPreviousTilePlayable == false && playable[tileX][tileY]) { Wall w = new Wall(tileX, tileY, Entity.DOWN_LEFT); this.snapToGrid(w); walls.add(w); } else if (isPreviousTilePlayable == true && playable[tileX][tileY] == false) { Wall w = new Wall(tileX, tileY, Entity.UP_RIGHT); this.snapToGrid(w); walls.add(w); } isPreviousTilePlayable = playable[tileX][tileY]; } } // Then on X for (int tileY = 0; tileY < getHeight(); tileY++) { for(int tileX = 0; tileX < getWidth(); tileX++) { if (isPreviousTilePlayable == false && playable[tileX][tileY]) { Wall w = new Wall(tileX - 1, tileY, Entity.DOWN_RIGHT); this.snapToGrid(w); walls.add(w); } else if (isPreviousTilePlayable == true && playable[tileX][tileY] == false) { Wall w = new Wall(tileX, tileY, Entity.UP_LEFT); this.snapToGrid(w); walls.add(w); } isPreviousTilePlayable = playable[tileX][tileY]; // Place floor sprites Floor f = new Floor(tileX, tileY, playable[tileX][tileY]); this.snapToGrid(f); floors.add(f); } } // Unblock the new tiles blocked[xTileAtMouse][yTileAtMouse] = false; } /** * Places a Character on the Map * @param entity * @param xTile * @param yTile * @return */ public void placeObject(Character character, int xTile, int yTile) { // Set the xTile and yTile of the Character on the Map character.setXTile(xTile); character.setYTile(yTile); // Set the xPos and yPos of the Entity snapToGrid(character); } /** * Places an Asset on the Map * @param asset * @param xTile * @param yTile * @throws SlickException */ public void placeObject(Asset asset, ArrayList<Character> characters, int xTile, int yTile) throws SlickException { // Set the xTile and yTile of the Asset on the Map asset.setXTile(xTile); asset.setYTile(yTile); // Blocks the Tiles the Asset occupies if(asset.blocksMap()) { // The Tiles this Asset will block on the Map int assetMapXTiles[] = new int[asset.getxSize() * asset.getySize()]; int assetMapYTiles[] = new int[asset.getxSize() * asset.getySize()]; int currentLoop = 0; // Count that will go through the two arrays above // Block the Highlighted Tiles for(int i = 0; i < getWidth(); i++) { for(int j = 0; j < getHeight(); j++) { if(gameTiles[i][j].isHighlighted()) { // The Tile will be marked as blocked assetMapXTiles[currentLoop] = i; assetMapYTiles[currentLoop] = j; // Increase the loop count currentLoop++; } } } // The Asset object should know which Tiles it blocks on the Map asset.setMapXTiles(assetMapXTiles); asset.setMapYTiles(assetMapYTiles); // Block those Tiles on the Map for(int i = 0; i < asset.getxSize() * asset.getySize(); i++) { block(asset.getMapXTiles()[i], asset.getMapYTiles()[i]); } // Move Characters away from there this.moveCharactersAway(asset, characters); } // Set the Asset's usable Tiles. This is where the Characters will move to when using the Asset // For a console, the Tiles around the chair are the usable ones. That means 6 Tiles int usableXTiles[] = new int[1]; // Initialize int usableYTiles[] = new int[1]; if(asset instanceof Table) { // Create the arrays of usable tiles usableXTiles = new int[4]; for(int i = 0; i < usableXTiles.length; i++) usableXTiles[i] = -1; usableYTiles = new int[4]; for(int i = 0; i < usableYTiles.length; i++) usableYTiles[i] = -1; if(asset.getFacingDirection() == Entity.DOWN_RIGHT) { // Available Tiles directly in front of the Asset if(asset.getXTile() + (asset.getxSize()) < this.getWidth()) { usableXTiles[0] = asset.getXTile() + asset.getxSize(); usableYTiles[0] = asset.getYTile(); usableXTiles[1] = asset.getXTile() + asset.getxSize(); usableYTiles[1] = asset.getYTile() + 1; } // Available Tiles on the left of the Asset (x+) if(asset.getYTile() + asset.getySize() < this.getWidth()) { usableXTiles[2] = asset.getXTile() + asset.getxSize() - 1; usableYTiles[2] = asset.getYTile() + asset.getySize(); } // Available Tiles on the right of the Asset (x-); if(asset.getYTile() > 0) { usableXTiles[3] = asset.getXTile() + asset.getxSize() - 1; usableYTiles[3] = asset.getYTile() - 1; } } else if(asset.getFacingDirection() == Entity.DOWN_LEFT) { // Available Tiles directly in front of the Asset if(asset.getYTile() + asset.getxSize() < this.getHeight()) { usableXTiles[0] = asset.getXTile(); usableYTiles[0] = asset.getYTile() + asset.getxSize(); usableXTiles[1] = asset.getXTile() - 1; usableYTiles[1] = asset.getYTile() + asset.getxSize(); } // Available Tiles on the left of the Asset (y-) if(asset.getXTile() - asset.getySize() >= 0) { usableXTiles[2] = asset.getXTile() - asset.getySize(); usableYTiles[2] = asset.getYTile() + asset.getxSize() - 1; } // Available Tiles on the right of the Asset (y+); if(asset.getXTile() + 1 < this.getWidth()) { usableXTiles[3] = asset.getXTile() + 1; usableYTiles[3] = asset.getYTile() + asset.getxSize() - 1; } } else if(asset.getFacingDirection() == Entity.UP_LEFT) { // Available Tiles directly in front of the Asset if(asset.getXTile() - asset.getxSize() >= 0) { usableXTiles[0] = asset.getXTile() - asset.getxSize(); usableYTiles[0] = asset.getYTile(); usableXTiles[1] = asset.getXTile() - asset.getxSize(); usableYTiles[1] = asset.getYTile() - 1; } // Available Tiles on the left of the Asset (y+) if(asset.getYTile() + 1 < this.getHeight()) { usableXTiles[2] = asset.getXTile() - asset.getxSize() + 1; usableYTiles[2] = asset.getYTile() + 1; } // Available Tiles on the right of the Asset (y-); if(asset.getYTile() - asset.getySize() >= 0) { usableXTiles[3] = asset.getXTile() - asset.getxSize() + 1; usableYTiles[3] = asset.getYTile() - asset.getySize(); } } else { // if(asset.getFacingDirection() == Entity.UP_RIGHT) { // Available Tiles directly in front of the Asset if(asset.getYTile() - asset.getxSize() >= 0) { usableXTiles[0] = asset.getXTile(); usableYTiles[0] = asset.getYTile() - asset.getxSize(); usableXTiles[1] = asset.getXTile() + 1; usableYTiles[1] = asset.getYTile() - asset.getxSize(); } // Available Tiles on the left of the Asset (y-) if(asset.getXTile() - 1 >= 0) { usableXTiles[2] = asset.getXTile() + asset.getySize(); usableYTiles[2] = asset.getYTile() - asset.getxSize() + 1; } // Available Tiles on the right of the Asset (y+); if(asset.getXTile() + asset.getySize() < this.getWidth()) { usableXTiles[3] = asset.getXTile() - 1; usableYTiles[3] = asset.getYTile() - asset.getxSize() + 1; } } } else { // For all other Assets, it's the Tiles directly in front of it // Create the arrays of usable tiles usableXTiles = new int[asset.getySize()]; for(int i = 0; i < usableXTiles.length; i++) usableXTiles[i] = -1; usableYTiles = new int[asset.getySize()]; for(int i = 0; i < usableYTiles.length; i++) usableYTiles[i] = -1; // Every Tile in front of the Asset becomes usable, doesn't matter its size. if(asset.getFacingDirection() == Entity.DOWN_RIGHT) { // Check if the position is ok if(asset.getXTile() + asset.getxSize() < this.getWidth()) { // For each Y in that X... for(int i = 0; i < asset.getySize(); i++) { usableXTiles[i] = asset.getXTile() + asset.getxSize(); usableYTiles[i] = asset.getYTile() + i; } } } else if(asset.getFacingDirection() == Entity.DOWN_LEFT) { // Check if the position is ok if(asset.getYTile() + asset.getxSize() < this.getHeight()) { // For each Y in that X... for(int i = 0; i < asset.getySize(); i++) { usableXTiles[i] = asset.getXTile() - i; usableYTiles[i] = asset.getYTile() + asset.getxSize(); } } } else if(asset.getFacingDirection() == Entity.UP_LEFT) { // Check if the position is ok if(asset.getXTile() - asset.getxSize() >= 0) { // For each Y in that X... for(int i = 0; i < asset.getySize(); i++) { usableXTiles[i] = asset.getXTile() - asset.getxSize(); usableYTiles[i] = asset.getYTile() - i; } } } else { //if(asset.getFacingDirection() == Entity.UP_RIGHT) // Check if the position is ok if(asset.getYTile() - asset.getxSize() >= 0) { // For each Y in that X... for(int i = 0; i < asset.getySize(); i++) { usableXTiles[i] = asset.getXTile() + i; usableYTiles[i] = asset.getYTile() - asset.getxSize(); } } } } // After calculating, set their usable Tiles asset.setUsableXTiles(usableXTiles); asset.setUsableYTiles(usableYTiles); // Set the xPos and yPos of the Asset snapToGrid(asset); // Set not being on a Table asset.setOnTable(false); // Updates the Depth of the Asset on the Map asset.updateDepth(); } /** * Check if there were any Characters in the blocked Tiles so we move them out * @param asset * @param characters * @throws SlickException */ public void moveCharactersAway(Asset asset, ArrayList<Character> characters) throws SlickException { for(int i = 0; i < asset.getxSize() * asset.getySize(); i++) { // Loop through Characters for(Character c : characters) { // Check if the Character position intersects with the Asset position if(c.getXTile() == asset.getMapXTiles()[i] && c.getYTile() == asset.getMapYTiles()[i]) { // Ops. Found a Character there! Let's get that fucker out. int nextFreeXTile = -1; int nextFreeYTile = -1; // Let's find the next free tile, looking in all 4 directions if(asset.getMapXTiles()[i] + 1 < getWidth()) { if(!isBlocked(asset.getMapXTiles()[i] + 1, asset.getMapYTiles()[i])) { // DOWN RIGHT nextFreeXTile = asset.getMapXTiles()[i] + 1; nextFreeYTile = asset.getMapYTiles()[i]; } } if(asset.getMapXTiles()[i] - 1 >= 0) { if(!isBlocked(asset.getMapXTiles()[i] - 1, asset.getMapYTiles()[i])) { // UP LEFT nextFreeXTile = asset.getMapXTiles()[i] - 1; nextFreeYTile = asset.getMapYTiles()[i]; } } if(asset.getMapYTiles()[i] + 1 < getHeight()) { if(!isBlocked(asset.getMapXTiles()[i], asset.getMapYTiles()[i] + 1)) { // DOWN RIGHT nextFreeXTile = asset.getMapXTiles()[i]; nextFreeYTile = asset.getMapYTiles()[i] + 1; } } if(asset.getMapYTiles()[i] - 1 >= 0) { if(!isBlocked(asset.getMapXTiles()[i], asset.getMapYTiles()[i] - 1)) { // UP RIGHT nextFreeXTile = asset.getMapXTiles()[i]; nextFreeYTile = asset.getMapYTiles()[i] - 1; } } // We should have both Tiles now // If we don't, then place the Character back at the spawning location. if(nextFreeXTile == -1 || nextFreeYTile == -1) { placeObject(c, spawnPoint.x, spawnPoint.y); } else { // Otherwise, place the Character in the found location placeObject(c, nextFreeXTile, nextFreeYTile); } // Last but not least, we update its position and stop its movement c.stopMoving(this); c.setPath(null); c.setXPos(c.getOriginalXPos()); c.setYPos(c.getOriginalYPos()); c.setState(Character.IDLE); } } } } /** * If the player was moving an Asset and hit right click, we put the Asset back in its original position * @param asset * @throws SlickException */ public void releaseMovingObject(Asset asset, ArrayList<Character> characters) throws SlickException { // Block the Tiles the Asset used to block for(int i = 0; i < asset.getxSize() * asset.getySize(); i++) { block(asset.getMapXTiles()[i], asset.getMapYTiles()[i]); } // Get Characters away from those tiles this.moveCharactersAway(asset, characters); } /** * Removes an Asset from the Map, freeing up the Tiles it occupies * @param asset */ public void removeObject(Asset asset) { // Unblocks the Tiles this asset is currently blocking if(asset.blocksMap()) { for(int i = 0; i < asset.getxSize() * asset.getySize(); i++) { unblock(asset.getMapXTiles()[i], asset.getMapYTiles()[i]); } } } /** * Updates the position of a Character on the Map * @param character */ public void snapToGrid(Character character) { // x and y Offsets float xSpriteOffset = 0f; float ySpriteOffset = 0f; // Characters have an specific placement so their feet fit the middle of the Tile xSpriteOffset = -1f * (character.getSpriteWidth() / 2f); ySpriteOffset = -1f * (character.getSpriteHeight() + (getTileHeight() / 3f)); // Set the x and y Pos character.setXPos((getTileWidth() / 2f * character.getXTile()) - (getTileWidth() / 2f * character.getYTile()) + (getTileWidth() / 2f) + xSpriteOffset); character.setYPos((getTileHeight() / 2f * character.getXTile()) + (getTileHeight() / 2f * character.getYTile()) + (getTileHeight()) + ySpriteOffset); } /** * Fixes the position of a Wall on the map * @param character */ public void snapToGrid(Wall wall) { float xSpriteOffset = 0f; float ySpriteOffset = 0f; // x and y Offsets if (wall.getFacingDirection() == Entity.DOWN_LEFT) { xSpriteOffset = 0f; ySpriteOffset = -35f; } else if (wall.getFacingDirection() == Entity.DOWN_RIGHT) { xSpriteOffset = -4f; ySpriteOffset = -27f; } else if (wall.getFacingDirection() == Entity.UP_LEFT) { xSpriteOffset = -16f; ySpriteOffset = -33f; } else { xSpriteOffset = -4f; ySpriteOffset = -33f; } // Set the x and y Pos wall.setXPos((getTileWidth() / 2f * wall.getXTile()) - (getTileWidth() / 2f * wall.getYTile()) + (getTileWidth() / 2f) + xSpriteOffset); wall.setYPos((getTileHeight() / 2f * wall.getXTile()) + (getTileHeight() / 2f * wall.getYTile()) + (getTileHeight()) + ySpriteOffset); } /** * Fixes the position of a Floor tile on the map * @param character */ public void snapToGrid(Floor floor) { float xSpriteOffset = -16f; float ySpriteOffset = -16f; // Set the x and y Pos floor.setXPos((getTileWidth() / 2f * floor.getXTile()) - (getTileWidth() / 2f * floor.getYTile()) + (getTileWidth() / 2f) + xSpriteOffset); floor.setYPos((getTileHeight() / 2f * floor.getXTile()) + (getTileHeight() / 2f * floor.getYTile()) + (getTileHeight()) + ySpriteOffset); } /** * Updates the position of an Asset on the Map * * /----------------------------\ * | Worst code I've ever written | * \----------------------------/ * * @param asset */ public void snapToGrid(Asset asset) { // x and y Offsets float xSpriteOffset = 0f; float ySpriteOffset = 0f; // Asset placement adjust, according to the facingDirection if(asset.getFacingDirection() == Entity.DOWN_RIGHT) { if(asset instanceof Shelf) { xSpriteOffset = -1f * (getTileWidth() * 0.5f);} else if(asset instanceof Tv) { xSpriteOffset = -1f * getTileWidth() * 0.25f - 2f;} else if(asset instanceof Console) { xSpriteOffset = -1f * getTileWidth() * 0.25f - 3f;} else if(asset instanceof Table) { xSpriteOffset = -1f * (getTileWidth());} else if(asset instanceof Misc) { xSpriteOffset = -1f * (getTileWidth() * 0.5f - 5f);} if(asset instanceof Shelf) { ySpriteOffset = -1f * (getTileHeight() * 2.75f);} else if(asset instanceof Tv) { ySpriteOffset = -1f * getTileHeight() * 1.25f - 3f;} else if(asset instanceof Console) { ySpriteOffset = -1f * getTileHeight();} else if(asset instanceof Table) { ySpriteOffset = -1f * (getTileHeight()) * 1.25f;} else if(asset instanceof Misc) { ySpriteOffset = -1f * (getTileHeight() * 2.5f + 2f);} } else if (asset.getFacingDirection() == Entity.DOWN_LEFT) { if(asset instanceof Shelf) { xSpriteOffset = -1f * (getTileWidth() * 0.5f);} else if(asset instanceof Tv) { xSpriteOffset = -1f * (getTileWidth() * 0.5f - 2f);} else if(asset instanceof Console) { xSpriteOffset = -1f * getTileWidth() * 0.25f - 4f;} else if(asset instanceof Table) { xSpriteOffset = -1f * (getTileWidth());} else if(asset instanceof Misc) { xSpriteOffset = -1f * (getTileWidth() * 0.5f - 5f);} if(asset instanceof Shelf) { ySpriteOffset = -1f * (getTileHeight() * 2.75f);} else if(asset instanceof Tv) { ySpriteOffset = -1f * (getTileHeight() * 1.5f - 1f);} else if(asset instanceof Console) { ySpriteOffset = -1f * getTileHeight();} else if(asset instanceof Table) { ySpriteOffset = -1f * (getTileHeight() * 1.75f);} else if(asset instanceof Misc) { ySpriteOffset = -1f * (getTileHeight() * 2.5f + 2f);} } else if (asset.getFacingDirection() == Entity.UP_LEFT) { if(asset instanceof Shelf) { xSpriteOffset = -1f * (getTileWidth() / 2f);} else if(asset instanceof Tv) { xSpriteOffset = -1f * getTileWidth() * 0.25f;} else if(asset instanceof Console) { xSpriteOffset = -1f * getTileWidth() / 2.25f;} else if(asset instanceof Table) { xSpriteOffset = -1f * (getTileWidth() / 2f);} else if(asset instanceof Misc) { xSpriteOffset = -1f * (getTileWidth() * 0.5f - 5f);} if(asset instanceof Shelf) { ySpriteOffset = -1f * (getTileHeight() * 2.75f);} else if(asset instanceof Tv) { ySpriteOffset = -1f * getTileHeight() * 1.5f;} else if(asset instanceof Console) { ySpriteOffset = -1f * getTileHeight();} else if(asset instanceof Table) { ySpriteOffset = -1f * (getTileHeight() * 1.75f);} else if(asset instanceof Misc) { ySpriteOffset = -1f * (getTileHeight() * 2.5f + 2f);} } else { //asset.getFacingDirection() == Entity.UP_RIGHT if(asset instanceof Shelf) { xSpriteOffset = -1f * (getTileWidth() / 2f);} else if(asset instanceof Tv) { xSpriteOffset = -1f * getTileWidth() * 0.25f - 3f;} else if(asset instanceof Console) { xSpriteOffset = -1f * getTileWidth() / 2.5f;} else if(asset instanceof Table) { xSpriteOffset = -1f * (getTileWidth() / 2f);} else if(asset instanceof Misc) { xSpriteOffset = -1f * (getTileWidth() * 0.5f - 5f);} if(asset instanceof Shelf) { ySpriteOffset = -1f * (getTileHeight() * 2.75f);} else if(asset instanceof Tv) { ySpriteOffset = -1f * getTileHeight() * 1.5f;} else if(asset instanceof Console) { ySpriteOffset = -1f * getTileHeight();} else if(asset instanceof Table) { ySpriteOffset = -1f * (getTileHeight()* 1.25f);} else if(asset instanceof Misc) { ySpriteOffset = -1f * (getTileHeight() * 2.5f + 2f);} } // Set the x and y Sprite Offset asset.setxSpriteOffset(xSpriteOffset); asset.setySpriteOffset(ySpriteOffset); // Set the x and y Pos asset.setXPos((getTileWidth() / 2 * asset.getXTile()) - (getTileWidth() / 2 * asset.getYTile()) + (getTileWidth() / 2)); asset.setYPos((getTileHeight() / 2 * asset.getXTile()) + (getTileHeight() / 2 * asset.getYTile()) + (getTileHeight())); } /** * Unhighlights all Tiles */ public void unhighlightAll() { for(int i = 0; i < getWidth(); i++) { for(int j = 0; j < getHeight(); j++) { gameTiles[i][j].setHighlighted(false); } } } /** * Returns a list of Walls and Floors * * @return */ public ArrayList<Terrain> getTerrain() { ArrayList<Terrain> terrainBlocks = new ArrayList<Terrain>(); terrainBlocks.addAll(walls); terrainBlocks.addAll(floors); return terrainBlocks; } // isBlocked, Block and Unblock public boolean isBlocked(int x, int y) {return blocked[x][y];} public void block(int x, int y) {blocked[x][y] = true;} public void unblock(int x, int y) {blocked[x][y] = false;} // Is playable public boolean isPlayable(int x, int y) {return playable[x][y];} /** * Returns a list of playable map tiles * @return */ public int getAmountOfPlayableTiles() { int playableTiles = 0; for (int i = 0; i < playable.length; i++) { for (int j = 0; j < playable[i].length; j++) { if (playable[i][j]) { playableTiles++; } } } return playableTiles; } @Override public void pathFinderVisited(int x, int y) { // TODO Auto-generated method stub } @Override public boolean blocked(PathFindingContext context, int tx, int ty) { return blocked[tx][ty]; } @Override public float getCost(PathFindingContext context, int tx, int ty) { return 0; } public int getXTileAtMouse() {return xTileAtMouse;} public int getYTileAtMouse() {return yTileAtMouse;} public AStarPathFinder getPathFinder() {return pathFinder;} @Override public int getHeightInTiles() { return getHeight(); } @Override public int getWidthInTiles() { return getWidth(); } public float getxOffset() { return xOffset; } public void setxOffset(float xOffset) { this.xOffset = xOffset; } public float getyOffset() { return yOffset; } public void setyOffset(float yOffset) { this.yOffset = yOffset; } public int getTileWidth() { return tileWidth; } public int getTileHeight() { return tileHeight; } public Tile getSpawnPoint() { return spawnPoint; } public void setSpawnPoint(Tile spawnPoint) { this.spawnPoint = spawnPoint; } public ArrayList<Wall> getWalls() { return walls; } public void setWalls(ArrayList<Wall> walls) { this.walls = walls; } public ArrayList<Floor> getFloors() { return floors; } public void setFloors(ArrayList<Floor> floors) { this.floors = floors; } }