package com.drakulo.games.ais.ui.state;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.newdawn.slick.Color;
import org.newdawn.slick.Font;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.tiled.TiledMap;
import com.drakulo.games.ais.AloneInSpace;
import com.drakulo.games.ais.core.Colony;
import com.drakulo.games.ais.core.GameData;
import com.drakulo.games.ais.core.GameEngine;
import com.drakulo.games.ais.core.NumberHelper;
import com.drakulo.games.ais.core.Resource;
import com.drakulo.games.ais.core.ResourceHelper;
import com.drakulo.games.ais.core.Settings;
import com.drakulo.games.ais.core.building.Building;
import com.drakulo.games.ais.core.building.BuildingData;
import com.drakulo.games.ais.core.building.BuildingHelper;
import com.drakulo.games.ais.core.building.BuildingLevelData;
import com.drakulo.games.ais.core.building.BuildingType;
import com.drakulo.games.ais.core.delayed.BuildingAction;
import com.drakulo.games.ais.core.delayed.DelayedAction;
import com.drakulo.games.ais.core.delayed.MapAction;
import com.drakulo.games.ais.core.delayed.PreparationAction;
import com.drakulo.games.ais.core.delayed.ColonyAction;
import com.drakulo.games.ais.core.delayed.SpecialActionManager;
import com.drakulo.games.ais.core.io.BuildingIO;
import com.drakulo.games.ais.core.tech.TechnologyHelper;
import com.drakulo.games.ais.ui.FontHelper;
import com.drakulo.games.ais.ui.I18n;
import com.drakulo.games.ais.ui.ImageManager;
import com.drakulo.games.ais.ui.Style;
import com.drakulo.games.ais.ui.TileHelper;
import com.drakulo.games.ais.ui.UIHelper;
import com.drakulo.games.ais.ui.component.ActionHandler;
import com.drakulo.games.ais.ui.component.Minimap;
import com.drakulo.games.ais.ui.component.ProgressBar;
import com.drakulo.games.ais.ui.component.UIComponent;
import com.drakulo.games.ais.ui.component.button.Button;
import com.drakulo.games.ais.ui.component.button.ImageButton;
import com.drakulo.games.ais.ui.component.button.TextButton;
import com.drakulo.games.ais.ui.component.window.BuildWindow;
import com.drakulo.games.ais.ui.twlbridge.RootPane;
import de.matthiasmann.twl.Label;
public class SectorState extends GameState {
/** -------------------------------------------- */
/** TWL Widgets -------------------------------- */
/** -------------------------------------------- */
/**
* Map of labels showing resource amounts, max space, space available and
* modifiers
*/
private Map<Resource, Label> inStoreLabels;
private Map<Resource, Label> maxStoreLabels;
private Map<Resource, Label> availableSpaceLabels;
private Map<Resource, Label> modifiersLabels;
/** Rows labels of resource extended mode */
private Label storeTitle;
private Label maxStoreTitle;
private Label availableSpaceTitle;
private Label modifierTitle;
/** Game menu buttons */
private List<Button> gameMenuButtons;
/** Selected building labels displaying it's attributes */
private Map<Resource, Label> buildingProdLabels;
private Map<Resource, Label> buildingConsLabels;
private Map<Resource, Label> buildingStoreLabels;
private Label[] buildingColLabels;
private Map<Resource, Label> buildingRowLabels;
/** Upgrade overview labels */
private Map<Resource, Label> upgradeLabels;
/** -------------------------------------------- */
/** Other properties --------------------------- */
/** -------------------------------------------- */
/** Height of the bottom bar */
private static final int BOTTOM_BAR_HEIGHT = Minimap.HEIGHT.intValue() + 20;
/** Padding */
private static final int PADDING = 10;
/** The top resource zone width */
private static final int TOP_BAR_WIDTH = 653;
/** The toggle button zone */
private static final int TOGGLE_BUTTON_ZONE_WIDTH = 24;
/** The map viewport width */
public static final int VIEWPORT_WIDTH = Settings.WIDTH;
/** The map viewport height */
public static final int VIEWPORT_HEIGHT = Settings.HEIGHT
- BOTTOM_BAR_HEIGHT - TOP_BAR_HEIGHT;
/** The minimap */
private Minimap minimap;
/** Top scroll zone */
private Rectangle topScrollZone;
/** Bottom scroll zone */
private Rectangle bottomScrollZone;
/** Left scroll zone */
private Rectangle leftScrollZone;
/** Right scroll zone */
private Rectangle rightScrollZone;
/** The building selected by the player */
private Building selectedBuilding;
/** A map of Progress bar, one for each resource */
private Map<Resource, ProgressBar> resourceBars;
/** Progress bar for robots use */
private ProgressBar robotBar;
/** Current research progress bar */
private ProgressBar researchBar;
/** Resource zone extended display */
private boolean extendedResourceDisplay;
/** The game menu display flag */
private boolean showGameMenu;
/** The building action Window */
private BuildWindow buildWindow;
/** The building action window display flag */
private boolean showActionWindow;
/** The selected map action */
private MapAction selectedAction;
/** Current X coordinate of the mouse on the screen */
private int mouseX;
/** Current Y coordinate of the mouse on the screen */
private int mouseY;
/** Current X coordinate of the square hovered on screen */
private int squareXOnScreen;
/** Current Y coordinate of the square hovered on screen */
private int squareYOnScreen;
/** Current X coordinate of the square hovered on map */
private int squareXOnMap;
/** Current Y coordinate of the square hovered on map */
private int squareYOnMap;
/** The selected building current action progress bar */
private ProgressBar selectedBuildingPB;
/** The Develop button */
private ImageButton developButton;
/** The research button */
private ImageButton researchVisionButton;
/** The planet button */
private ImageButton planetVisionButton;
/** This button cancels the selected building current action */
private ImageButton cancelButton;
/** Building buttons array */
private ImageButton[][] buildingButtons;
/** The list of UIComponents to render and update */
private List<UIComponent> components;
public SectorState(int id) {
super(id);
this.extendedResourceDisplay = false;
this.showGameMenu = false;
this.components = new ArrayList<UIComponent>();
}
@Override
protected RootPane createRootPane() {
this.rootPane = super.createRootPane();
// final int startX = Settings.WIDTH - Minimap.WIDTH.intValue() -
// PADDING
// + 5;
// final int startY = Settings.HEIGHT - Minimap.HEIGHT.intValue()
// - PADDING + 5;
int width = TOP_BAR_WIDTH + TOGGLE_BUTTON_ZONE_WIDTH;
int x = Settings.WIDTH / 2 - width / 2 + 3;
int y = PADDING + 3;
this.inStoreLabels = new HashMap<Resource, Label>();
this.maxStoreLabels = new HashMap<Resource, Label>();
this.availableSpaceLabels = new HashMap<Resource, Label>();
this.modifiersLabels = new HashMap<Resource, Label>();
Resource[] resources = Resource.values();
for (Resource r : resources) {
this.inStoreLabels.put(r, createAndAddResourceLabel(null));
this.maxStoreLabels.put(r, createAndAddResourceLabel(null));
this.availableSpaceLabels.put(r, createAndAddResourceLabel(null));
this.modifiersLabels.put(r, createAndAddResourceLabel(null));
}
this.storeTitle = createAndAddResourceLabel(I18n
.get("resource.stored_quantity"));
this.maxStoreTitle = createAndAddResourceLabel(I18n
.get("resource.max_space"));
this.availableSpaceTitle = createAndAddResourceLabel(I18n
.get("resource.available_space"));
this.modifierTitle = createAndAddResourceLabel(I18n
.get("resource.modifier"));
// Selected building attributes labels
this.buildingProdLabels = new HashMap<Resource, Label>();
this.buildingConsLabels = new HashMap<Resource, Label>();
this.buildingStoreLabels = new HashMap<Resource, Label>();
this.buildingRowLabels = new HashMap<Resource, Label>();
this.upgradeLabels = new HashMap<Resource, Label>();
for (Resource r : resources) {
this.buildingProdLabels.put(r,
createAndAddResourceLabel(null, 80, "resourceLabel"));
this.buildingConsLabels.put(r,
createAndAddResourceLabel(null, 80, "resourceLabel"));
this.buildingStoreLabels.put(r,
createAndAddResourceLabel(null, 80, "resourceLabel"));
this.buildingRowLabels.put(
r,
createAndAddResourceLabel(
FontHelper.firstToUpper(r.getI18n()), 80,
"resourceLabel"));
this.upgradeLabels.put(r,
createAndAddResourceLabel(null, 80, "resourceLabel"));
}
this.buildingColLabels = new Label[3];
this.buildingColLabels[0] = createAndAddResourceLabel(
I18n.get("resource.income.short"), 80, "titleResourceLabel");
this.buildingColLabels[1] = createAndAddResourceLabel(
I18n.get("resource.consumption.short"), 80,
"titleResourceLabel");
this.buildingColLabels[2] = createAndAddResourceLabel(
I18n.get("resource.store"), 80, "titleResourceLabel");
return this.rootPane;
}
private Label createAndAddResourceLabel(String title, int width,
String theme) {
Label l;
if (title == null) {
l = new Label();
} else {
l = new Label(title);
}
l.setVisible(false);
l.setSize(width, 15);
l.setTheme(theme);
this.rootPane.add(l);
return l;
}
/**
* @return A themed label for extended resources display
*/
private Label createAndAddResourceLabel(String title) {
return this.createAndAddResourceLabel(title, 122, "resourceLabel");
}
@Override
public void initState() throws SlickException {
// TODO externalize this part
// Load the tiledmap
TiledMap tiledMap = new TiledMap("data/testmap.tmx");
Colony c = new Colony();
c.setAvailableRobots(3);
c.setTotalRobots(3);
c.setMap(tiledMap);
c.setName("Anthem Base");
Resource[] resources = Resource.values();
for (Resource r : resources) {
c.setResource(r, BigDecimal.valueOf(1000));
}
c.setResearchCenterBuilt(false);
GameData.addColony(c);
GameData.setSelectedColony(c);
// /////////////////////////
// End of to externalize zone
final int pad = 10;
final int minimapX = pad;
final int minimapY = Settings.HEIGHT - pad - Minimap.HEIGHT.intValue();
this.minimap = new Minimap(minimapX, minimapY);
// Initialization of border scroll zones
initializeScrollZones();
// Progress bars
this.resourceBars = new HashMap<Resource, ProgressBar>();
for (Resource r : resources) {
ProgressBar pb = UIHelper.createBar(r.getI18n(), r.getColor(),
false);
this.resourceBars.put(r, pb);
}
this.robotBar = UIHelper.createBar("Robots", Color.white, true);
this.selectedBuildingPB = new ProgressBar();
this.selectedBuildingPB.setHeight(10);
this.selectedBuildingPB.setWidth(202);
this.selectedBuildingPB.setEmptyColor(Color.darkGray);
this.selectedBuildingPB.setFilledColor(Color.magenta);
int x = Settings.WIDTH / 2 - ImageButton.IB_DEFAULT_SIZE / 2;
int y = Settings.HEIGHT - 116 - PADDING - ImageButton.IB_DEFAULT_SIZE
- PADDING;
this.developButton = new ImageButton("cog", x, y);
developButton.setTitle(I18n.get("ui.build_panel"));
this.developButton.setActionHandler(new ActionHandler() {
@Override
public void run() {
showBuildWindow(!SectorState.this.showActionWindow);
}
});
add(developButton);
x -= PADDING + ImageButton.IB_DEFAULT_SIZE;
this.researchVisionButton = new ImageButton("lightbulb", x, y);
researchVisionButton.setTitle(I18n.get("vision.research"));
this.researchVisionButton.disable();
this.researchVisionButton.setActionHandler(new ActionHandler() {
@Override
public void run() {
GameData.getGame().enterState(AloneInSpace.RESEARCH_STATE);
}
});
add(researchVisionButton);
x -= PADDING + ImageButton.IB_DEFAULT_SIZE;
this.planetVisionButton = new ImageButton("globe_3", x, y);
planetVisionButton.setTitle(I18n.get("vision.planet"));
this.planetVisionButton.disable();
this.planetVisionButton.setActionHandler(new ActionHandler() {
@Override
public void run() {
SectorState.this.selectedAction = null;
SectorState.this.selectedBuilding = null;
GameData.getGame().enterState(AloneInSpace.PLANET_STATE);
}
});
add(planetVisionButton);
// Cancel button
final int startX = Settings.WIDTH - Minimap.WIDTH.intValue() - PADDING
+ 10;
final int startY = Settings.HEIGHT - Minimap.HEIGHT.intValue()
- PADDING + 9;
this.buildingButtons = new ImageButton[3][3];
for (int col = 0; col < 3; col++) {
for (int row = 0; row < 3; row++) {
this.buildingButtons[col][row] = new ImageButton(null, startX
+ col * 46, startY + row * 46);
this.buildingButtons[col][row].disable();
this.buildingButtons[col][row].hide();
}
}
this.cancelButton = this.buildingButtons[2][2];
this.cancelButton.setImageRef("cancel");
this.cancelButton.setActionHandler(new ActionHandler() {
@Override
public void run() {
stopSelectedBuildingAction();
}
});
this.buildingButtons[0][2].setImageRef("upgrade");
this.buildingButtons[0][2].setActionHandler(new ActionHandler() {
@Override
public void run() {
hideUpgradeLabels();
upgradeBuilding(SectorState.this.selectedBuilding);
}
});
int width = TOP_BAR_WIDTH + TOGGLE_BUTTON_ZONE_WIDTH;
x = Settings.WIDTH / 2 - width / 2 + 4;
y = PADDING + 3;
final TextButton resourceTogglerButton = new TextButton("+");
resourceTogglerButton.setPosition(x, y);
resourceTogglerButton.setSize(21, 21);
resourceTogglerButton.setActionHandler(new ActionHandler() {
@Override
public void run() {
SectorState.this.extendedResourceDisplay = !SectorState.this.extendedResourceDisplay;
Resource[] resources = Resource.values();
for (Resource r : resources) {
boolean show = SectorState.this.extendedResourceDisplay;
SectorState.this.inStoreLabels.get(r).setVisible(show);
SectorState.this.maxStoreLabels.get(r).setVisible(show);
SectorState.this.availableSpaceLabels.get(r).setVisible(
show);
SectorState.this.modifiersLabels.get(r).setVisible(show);
SectorState.this.storeTitle.setVisible(show);
SectorState.this.maxStoreTitle.setVisible(show);
SectorState.this.availableSpaceTitle.setVisible(show);
SectorState.this.modifierTitle.setVisible(show);
if (show) {
resourceTogglerButton.setText("-");
} else {
resourceTogglerButton.setText("+");
}
}
}
});
add(resourceTogglerButton);
width = 270;
int height = 300;
x = Settings.WIDTH / 2 - width / 2;
y = Settings.HEIGHT - BOTTOM_BAR_HEIGHT - height;
this.buildWindow = new BuildWindow(this, width, height, x, y);
}
@Override
public void renderState(Graphics g) throws SlickException {
// Render the tiled map view port
Colony c = GameData.getSelectedColony();
GameData.getCurrentMap().render(c.getViewportX(), c.getViewportY(),
TileHelper.DECO_LAYER);
// Render the buildings
renderBuildings(g);
// Render the robots
renderRobots(g);
// If an action is selected, a shadow rendering is done
if (this.selectedAction != null) {
Image gfx = ImageManager.getGfx(this.selectedAction.getGfxKey());
final int tileX = this.squareXOnMap;
final int tileY = this.squareYOnMap;
if (this.selectedAction instanceof PreparationAction) {
// Preparation action
if (TileHelper.tileIsPreparable(tileX, tileY)) {
gfx.draw(this.squareXOnScreen, this.squareYOnScreen);
} else {
gfx.draw(this.squareXOnScreen, this.squareYOnScreen,
Color.red);
}
} else if (this.selectedAction instanceof BuildingAction) {
// Building action
BuildingAction ba = (BuildingAction) this.selectedAction;
if (BuildingType.COMMAND_CENTER.equals(ba.getBuilding()
.getType())) {
// Render the effect zone around the command center
if (TileHelper.isValidCommandCenterTile(tileX, tileY)) {
g.setColor(Style.FILTER_GREEN);
} else {
// The zone is not correct for Command Center
// construction.
g.setColor(Style.FILTER_RED);
}
int x = getScreenX(tileX - 1);
int y = getScreenY(tileY - 1);
g.fillRect(x, y, Settings.TILE_SIZE * 3,
Settings.TILE_SIZE * 3);
gfx.draw(this.squareXOnScreen, this.squareYOnScreen);
// The command center construction is an exception
} else if (TileHelper.tileIsBuildable(tileX, tileY, ba
.getBuilding().getType())) {
// Can build here
gfx.draw(this.squareXOnScreen, this.squareYOnScreen);
} else {
// Cannot build here
gfx.draw(this.squareXOnScreen, this.squareYOnScreen,
Color.red);
}
}
}
// The UI rendering is done in last order
renderUI(g);
// DEBUG Data
// final int tileX = this.squareXOnMap;
// final int tileY = this.squareYOnMap;
// Font debugFont = FontHelper
// .getFont(FontHelper.ANONYMOUS, Color.red, 20);
// debugFont.drawString(0, 50, "[" + tileX + "," + tileY + "]");
}
/**
* Renders the user interface
*
* @param g
* The graphics canvas
* @throws SlickException
*/
private void renderUI(Graphics g) throws SlickException {
int x = 0;
int y = Settings.HEIGHT - Minimap.HEIGHT.intValue() - PADDING * 2;
UIHelper.drawBox(g, x, y, Settings.WIDTH, Settings.HEIGHT - y);
// The minimap
this.minimap.render(g);
// The action zone
y = Settings.HEIGHT - Minimap.HEIGHT.intValue() - PADDING;
x = Settings.WIDTH - Minimap.WIDTH.intValue() - PADDING;
g.setColor(Style.BORDER_COLOR);
UIHelper.drawBox(g, x, y, 150, 150);
final int startX = Settings.WIDTH - Minimap.WIDTH.intValue() - PADDING
+ 7;
final int startY = Settings.HEIGHT - Minimap.HEIGHT.intValue()
- PADDING + 7;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
UIHelper.drawDarkBox(g, startX + i * 46, startY + j * 46, 43,
43);
}
}
// The game menu
if (this.showGameMenu) {
int menuHeight = 35 + this.gameMenuButtons.size() * 25;
UIHelper.drawDarkBox(g, PADDING / 2, PADDING / 2, 120, menuHeight);
}
// The action window
this.buildWindow.render(g);
// Attributes Background
int ox = 150 + PADDING * 2;
int oy = Settings.HEIGHT - 116 - PADDING;
UIHelper.drawDarkBox(g, ox, oy, 368, 116);
// Overview background
ox = 150 + PADDING * 2 + 368 + PADDING;
oy = Settings.HEIGHT - Minimap.HEIGHT.intValue() - PADDING;
UIHelper.drawDarkBox(g, ox, oy, 306, 150);
if (this.selectedBuilding != null) {
renderBuildingAttributes(g);
renderBuildingOverview(g);
}
// Rendering of building buttons
for (int col = 0; col < 3; col++) {
for (int row = 0; row < 3; row++) {
this.buildingButtons[col][row].render(g);
}
}
// Upgrade button
if (this.selectedBuilding != null) {
BuildingLevelData data = BuildingIO.getBuildingData(
this.selectedBuilding.getType()).getLevelData(
this.selectedBuilding.getLevel());
if (this.buildingButtons[0][2].isHovered()) {
// The upgrade button is hovered : show the resources needed
showUpgradeCost(data.getUpgradeCost(), g,
this.buildingButtons[0][2]);
} else {
hideUpgradeLabels();
}
// Rendering of special building actions
if (data.getSpecialActions() != null) {
// There id some special action to show
int col = 0;
int row = 0;
for (String name : data.getSpecialActions()) {
final ColonyAction sa = SpecialActionManager.get(
GameData.getSelectedColony(), name);
ImageButton btn = this.buildingButtons[col][row];
btn.setImageRef(sa.getGfxKey());
btn.setActionHandler(new ActionHandler() {
@Override
public void run() {
if (ResourceHelper.enoughResourcesFor(sa
.getCostMap())) {
sa.setLinkedBuilding(SectorState.this.selectedBuilding);
final Colony cc = GameData.getSelectedColony();
for (Resource r : Resource.values()) {
BigDecimal d = sa.getCostMap().get(r);
if (d == null) {
continue;
}
cc.updateResource(r, d.negate());
}
GameData.getSelectedColony().addSpecialAction(
sa);
} else {
// TODO Play error sound
}
}
});
btn.show();
if (getSelectedBuildingAction() == null) {
btn.enable();
} else {
btn.disable();
}
if (btn.isHovered()) {
showUpgradeCost(sa.getCostMap(), g, btn);
}
col++;
if (col == 3) {
col = 0;
row++;
}
}
}
}
// Render the UIComponents
for (UIComponent comp : this.components) {
comp.render(g);
}
}
@Override
public void updateState(Input input, int time) throws SlickException {
this.mouseX = input.getMouseX();
this.mouseY = input.getMouseY();
this.squareXOnScreen = getHoveredSquareX(getMouseXOnMap(input
.getMouseX()));
this.squareYOnScreen = getHoveredSquareY(getMouseYOnMap(input
.getMouseY()));
this.squareXOnMap = getMouseXOnMap(this.squareXOnScreen)
/ Settings.TILE_SIZE;
this.squareYOnMap = getMouseYOnMap(this.squareYOnScreen)
/ Settings.TILE_SIZE;
// Map scroll update
handleScrollUpdate(input);
// Minimap update
this.minimap.update(input);
// Resource progress bars updates
Resource[] resources = Resource.values();
for (Resource r : resources) {
ProgressBar pb = this.resourceBars.get(r);
pb.update(input);
}
this.robotBar.update(input);
if (GameData.getSelectedColony().isCommandCenterBuilt()) {
SectorState.this.buildWindow.setCommandCenterBuilt(true);
} else {
if (GameData.getSelectedColony().isCommandCenterUnderConstruction()) {
this.developButton.enable();
}
if(selectedAction != null){
if(selectedAction instanceof BuildingAction){
BuildingAction ba = (BuildingAction) selectedAction;
if(!BuildingType.COMMAND_CENTER.equals(ba.getBuilding().getType())){
// The selected action is not a command center construction
selectedAction = null;
}
}else{
// The action is not allowed yet
selectedAction = null;
}
}
this.buildWindow.setCommandCenterBuilt(false);
}
this.buildWindow.update(input);
// Handle action drop
if (this.selectedAction != null) {
if (input.isMousePressed(Input.MOUSE_LEFT_BUTTON)
&& this.mouseY > TOP_BAR_HEIGHT
&& this.mouseY < Settings.HEIGHT - BOTTOM_BAR_HEIGHT) {
final int tileX = this.squareXOnMap;
final int tileY = this.squareYOnMap;
if (this.selectedAction instanceof PreparationAction) {
// Preparation action
PreparationAction pa = (PreparationAction) this.selectedAction;
boolean canBuild = false;
if (TileHelper.tileIsPreparable(tileX, tileY)) {
// Tile is OK
if (ResourceHelper
.enoughResourcesFor(SectorState.this.selectedAction
.getCostMap())) {
// Resources are OK
if (GameData.getSelectedColony()
.getAvailableRobots() > 0) {
canBuild = true;
}
}
}
if (canBuild) {
// Preparation can be done
pa.setX(tileX);
pa.setY(tileY);
Map<Resource, BigDecimal> map = pa.getCostMap();
for (Resource r : resources) {
if (map.get(r) == null) {
// No value defined for this resource
continue;
}
GameData.getSelectedColony().updateResource(r,
map.get(r).negate());
}
GameData.getSelectedColony().addPreparationAction(
pa.clone());
} else {
// TODO play an error sound
}
} else if (this.selectedAction instanceof BuildingAction) {
BuildingAction ba = (BuildingAction) this.selectedAction;
if (BuildingType.COMMAND_CENTER.equals(ba.getBuilding()
.getType())) {
// Command center construction is handled in a submethod
handleCommandCenterConstruction(ba, tileX, tileY);
} else if (TileHelper.tileIsBuildable(tileX, tileY, ba
.getBuilding().getType())) {
// Is there already a building there?
List<Building> buildings = GameData.getSelectedColony()
.getBuildings();
boolean canBuild = true;
for (Building b : buildings) {
if (b.getX() == tileX && b.getY() == tileY) {
// Oops, there is already a building here.
// Construction is impossible
canBuild = false;
break;
}
}
// No building, but is there a building under
// construction?
List<BuildingAction> bactions = GameData
.getSelectedColony().getBuildingActions();
for (BuildingAction cba : bactions) {
Building cb = cba.getBuilding();
if (cb.getX() == tileX && cb.getY() == tileY) {
// Construction is impossible
canBuild = false;
break;
}
}
if (!ResourceHelper
.enoughResourcesFor(SectorState.this.selectedAction
.getCostMap())) {
canBuild = false;
}
if (canBuild) {
ba.getBuilding().setX(tileX);
ba.getBuilding().setY(tileY);
final BuildingAction nba = ba.clone();
if (!BuildingType.ROAD.equals(nba.getBuilding()
.getType())) {
nba.setCallback(new Runnable() {
@Override
public void run() {
if (nba.getBuilding()
.equals(SectorState.this.selectedBuilding)) {
SectorState.this.selectBuilding(nba
.getBuilding());
}
}
});
}
GameData.getSelectedColony().addBuildingAction(nba);
// Remove from the stock the building cost
BuildingData data = BuildingIO.getBuildingData(nba
.getBuilding().getType());
Map<Resource, BigDecimal> map = data
.getLevelData(0).getUpgradeCost();
for (Resource r : resources) {
GameData.getSelectedColony().updateResource(r,
map.get(r).negate());
}
} else {
// TODO play an error sound
}
} else {
// Cannot build here
}
}
} else if (input.isMousePressed(Input.MOUSE_RIGHT_BUTTON)) {
// Right clic when a building action is selected = deselect
// building mode
this.selectedAction = null;
}
}
// Handle building selection
handleBuildingSelection(input);
// Building buttons
for (int col = 0; col < 3; col++) {
for (int row = 0; row < 3; row++) {
this.buildingButtons[col][row].update(input);
}
}
// Update the UIComponents
for (UIComponent comp : this.components) {
comp.update(input);
}
// Shortcuts handling
handleShortcuts(input);
//
if (GameData.getSelectedColony().isResearchCenterBuilt()) {
this.researchVisionButton.enable();
} else {
this.researchVisionButton.disable();
}
// If the Planet Exploration technology is researched, the Planet vision
// is enabled
if (GameData.getTechnologyMap().get("planet_exploration").isOwned()) {
this.planetVisionButton.enable();
} else {
this.planetVisionButton.disable();
}
// Game logic update
GameEngine.run(time);
}
private void handleShortcuts(Input input) {
// Defined shortcuts :
// - U : Upgrade the selected building
// - B : Open the building panel
// -
// -
// -
if (this.selectedBuilding != null) {
// Shortcut for building
if (input.isKeyPressed(Input.KEY_U)) {
// Upgrade wanted
upgradeBuilding(this.selectedBuilding);
}
}
if (!this.showActionWindow) {
if (input.isKeyPressed(Input.KEY_B)) {
showBuildWindow(true);
}
} else {
// Building window is shown : handle building shortcuts
if (input.isKeyPressed(Input.KEY_ESCAPE)) {
showBuildWindow(false);
} else {
// Building shortcuts are defined in buildings
for (BuildingType t : BuildingType.values()) {
if (t.getShortcut() != -1
&& input.isKeyPressed(t.getShortcut())) {
// Building selected
BuildingData data = BuildingIO.getBuildingData(t);
BuildingAction ba = BuildingHelper.createAction(
GameData.getSelectedColony(), t, data
.getLevelData(0).getUpgradeCost());
setSelectedAction(ba);
showBuildWindow(false);
break;
}
}
// May be a robot shortcut?
if (input.isKeyPressed(Input.KEY_A)) {
// Robot action
setSelectedAction(BuildingHelper.create(GameData
.getSelectedColony()));
showBuildWindow(false);
}
}
}
}
private void showBuildWindow(boolean show) {
this.showActionWindow = show;
if (show) {
this.buildWindow.show();
} else {
this.buildWindow.hide();
}
}
/**
* This method create the scroll zones. Those zones will be used in the
* update method in order to trigger the scrolls.
*/
private void initializeScrollZones() {
// Top zone
int x = -1;
int y = 0;
int width = Settings.WIDTH + 2;
int height = Settings.MAP_SCROLL_SENSITIVITY;
this.topScrollZone = new Rectangle(x, y, width, height);
// Bottom zone
x = -1;
y = Settings.HEIGHT - Settings.MAP_SCROLL_SENSITIVITY + 1;
width = Settings.WIDTH + 2;
height = Settings.MAP_SCROLL_SENSITIVITY + 1;
this.bottomScrollZone = new Rectangle(x, y, width, height);
// Left zone
x = -1;
y = 0;
width = Settings.MAP_SCROLL_SENSITIVITY;
height = Settings.HEIGHT + 2;
this.leftScrollZone = new Rectangle(x, y, width, height);
// Right zone
x = Settings.WIDTH - Settings.MAP_SCROLL_SENSITIVITY;
y = 0;
width = Settings.MAP_SCROLL_SENSITIVITY + 1;
height = Settings.HEIGHT + 2;
this.rightScrollZone = new Rectangle(x, y, width, height);
}
/**
* Handle the scroll on the map
*
* @param input
* the player input
*/
private void handleScrollUpdate(Input input) {
final int mouseX = input.getMouseX();
final int mouseY = input.getMouseY();
Colony c = GameData.getSelectedColony();
// Vertical scroll
if (this.topScrollZone.contains(mouseX, mouseY)) {
c.setViewportY(c.getViewportY() + Settings.MAP_SCROLL_SPEED);
} else if (this.bottomScrollZone.contains(mouseX, mouseY)) {
c.setViewportY(c.getViewportY() - Settings.MAP_SCROLL_SPEED);
}
// Horizontal scroll
if (this.leftScrollZone.contains(mouseX, mouseY)) {
c.setViewportX(c.getViewportX() + Settings.MAP_SCROLL_SPEED);
} else if (this.rightScrollZone.contains(mouseX, mouseY)) {
c.setViewportX(c.getViewportX() - Settings.MAP_SCROLL_SPEED);
}
}
/**
* Render the buildings on the map
*
* @param g
* the graphic canvas
* @throws SlickException
*/
private void renderBuildings(Graphics g) throws SlickException {
// Built constructions
List<Building> buildings = GameData.getSelectedColony().getBuildings();
for (Building b : buildings) {
Image gfx = null;
if (BuildingType.ROAD.equals(b.getType())) {
// Road are rendered according to the neighbors buildings
gfx = UIHelper.getRoadGfx(b);
gfx.draw(getScreenX(b.getX()), getScreenY(b.getY()));
} else {
gfx = ImageManager.getGfx(b.getType().toString());
gfx.draw(getScreenX(b.getX()), getScreenY(b.getY()));
if (b.equals(this.selectedBuilding)) {
highlightBuilding(g, b);
}
}
}
// Constructions in progress
List<BuildingAction> actions = GameData.getSelectedColony()
.getBuildingActions();
for (BuildingAction action : actions) {
Building b = action.getBuilding();
Image gfx = null;
if (BuildingType.ROAD.equals(b.getType())) {
// Road are rendered according to the neighbors buildings
gfx = UIHelper.getRoadGfx(b);
} else {
gfx = ImageManager.getGfx(b.getType().toString());
}
gfx.draw(getScreenX(b.getX()), getScreenY(b.getY()), new Color(
0.5F, 0.5F, 0.5F, 0.5F));
// Render the construction progress bar
int progress = action.getProgression();
int x = getScreenX(b.getX());
int y = getScreenY(b.getY());
int width = NumberHelper.ruleOf3(100, Settings.TILE_SIZE, progress);
if (action.isUpgrade()) {
// Update : yellow
g.setColor(Color.magenta);
} else {
// Creation : red
g.setColor(Color.red);
}
g.drawLine(x, y, x + width, y);
g.drawLine(x, y + 1, x + width, y + 1);
g.drawLine(x, y + 2, x + width, y + 2);
if (b.equals(this.selectedBuilding)) {
highlightBuilding(g, b);
}
}
// Robots
List<PreparationAction> robotActions = GameData.getSelectedColony()
.getPreparationActions();
for (PreparationAction a : robotActions) {
Image gfx = ImageManager.getGfx(a.getGfxKey());
gfx.draw(getScreenX(a.getX()), getScreenY(a.getY()));
// Render the construction progress bar
int progress = a.getProgression();
int x = getScreenX(a.getX());
int y = getScreenY(a.getY());
int width = NumberHelper.ruleOf3(100, Settings.TILE_SIZE, progress);
g.setColor(Color.red);
g.drawLine(x, y, x + width, y);
g.drawLine(x, y + 1, x + width, y + 1);
g.drawLine(x, y + 2, x + width, y + 2);
}
}
/**
* Transform a screen coordinate to a map coordinate
*
* @param mouseXOnScreen
* The X coordinate of the mouse on the screen
* @return the X coordinate of the mouse on the map
*/
private int getMouseXOnMap(int mouseXOnScreen) {
return -GameData.getSelectedColony().getViewportX() + mouseXOnScreen;
}
/**
* Transform a screen coordinate to a map coordinate
*
* @param mouseYOnScreen
* The Y coordinate of the mouse on the screen
* @return the Y coordinate of the mouse on the map
*/
private int getMouseYOnMap(int mouseYOnScreen) {
return -GameData.getSelectedColony().getViewportY() + mouseYOnScreen;
}
/**
* Take a coordinate from the map and convert it to screen coordinate
*
* @param mapX
* the X coordinate
* @return the screen X coordinate
*/
private int getScreenX(int mapX) {
return mapX * Settings.TILE_SIZE
+ GameData.getSelectedColony().getViewportX();
}
/**
* Take a coordinate from the map and convert it to screen coordinate
*
* @param mapY
* the Y coordinate
* @return the screen Y coordinate
*/
private int getScreenY(int mapY) {
return mapY * Settings.TILE_SIZE
+ GameData.getSelectedColony().getViewportY();
}
/**
* Render a highligh on the given building
*
* @param g
* The graphic canvas
* @param b
* The building to highlight
*/
private void highlightBuilding(Graphics g, Building b) {
final int tileSize = Settings.TILE_SIZE - 1;
g.setColor(Color.red);
g.drawRect(getScreenX(b.getX()), getScreenY(b.getY()), tileSize,
tileSize);
}
/**
* Render robots currently preparing the ground
*
* @param g
* the graphic canvas
* @throws SlickException
*/
private void renderRobots(Graphics g) throws SlickException {
List<PreparationAction> actions = GameData.getSelectedColony()
.getPreparationActions();
for (PreparationAction a : actions) {
Image gfx = ImageManager.getGfx("terrabot");
gfx.draw(getScreenX(a.getX()), getScreenY(a.getY()));
}
}
/**
* This method handles resource rendering. For each resource, a progress bar
* will be rendered representing the store space used. The last modifier
* applyed on the resource will also be rendered
*
* @param g
* the graphic canvas
* @param ox
* the x origin for the render of this area
* @param oy
* the y origin for the render of this area
* @throws SlickException
*/
private void renderProgressBars(Graphics g, int ox, int oy)
throws SlickException {
final int padding = 3;
int pitch = 106 + 24;
int x = ox;
BigDecimal inStore;
BigDecimal max;
StringBuilder builder = new StringBuilder();
Resource[] resources = Resource.values();
ProgressBar pb;
Map<Resource, BigDecimal> modifiers = GameData.getSelectedColony()
.getLastModifiers();
BigDecimal modifier;
// Progress bar of robots use
UIHelper.drawDarkBox(g, x + padding, oy + padding, 24, 20);
Image img = ImageManager.getGfx("robot-small");
img.draw(x + padding + 2, oy + padding);
BigDecimal maxVal = BigDecimal.valueOf(GameData.getSelectedColony()
.getTotalRobots());
BigDecimal curVal = BigDecimal.valueOf(GameData.getSelectedColony()
.getAvailableRobots());
this.robotBar.setMaxValue(maxVal);
this.robotBar.setValue(curVal);
this.robotBar.setX(x + padding + 24);
this.robotBar.setY(oy + padding);
this.robotBar.render(g);
// Rendering values
// builder.setLength(0);
// builder.append(curVal).append("/").append(maxVal);
// font.drawString(x + padding, oy + 22, builder.toString());
final int padd = 18;
// Rendering of the rows titles
int y = oy + 25;
this.storeTitle.setPosition(x, y);
y += padd;
this.modifierTitle.setPosition(x, y);
y += padd;
this.availableSpaceTitle.setPosition(x, y);
y += padd;
this.maxStoreTitle.setPosition(x, y);
x += pitch;
for (Resource r : resources) {
// Retreiving data
inStore = GameData.getSelectedColony().getResource(r);
max = GameData.getSelectedColony().getStorSpace(r);
final int availableSpace = max.subtract(inStore).intValue();
UIHelper.drawDarkBox(g, x + padding, oy + padding, 24, 20);
img = ImageManager.getGfx(r.getGfxBase() + "-small");
img.draw(x + padding + 2, oy + padding);
// Creating and rendering the progress bar
pb = this.resourceBars.get(r);
pb.setX(x + padding + 24);
pb.setY(oy + padding);
pb.setMaxValue(max);
pb.setValue(inStore);
pb.render(g);
// Rendering the resource amount, max and modifier
if (this.extendedResourceDisplay) {
y = oy + 25;
// Currently in store
String temp = inStore.setScale(0, BigDecimal.ROUND_FLOOR)
.toString();
Label current = this.inStoreLabels.get(r);
drawResourceData(g, x + padding, y + 2, temp, current);
y += padd;
// Modifiers
builder.setLength(0);
modifier = modifiers.get(r);
if (modifier.signum() == -1) {
// Negative value
builder.append("-");
} else if (modifier.signum() == 1) {
// Positive value
builder.append("+");
}
builder.append(modifier);
Label modifierLabel = this.modifiersLabels.get(r);
drawResourceData(g, x + padding, y + 2, modifier.toString(),
modifierLabel);
y += padd;
// Available space
Label availableLabel = this.availableSpaceLabels.get(r);
drawResourceData(g, x + padding, y + 2,
String.valueOf(availableSpace), availableLabel);
y += padd;
// Max
temp = max.toString();
Label maxLabel = this.maxStoreLabels.get(r);
drawResourceData(g, x + padding, y + 2, temp, maxLabel);
}
x += pitch;
}
}
/**
* Draws the black box behind resources values and move the label at the
* right position
*
* @param g
* The graphic canvas
* @param x
* The X coordinate
* @param y
* The Y coordinate
* @param value
* The string representation of the resource value
* @param label
* The label
* @throws SlickException
*/
private void drawResourceData(Graphics g, int x, int y, String value,
Label label) throws SlickException {
final int zoneHeight = 15;
UIHelper.drawDarkBox(g, x, y, label.getWidth() + 4, zoneHeight);
label.setPosition(x, y);
label.setText(value);
label.setVisible(true);
}
/**
*
* @param action
*/
public void setSelectedAction(MapAction action) {
this.selectedAction = action;
showBuildWindow(false);
}
/**
* According to the last mouse position on screen, get the X coordinate of
* the hovered square on the map
*
* @param mouseXOnMap
* X coordinate of the mouse on the map
* @return X coordinate of the hovered square on the map
*/
private int getHoveredSquareX(int mouseXOnMap) {
return mouseXOnMap - (mouseXOnMap % 32)
+ GameData.getSelectedColony().getViewportX();
}
/**
* According to the last mouse position on screen, get the Y coordinate of
* the hovered square on the map
*
* @param mouseYOnMap
* Y coordinate of the mouse on the map
* @return Y coordinate of the hovered square on the map
*/
private int getHoveredSquareY(int mouseYOnMap) {
return mouseYOnMap - (mouseYOnMap % 32)
+ GameData.getSelectedColony().getViewportY();
}
/**
* Handle the building selected area with the proper data
*
* @param input
* The player input
*/
private void handleBuildingSelection(Input input) {
// Handle the building selection on the map only if the mouse is on the
// viewport
Rectangle zone = new Rectangle(0, TOP_BAR_HEIGHT, Settings.WIDTH,
Settings.HEIGHT - TOP_BAR_HEIGHT - BOTTOM_BAR_HEIGHT);
if (input.isMousePressed(Input.MOUSE_LEFT_BUTTON)
&& zone.contains(this.mouseX, this.mouseY)) {
selectBuilding(GameData.getSelectedColony().getBuildingAt(
this.squareXOnMap, this.squareYOnMap));
if (this.selectedBuilding != null) {
if (BuildingType.ROAD.equals(this.selectedBuilding.getType())) {
// For now, road are not selectable.
// TODO Handle selectable buildings properly
selectBuilding(null);
} else {
// The center button must be updated with the building gfx
// this.buildCenterButton.setImageRef(this.selectedBuilding
// .getType().toString());
// this.buildCenterButton
// .setActionHandler(new ActionHandler() {
//
// @Override
// public void run() {
// Move the viewport to the building
// centerVieportOn(
// PlayState.this.selectedBuilding
// .getX()
// * Settings.TILE_SIZE,
// PlayState.this.selectedBuilding
// .getY()
// * Settings.TILE_SIZE);
// }
// });
}
}
}
}
/**
* Render the selected building's attributes
*
* @param g
* The graphic canvas
* @throws SlickException
*/
private void renderBuildingAttributes(Graphics g) throws SlickException {
final int ox = 150 + PADDING * 2;
final int oy = Settings.HEIGHT - 116 - PADDING;
// Building stats
final int pitchX = 88;
final int pitchY = 22;
final int startX = ox + PADDING;
int x = ox + pitchX;
int y = oy;
// Columns labels
for (int col = 0; col < 3; col++) {
Label lbl = this.buildingColLabels[col];
lbl.setVisible(true);
lbl.setPosition(x, y);
x += pitchX;
}
y += 25;
x = startX;
BuildingData data = BuildingIO.getBuildingData(this.selectedBuilding
.getType());
BuildingLevelData levelData = data.getLevelData(this.selectedBuilding
.getLevel());
Map<Resource, BigDecimal> prod = levelData.getProduction();
Map<Resource, BigDecimal> cons = levelData.getConsumption();
Map<Resource, BigDecimal> store = levelData.getStoreCapacity();
Resource[] resources = Resource.values();
for (Resource r : resources) {
// TODO Row label
Label rowLabel = this.buildingRowLabels.get(r);
rowLabel.setVisible(true);
rowLabel.setPosition(x, y);
x += pitchX;
// Production
Label prodLabel = this.buildingProdLabels.get(r);
String prodValue = prod.get(r).toString();
drawResourceData(g, x, y, prodValue, prodLabel);
// Consumption
Label consLabel = this.buildingConsLabels.get(r);
String consValue = cons.get(r).toString();
drawResourceData(g, x += pitchX, y, consValue, consLabel);
// Store provided
Label storeLabel = this.buildingStoreLabels.get(r);
String storeValue = store.get(r).toString();
drawResourceData(g, x += pitchX, y, storeValue, storeLabel);
y += pitchY;
x = startX;
}
}
/**
* Render the building overview
*
* @param g
* The graphic canvas
* @throws SlickException
*/
private void renderBuildingOverview(Graphics g) throws SlickException {
final int ox = 150 + PADDING * 2 + 368 + PADDING;
final int oy = Settings.HEIGHT - Minimap.HEIGHT.intValue() - PADDING;
UIHelper.drawDarkBox(g, ox + PADDING, oy + PADDING * 2 + 32, 33, 33);
Image gfx = ImageManager.getGfx(this.selectedBuilding.getType()
.toString().toLowerCase());
gfx.draw(ox + PADDING + 1, oy + PADDING * 2 + 32);
// Building name
Font fontBig = FontHelper
.getFont(FontHelper.HEMI_HEAD, Color.white, 30);
Font fontNormal = FontHelper.getFont(FontHelper.HEMI_HEAD, Color.white,
20);
int x = ox + PADDING * 2 + 32;
int y = oy + PADDING * 2;
fontBig.drawString(x - 40, y, FontHelper.firstToUpper(I18n
.get(this.selectedBuilding.getI18n())));
// Building level
String temp = I18n.get("global.level") + " : "
+ this.selectedBuilding.getLevel();
fontNormal.drawString(x, y += 40, FontHelper.firstToUpper(temp));
// Current action
String title = null;
BigDecimal maxValue = null;
BigDecimal value = null;
DelayedAction a = getSelectedBuildingAction();
this.selectedBuildingPB.setFilledColor(Color.red);
if (a instanceof BuildingAction) {
BuildingAction ba = (BuildingAction) a;
if (ba.isUpgrade()) {
// Upgrade process
title = FontHelper.firstToUpper(I18n.get("global.upgrading"))
+ "...";
this.selectedBuildingPB.setFilledColor(Color.magenta);
} else if (!ba.isUpgrade()) {
// Building process
title = FontHelper.firstToUpper(I18n.get("global.building"))
+ "...";
}
maxValue = BigDecimal.valueOf(ba.getDuration());
value = BigDecimal.valueOf(ba.getCurrentValue());
} else if (a instanceof ColonyAction) {
ColonyAction sa = (ColonyAction) a;
title = FontHelper.firstToUpper(I18n.get(sa.getI18nKey())) + "...";
this.selectedBuildingPB.setFilledColor(Color.red);
maxValue = BigDecimal.valueOf(sa.getDuration());
value = BigDecimal.valueOf(sa.getCurrentValue());
}
if (a != null) {
fontNormal.drawString(x, y += 35, title);
// Action progress
this.selectedBuildingPB.setMaxValue(maxValue);
this.selectedBuildingPB.setValue(value);
this.selectedBuildingPB.setOX(x);
this.selectedBuildingPB.setOY(y += 20);
this.selectedBuildingPB.render(g);
}
}
/**
* Select a building. By selecting a building (or unselecting one), the
* attributes labels will be shown or hidden
*
* @param b
* The building to select or null
*/
private void selectBuilding(Building b) {
// Manage buttons visibility
// Default buttons :
// - Upgrade [0,2]
// - Destroy [1,2]
// - Cancel [2,2]
// All buttons are hidden and disabled first, then, only useful buttons
// are shown
for (int col = 0; col < 3; col++) {
for (int row = 0; row < 3; row++) {
this.buildingButtons[col][row].hide();
this.buildingButtons[col][row].disable();
}
}
this.selectedBuilding = b;
if (b == null) {
// No building selected : hide buttons and labels
Resource[] resources = Resource.values();
for (Resource r : resources) {
this.buildingConsLabels.get(r).setVisible(false);
this.buildingProdLabels.get(r).setVisible(false);
this.buildingStoreLabels.get(r).setVisible(false);
this.buildingRowLabels.get(r).setVisible(false);
}
for (int i = 0; i < 3; i++) {
this.buildingColLabels[i].setVisible(false);
}
return;
}
final boolean actionOngoing = this.getSelectedBuildingAction() != null;
// Show useful buttons
// Upgrade button is shown if there is another level for the building
BuildingData data = BuildingIO.getBuildingData(this.selectedBuilding
.getType());
BuildingLevelData nextLevel = data.getLevelData(this.selectedBuilding
.getLevel() + 1);
if (nextLevel != null) {
// There is a level
this.buildingButtons[0][2].show();
// Is it OK with technologies?
if (TechnologyHelper.technologiesAreOwned(nextLevel
.getTechnologiesNeeded())) {
// OK but... Is there an action ongoing?
if (!actionOngoing) {
this.buildingButtons[0][2].enable();
}
}
} else {
// No more level : button stay hidden
}
// Cancel button is always shown but only enabled if an action is
// currently being done
this.buildingButtons[2][2].show();
if (actionOngoing) {
// There is an action to stop : enable the cancel button
this.buildingButtons[2][2].enable();
}
}
/**
* Stops the selected building action
*/
private void stopSelectedBuildingAction() {
DelayedAction a = getSelectedBuildingAction();
// Robot release
GameData.getSelectedColony().releaseRobots(a.getRobotsUsed());
// Deletion of the action in the GameData
if (a instanceof BuildingAction) {
BuildingAction ba = (BuildingAction) a;
GameData.getSelectedColony().getBuildingActions().remove(ba);
// If the action was a building then unselect the building
if (ba.getBuilding().isUnderConstruction()) {
// Call to selectBuilding method to handle buttons state
// properly
this.selectBuilding(null);
// TODO Play destruction sound
} else {
// Call to selectBuilding method to handle buttons state
// properly
this.selectBuilding(this.selectedBuilding);
}
}
}
/**
* @return the action currently done by the building
*/
private DelayedAction getSelectedBuildingAction() {
// Searching for building or upgrading action...
List<BuildingAction> baList = GameData.getSelectedColony()
.getBuildingActions();
for (BuildingAction ba : baList) {
if (ba.getBuilding().equals(this.selectedBuilding)) {
return ba;
}
}
// Searching for special action
List<ColonyAction> saList = GameData.getSelectedColony()
.getSpecialActions();
for (ColonyAction sa : saList) {
if (sa.getLinkedBuilding() != null
&& sa.getLinkedBuilding().equals(this.selectedBuilding)) {
return sa;
}
}
return null;
}
/**
* Upgrade a building to it's next level. Checks resources first and then
* lunch an upgrade action
*
* @param b
* the building to upgrade
*/
private void upgradeBuilding(final Building b) {
// Check resources
BuildingLevelData levelData = BuildingIO.getBuildingData(b.getType())
.getLevelData(b.getLevel());
Map<Resource, BigDecimal> costMap = levelData.getUpgradeCost();
// Enough resources ?
if (ResourceHelper.enoughResourcesFor(costMap)) {
Resource[] resources = Resource.values();
for (Resource r : resources) {
if (costMap.get(r) == null) {
// No value defined for this resource
continue;
}
GameData.getSelectedColony().updateResource(r,
costMap.get(r).negate());
}
// Enough robots?
if (GameData.getSelectedColony().getAvailableRobots() == 0) {
// TODO Play error sound
return;
}
// Create the action
int duration = 5; // TODO extract into building config file
BuildingAction ba = new BuildingAction(
GameData.getSelectedColony(), costMap, b, duration, 1, true);
ba.setCallback(new Runnable() {
@Override
public void run() {
if (b.equals(SectorState.this.selectedBuilding)) {
SectorState.this.selectBuilding(b);
}
}
});
GameData.getSelectedColony().addBuildingAction(ba);
// Call to selectBuilding method to handle buttons state properly
selectBuilding(b);
} else {
// TODO Play error sound
}
}
/**
* Render a window with upgrade informations
*
* @param costMap
* The cost map of the upgrade
* @param g
* The graphic canvas
* @throws SlickException
*/
protected void showUpgradeCost(Map<Resource, BigDecimal> costMap,
Graphics g, ImageButton btn) throws SlickException {
// Draw the BG
final int width = 120;
final int height = 101;
final int box = btn.getOX();
final int boy = btn.getOY();
int x = box + btn.getWidth() / 2 - width / 2;
int y = Settings.HEIGHT - BOTTOM_BAR_HEIGHT - height;
UIHelper.drawBox(g, x, y, width, height);
UIHelper.drawDarkBox(g, x += 3, y += 3, width - 6, height - 6);
Resource[] resources = Resource.values();
Image img;
x += 3;
for (Resource r : resources) {
UIHelper.drawDarkBox(g, x, y += 3, 24, 20);
img = ImageManager.getGfx(r.getGfxBase() + "-small");
img.draw(x + 3, y, r.getColor());
String value = costMap.get(r).toString();
Label lbl = this.upgradeLabels.get(r);
drawResourceData(g, x + 24, y, value, lbl);
y += 20;
}
}
/**
* Hide the labels in the upgrade overview window
*/
private void hideUpgradeLabels() {
// Hide the labels
Resource[] resources = Resource.values();
for (Resource r : resources) {
this.upgradeLabels.get(r).setVisible(false);
}
}
private void handleCommandCenterConstruction(BuildingAction ba,
final int tileX, final int tileY) {
// If there is already a command center under construction, no mode
// build action is handled (prevents from creating more than one command
// center)
if (GameData.getSelectedColony().isCommandCenterBuilt()) {
return;
}
List<BuildingAction> actions = GameData.getSelectedColony()
.getBuildingActions();
for (BuildingAction a : actions) {
if (BuildingType.COMMAND_CENTER.equals(a.getBuilding().getType())) {
// There is already a command center under construction
return;
}
}
TiledMap map = GameData.getSelectedColony().getMap();
final int mapWidth = map.getWidth();
final int mapHeight = map.getHeight();
if (!TileHelper.isValidCommandCenterTile(tileX, tileY)) {
// TODO Play error sound
// The zone is not correct for Command Center construction.
return;
}
ba.getBuilding().setX(tileX);
ba.getBuilding().setY(tileY);
final BuildingAction nba = ba.clone();
final Colony c = GameData.getSelectedColony();
nba.setCallback(new Runnable() {
@Override
public void run() {
BuildingHelper.createCMConstructionCallback(tileX, tileY, c);
}
});
TileHelper.setTile(tileX, tileY, TileHelper.BUILDABLE_TILE,
GameData.getSelectedColony());
c.addBuildingAction(nba);
// Construction is disabled until command center is fully built
this.developButton.disable();
// By the way the Command Center is unselected automatically when built
this.selectedAction = null;
GameData.getSelectedColony().setCommandCenterUnderConstruction(true);
}
@Override
protected void renderTopZone(Graphics g) throws SlickException {
int width = TOP_BAR_WIDTH + TOGGLE_BUTTON_ZONE_WIDTH;
int height;
if (this.extendedResourceDisplay) {
height = 100;
} else {
height = 26;
}
int x = Settings.WIDTH / 2 - width / 2;
int y = PADDING;
UIHelper.drawWindow(g, x - 10, y - 10, width + 20, height + 20, 5);
// UIHelper.drawBlackBox(g, x, y, width, height);
renderProgressBars(g, x + TOGGLE_BUTTON_ZONE_WIDTH, y);
// Render the colony name
UIHelper.drawWindow(g, Settings.WIDTH - 140, 0, 140, 46, 5);
Font font = FontHelper.getFont(FontHelper.HEMI_HEAD, Color.white, 20);
font.drawString(Settings.WIDTH - 130, 15, GameData.getSelectedColony()
.getName());
}
}