package com.lucasdnd.ags.gameplay; import java.util.ArrayList; import org.newdawn.slick.Animation; import org.newdawn.slick.Color; import org.newdawn.slick.GameContainer; import org.newdawn.slick.Graphics; import org.newdawn.slick.Image; import org.newdawn.slick.Input; import org.newdawn.slick.SlickException; import org.newdawn.slick.state.StateBasedGame; import com.lucasdnd.ags.gameplay.market.MarketAsset; import com.lucasdnd.ags.map.Map; import com.lucasdnd.ags.map.OffsetUtil; import com.lucasdnd.ags.system.GameSystem; import com.lucasdnd.ags.system.MainState; import com.lucasdnd.ags.ui.MiniPanel; public abstract class Asset extends Entity { /** Position */ private int[] mapXTiles; // Based on the x and y Tiles and the Entity Size, these are the private int[] mapYTiles; // tiles this Entity occupies on the Map. private int[] usableXTiles; // Based on the asset's x and y Map Tiles and the facingDirection, these will be the private int[] usableYTiles; // tiles the Characters will move to when using this Asset. protected float xSpriteOffset; // Sprite x Offset specific to Assets protected float ySpriteOffset; // Sprite y Offset specific to Assets /** Movement and Placement */ protected boolean validPlacement; // Indicates if the current placement is valid (for moving assets). protected boolean isBeingMoved; // Indicates if the player is moving this Asset to another place protected boolean isOnTable; // Is on the table protected boolean canMove; // Indicates if the Asset can be moved. // If there's a Character using, for example, this will be false. /** Market */ private MarketAsset referringMarketAsset; // The product this Asset refers to /** Use of the Asset */ private ArrayList<Customer> users; /** The MiniPanel */ protected MiniPanel miniPanel; protected Asset(int id, MarketAsset placingMarketAsset) throws SlickException { // Entity Constructor super(id); // The product it refers to referringMarketAsset = placingMarketAsset; // Create and load the Standing Still Images this.spriteSheet = placingMarketAsset.getSpriteSheet(); image = new Image[4]; for(int i = 0; i < image.length; i++) { image[i] = spriteSheet.getSprite(i, 0); image[i].setFilter(Image.FILTER_NEAREST); } // Create the Animations frameDuration = 150; animation = new Animation[4]; animation[DOWN_RIGHT] = new Animation(new Image[] {image[DOWN_RIGHT], spriteSheet.getSprite(0, 0), spriteSheet.getSprite(0, 0), spriteSheet.getSprite(0, 0)}, frameDuration); animation[DOWN_LEFT] = new Animation(new Image[] {image[DOWN_LEFT], spriteSheet.getSprite(1, 0), spriteSheet.getSprite(1, 0), spriteSheet.getSprite(1, 0)}, frameDuration); animation[UP_LEFT] = new Animation(new Image[] {image[UP_LEFT], spriteSheet.getSprite(2, 0), spriteSheet.getSprite(2, 0), spriteSheet.getSprite(2, 0)}, frameDuration); animation[UP_RIGHT] = new Animation(new Image[] {image[UP_RIGHT], spriteSheet.getSprite(3, 0), spriteSheet.getSprite(3, 0), spriteSheet.getSprite(3, 0)}, frameDuration); for(int i = 0; i < animation.length; i++) { animation[i].setAutoUpdate(true); animation[i].setPingPong(true); } // Some basic Sprite parameters spriteWidth = image[0].getWidth(); spriteHeight = image[0].getHeight(); facingDirection = DOWN_RIGHT; scale = 1f; // Basic Attributes blocksMap = true; canMove = true; isBeingMoved = false; // Users of this Asset users = new ArrayList<Customer>(); // Set the facingDirection according to the facingDirection of the Placement facingDirection = Entity.DOWN_RIGHT; // Set the size of the Asset xSize = placingMarketAsset.getxSize(); ySize = placingMarketAsset.getySize(); // Update the Depth this.updateDepth(); } /** * Specific update for Assets. Different depth calculation. * @param container * @param game * @param delta * @param input * @param map * @param leftMouseClicked * @param mouseX * @param mouseY * @param entities * @throws SlickException */ public void update(GameContainer container, StateBasedGame game, int delta, Input input, boolean leftMouseClicked, boolean leftMouseDown, int mouseX, int mouseY, Business business, MainState mainState) throws SlickException { // Check if the Asset can be moved or deleted if(users.size() == 0 && isBeingMoved == false) { canMove = true; } else { canMove = false; } } /** * Returns an array of size 2 where the first index is the random usable X tile * and the second index is the random usable Y tile. * @return */ public int[] getRandomUsableTile(Map map) { // Get all the Valid Usable Tiles (ones that are not -1 or blocked) ArrayList<Integer> validUsableTilesIndexes = new ArrayList<Integer>(); for(int i = 0; i < usableXTiles.length; i++) { // Not blocked, not -1 if(usableXTiles[i] != -1 && usableYTiles[i] != -1 && !map.isBlocked(usableXTiles[i], usableYTiles[i])) { validUsableTilesIndexes.add(i); } } // If there's any if(validUsableTilesIndexes.size() > 0) { // Generates a random index int randomIndex = new java.util.Random().nextInt(validUsableTilesIndexes.size()); // Get the coordinates according to the random index int[] result = new int[2]; result[0] = usableXTiles[validUsableTilesIndexes.get(randomIndex)]; result[1] = usableYTiles[validUsableTilesIndexes.get(randomIndex)]; // Return the coordinates return result; } return null; } /** * This method calculates the uppermost tile of the Asset. Called when we move it. */ public void updateDepth() { // Tables have different stuff int xReduction = 1; if(this instanceof Table) { xReduction = 2; // Because tables don't really take 3x2 on the screen } // Calculate the Uppermost Tile, since Assets can occupy more than 1 Tile // The Uppermost Tile depends on the facingDirection of the Asset if(facingDirection == DOWN_RIGHT) { topmostXTile = xTile + (xSize - xReduction); topmostYTile = yTile + (ySize - 1); } else if(facingDirection == DOWN_LEFT) { topmostXTile = xTile; topmostYTile = yTile + (xSize - xReduction); } else if(facingDirection == UP_LEFT) { topmostXTile = xTile; topmostYTile = yTile; } else {//if(facingDirection == UP_RIGHT) { topmostXTile = xTile - (ySize - 1); topmostYTile = yTile; } // Calculates its depth depth = topmostXTile + topmostYTile; } @Override public void render(GameContainer container, StateBasedGame game, Graphics g) throws SlickException { // Draw only the first Sprite // If the Asset is being moved, we ghost the current image out if(isBeingMoved) { animation[facingDirection].getImage(0).draw( xSpriteOffset + (float)container.getInput().getMouseX() / GameSystem.globalScale, ySpriteOffset + (float)container.getInput().getMouseY() / GameSystem.globalScale, new Color(255, 255, 255, 0.5f)); } else { animation[facingDirection].getImage(0).draw(xPos + OffsetUtil.getPreciseOffset(xOffset) + xSpriteOffset, yPos + OffsetUtil.getPreciseOffset(yOffset) + ySpriteOffset); } } /** * Check if the player mouse overed the Tiles * @param xTileAtMouse * @param yTileAtMouse * @return */ public boolean tilesGotMouseOvered(int xTileAtMouse, int yTileAtMouse) { if(mapXTiles == null || mapYTiles == null) return false; for(int i = 0; i < xSize * ySize; i++) { if(xTileAtMouse == mapXTiles[i] && yTileAtMouse == mapYTiles[i]) { return true; } } return false; } /** * Check if the Tiles of the Asset got Left Clicked * @param leftMouseClicked * @param xTileAtMouse * @param yTileAtMouse * @return */ public boolean tilesGotLeftClicked(boolean leftMouseClicked, int xTileAtMouse, int yTileAtMouse) { if(leftMouseClicked) { return tilesGotMouseOvered(xTileAtMouse, yTileAtMouse); } return false; } /** * Changes the Facing Direction */ public void rotate() { facingDirection++; if(facingDirection > 3) facingDirection = 0; } public int[] getMapXTiles() { return mapXTiles; } public void setMapXTiles(int[] mapXTiles) { this.mapXTiles = mapXTiles; } public int[] getMapYTiles() { return mapYTiles; } public void setMapYTiles(int[] mapYTiles) { this.mapYTiles = mapYTiles; } public boolean isValidPlacement() { return validPlacement; } public void setValidPlacement(boolean validPlacement) { this.validPlacement = validPlacement; } public boolean isBeingMoved() { return isBeingMoved; } public void setBeingMoved(boolean isBeingMoved) { this.isBeingMoved = isBeingMoved; } public MarketAsset getReferringMarketAsset() { return referringMarketAsset; } public void setReferringMarketAsset(MarketAsset referringMarketAsset) { this.referringMarketAsset = referringMarketAsset; } public int[] getUsableXTiles() { return usableXTiles; } public void setUsableXTiles(int[] usableXTiles) { this.usableXTiles = usableXTiles; } public int[] getUsableYTiles() { return usableYTiles; } public void setUsableYTiles(int[] usableYTiles) { this.usableYTiles = usableYTiles; } public boolean canMove() { return canMove; } public void setCanMove(boolean canMove) { this.canMove = canMove; } public ArrayList<Customer> getUsers() { return users; } public void setUsers(ArrayList<Customer> users) { this.users = users; } public float getxSpriteOffset() { return xSpriteOffset; } public void setxSpriteOffset(float xSpriteOffset) { this.xSpriteOffset = xSpriteOffset; } public float getySpriteOffset() { return ySpriteOffset; } public void setySpriteOffset(float ySpriteOffset) { this.ySpriteOffset = ySpriteOffset; } public MiniPanel getMiniPanel() { return miniPanel; } public void setMiniPanel(MiniPanel miniPanel) { this.miniPanel = miniPanel; } public boolean isOnTable() { return isOnTable; } public void setOnTable(boolean isOnTable) { this.isOnTable = isOnTable; } public boolean isCanMove() { return canMove; } }