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;
}
}