BuildingMenu.java
package io.github.unisim.ui;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.Align;
import io.github.unisim.GameLogic;
import io.github.unisim.GlobalState;
import io.github.unisim.Point;
import io.github.unisim.building.Building;
import io.github.unisim.building.BuildingType;
import io.github.unisim.world.World;
import java.util.ArrayList;
import java.util.List;
/**
* Menu used to place buildings in the world by clicking and dragging them
* from the list onto the map.
*/
@SuppressWarnings({"MemberName", "AbbreviationAsWordInName"})
public class BuildingMenu {
private final World world;
private final GameLogic gameLogic;
private final ShapeActor bar = new ShapeActor(GlobalState.UISecondaryColour);
private final Table table;
private final List<Building> buildings = new ArrayList<>();
private final List<Image> buildingImages = new ArrayList<>();
private final Label buildingInfoLabel = new Label(
"", new Skin(Gdx.files.internal("ui/uiskin.json"))
);
private final Table buildingInfoTable = new Table();
/**
* Create a Building Menu and attach its actors and components to the provided stage.
* Also handles drawing buildings and their flipped variants
*
* @param stage - The stage on which to draw the menu.
*/
public BuildingMenu(Stage stage, World world, GameLogic gameLogic) {
this.world = world;
this.gameLogic = gameLogic;
// Set building images and sizes
buildings.add(new Building(
new Texture(Gdx.files.internal("buildings/restaurant.png")),
0.005f,
new Vector2(1.1f, -0.2f),
new Point(),
new Point(6, 6),
false,
BuildingType.EATING,
"Canteen",
15000,
0
));
buildings.add(new Building(
new Texture(Gdx.files.internal("buildings/library.png")),
0.0075f,
new Vector2(1.8f, -4.6f),
new Point(),
new Point(20, 12),
false,
BuildingType.LEARNING,
"Library",
30000,
0
));
buildings.add(new Building(
new Texture(Gdx.files.internal("buildings/basketballCourt.png")),
0.0025f,
new Vector2(1f, -2.4f),
new Point(),
new Point(6, 9),
false,
BuildingType.RECREATION,
"Basketball Court",
10000,
0
));
buildings.add(new Building(
new Texture(Gdx.files.internal("buildings/studentHousing.png")),
0.108f,
new Vector2(1.4f, -2.8f),
new Point(),
new Point(11, 11),
false,
BuildingType.SLEEPING,
"Student Accommodation",
12500,
0
));
buildings.add(new Building(
new Texture(Gdx.files.internal("buildings/club.png")),
0.005f,
new Vector2(0.5f, 1.25f),
new Point(),
new Point(10, 10),
false,
BuildingType.RECREATION,
"Club",
15000,
25000
));
table = new Table();
// Add buldings to the table
for (int i = 0; i < buildings.size(); i++) {
buildingImages.add(new Image(buildings.get(i).texture));
final int buildingIndex = i;
buildingImages.get(i).addListener(new ClickListener() {
@Override
public void clicked(InputEvent e, float x, float y) {
if (world.selectedBuilding == buildings.get(buildingIndex)) {
world.selectedBuilding = null;
} else {
world.selectedBuilding = buildings.get(buildingIndex);
int buildingPrice = gameLogic.getBuildingPrice(world.selectedBuilding);
buildingInfoLabel.setText(String.format("%s (£%d) - Press 'R' to rotate",
world.selectedBuilding.name,
buildingPrice));
if (world.selectedBuilding.flipped) {
world.selectedBuilding.flipped = false;
int temp = world.selectedBuilding.size.x;
world.selectedBuilding.size.x = world.selectedBuilding.size.y;
world.selectedBuilding.size.y = temp;
world.selectedBuildingUpdated = true;
}
}
}
});
table.add(buildingImages.get(i));
}
buildingInfoTable.add(buildingInfoLabel).expandX().align(Align.center);
stage.addActor(bar);
stage.addActor(table);
stage.addActor(buildingInfoTable);
}
/**
* Called when the window is resized, scales the building menu images with the window size.
*
* @param width - The new width of the window in pixels
* @param height - The new height of the window in pixels
*/
@SuppressWarnings("unchecked")
public void resize(int width, int height) {
table.setBounds(0, 0, width, height * 0.1f);
bar.setBounds(0, 0, width, height * 0.1f);
buildingInfoTable.setBounds(0, height * 0.1f, width, height * 0.025f);
// we must perform an unchecked type conversion here
// this is acceptable as we know our table only contains instances of Actors
for (Cell<Actor> cell : table.getCells()) {
Image buildingImage = (Image) (cell.getActor());
Vector2 textureSize = new Vector2(buildingImage.getWidth(), buildingImage.getHeight());
cell.width(
height * 0.1f * (textureSize.x < textureSize.y ? textureSize.x / textureSize.y : 1)
).height(
height * 0.1f * (textureSize.y < textureSize.x ? textureSize.y / textureSize.x : 1)
);
}
buildingInfoLabel.setFontScale(height * 0.0015f);
}
/**
* Called when the building menu needs to be redrawn with new values in the labels.
*/
public void update() {
if (world.selectedBuilding == null) {
buildingInfoLabel.setText("");
}
}
}