package settlers.ui;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import settlers.game.SettlerGame;
import settlers.game.DefaultGameEnums.BuildingTypes;
import settlers.game.DefaultGameEnums.TileTypes;
import settlers.game.data.MapCoord;
import settlers.game.data.SettlerGameData;
import settlers.game.map.SettlerMap;
import settlers.ui.themes.SettlersTheme;
@SuppressWarnings("serial")
public class MapArea extends Component implements MouseMotionListener {
BufferedImage tileMapImage = new BufferedImage(1, 1,
BufferedImage.TYPE_INT_ARGB);
BufferedImage mapObjectsImage = new BufferedImage(1, 1,
BufferedImage.TYPE_INT_ARGB);
BufferedImage resourcesImage = new BufferedImage(1, 1,
BufferedImage.TYPE_INT_ARGB);
BufferedImage playerInfo = new BufferedImage(1, 1,
BufferedImage.TYPE_INT_ARGB);
public SettlersTheme theme;
public MapCoord[] storage;
int[] mapScreenOrigin = { 40, 15 };
int[] mapObjectsScreenOrigin = { 30, 5 };
Point lastPoint;
SettlerGame game = new SettlerGame();
BlockingQueue<String> gameCommandQueue = new LinkedBlockingQueue<String>();
BuildMenu buildMenuPopup;
MapArea(SettlersTheme theme) {
this.theme = theme;
//addMouseListener(this);
//addMouseMotionListener(this);
buildMenuPopup = new BuildMenu();
buildMenuPopup.menuItems[0].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
(new Thread(new AddCommand("build settlement "
+ Arrays.deepToString(storage)))).start();
}
});
buildMenuPopup.menuItems[1].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
(new Thread(new AddCommand("build city "
+ Arrays.deepToString(storage)))).start();
}
});
buildMenuPopup.menuItems[2].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
(new Thread(new AddCommand("build road "
+ Arrays.deepToString(storage)))).start();
}
});
drawPlayerInfo();
repaint();
}
public void updateMapObjects(SettlerGameData data) {
mapObjectsImage = drawMapObjects(data, theme);
}
public static BufferedImage drawMapObjects(SettlerGameData data,
SettlersTheme theme) {
// TODO calculate the height and width
BufferedImage tempMapObjectImages = new BufferedImage(400, 400,
BufferedImage.TYPE_INT_ARGB);
Graphics g = tempMapObjectImages.createGraphics();
int yOffset = 0, xOffset = 0;
for (int i = 0; i < data.mapObjects.size(); i++) {
// TODO all drawing code using more than two input MapCoord(s) is
// broken if the MapCoord(s) are out of order
switch (data.mapObjects.get(i).getType()) {
case THIEF:
g
.drawImage(
theme.getMapObjectImage(BuildingTypes.THIEF),
(data.mapObjects.get(i).location[0].getX())
* theme.X_TILE_OFFSET + 36,
(data.mapObjects.get(i).location[0].getY())
* theme.Y_TILE_OFFSET
+ (SettlerMap
.isPartofDownRow(
data.map.isOriginDown,
data.mapObjects.get(i).location[0]
.getX()) ? 33
: 0) + 31, null);
break;
case ROAD: // builds roads
if (SettlerMap.tilesVeticallyAdjacent(data.map.isOriginDown,
data.mapObjects.get(i).location[0], data.mapObjects
.get(i).location[1])) {
// Checks if road is Horizontal
if (SettlerMap.isPartofDownRow(data.map.isOriginDown,
data.mapObjects.get(i).location[0].getX()))
// checks if it is down row
yOffset = 106;
else
yOffset = 73;// modifies placement
g.drawImage(theme.getRoad(1, 1),
(data.mapObjects.get(i).location[0].getX())
* theme.X_TILE_OFFSET + 30,
(data.mapObjects.get(i).location[0].getY())
* theme.Y_TILE_OFFSET + yOffset, null);
} else if (SettlerMap.tilesDiagonalLeft(data.map.isOriginDown,
data.mapObjects.get(i).location[0], data.mapObjects
.get(i).location[1])) {
// checks if diagonally left
if (SettlerMap.isPartofDownRow(data.map.isOriginDown,
data.mapObjects.get(i).location[0].getX()))
// checks if it is down row
yOffset = 76;
else
yOffset = 43;// modifies placement
g
.drawImage(theme.getRoad(1, 0),
(data.mapObjects.get(i).location[0].getX())
* theme.X_TILE_OFFSET
+ theme.X_TILE_OFFSET + 10,
(data.mapObjects.get(i).location[0].getY())
* theme.Y_TILE_OFFSET + yOffset,
null);
// Draws diagonally left road
} else if (SettlerMap.tilesDiagonalRight(data.map.isOriginDown,
data.mapObjects.get(i).location[0], data.mapObjects
.get(i).location[1])) {
// checks if diagonally right
if (SettlerMap.isPartofDownRow(data.map.isOriginDown,
data.mapObjects.get(i).location[0].getX())) {
// checks if it is down row
yOffset = 43;
} else {
yOffset = 11;// modifies placement
}
g
.drawImage(theme.getRoad(1, 2),
(data.mapObjects.get(i).location[0].getX())
* theme.X_TILE_OFFSET
+ theme.X_TILE_OFFSET + 9,
(data.mapObjects.get(i).location[0].getY())
* theme.Y_TILE_OFFSET + yOffset,
null);
// Draws Diagonal Right Road
}
break;
case SETTLEMENT:
if (SettlerMap.tilesRightFacing(data.map.isOriginDown,
data.mapObjects.get(i).location[0], data.mapObjects
.get(i).location[1],
data.mapObjects.get(i).location[2])) {
// checks if it is point right
if (SettlerMap.isPartofDownRow(data.map.isOriginDown,
data.mapObjects.get(i).location[0].getX())) {
// checks if it is down row
xOffset = 59;
yOffset = 99;// modifies placement
} else {
xOffset = 59;
yOffset = 68;// modifies placement
}
} else {
if (SettlerMap.isPartofDownRow(data.map.isOriginDown,
data.mapObjects.get(i).location[0].getX())) {
// checks if it is down row
xOffset = 76;
yOffset = 67;// modifies placement
} else {
xOffset = 76;
yOffset = 34;// modifies placement
}
}
g.drawImage(theme.getMapObjectImage(BuildingTypes.SETTLEMENT),
(data.mapObjects.get(i).location[0].getX())
* theme.X_TILE_OFFSET + xOffset,
(data.mapObjects.get(i).location[0].getY())
* theme.Y_TILE_OFFSET + yOffset, null);
// Draws the settlement
break;
case CITY:
if (SettlerMap.tilesRightFacing(data.map.isOriginDown,
data.mapObjects.get(i).location[0], data.mapObjects
.get(i).location[1],
data.mapObjects.get(i).location[2])) {
// checks if it is point right
if (SettlerMap.isPartofDownRow(data.map.isOriginDown,
data.mapObjects.get(i).location[0].getX())) {
// checks if it is down row
xOffset = 57;
yOffset = 100;// modifies placement
} else {
xOffset = 59;
yOffset = 68;// modifies placement
}
} else {
if (SettlerMap.isPartofDownRow(data.map.isOriginDown,
data.mapObjects.get(i).location[0].getX())) {
// checks if it is down row
xOffset = 75;
yOffset = 68;// modifies placement
} else {
xOffset = 75;
yOffset = 32;// modifies placement
}
}
g.drawImage(theme.getMapObjectImage(BuildingTypes.CITY),
(data.mapObjects.get(i).location[0].getX())
* theme.X_TILE_OFFSET + xOffset,
(data.mapObjects.get(i).location[0].getY())
* theme.Y_TILE_OFFSET + yOffset, null); //draws the city
}
}
return tempMapObjectImages;
}
public void updateResources(Map<TileTypes, Integer> resources) {
if (resources != null) {
resourcesImage = MapArea.drawResourceDock(resources, theme);
} else {
resourcesImage = new BufferedImage(1, 1,
BufferedImage.TYPE_INT_ARGB);
}
repaint();
}
private BufferedImage drawPlayerInfo(){
Graphics g = playerInfo.createGraphics();
g.setFont(new Font("sans-serif", Font.BOLD, 50));
g.setColor(Color.BLACK);
g.drawString("BILL!", 0, 0);
return playerInfo;
}
private static BufferedImage drawResourceDock(
Map<TileTypes, Integer> resources, SettlersTheme theme) {
BufferedImage resourcesImage = new BufferedImage(theme.getResourceIcon(
TileTypes.BRICK).getWidth() * 5, theme.getResourceIcon(
TileTypes.BRICK).getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics g = resourcesImage.createGraphics();
// TODO move font to theme
g.setFont(new Font("sans-serif", Font.BOLD, 15));
g.setColor(Color.BLACK);
int xOffset = 0;
for (TileTypes tileType : TileTypes.values()) {
if (tileType.isResource()) {
g.drawImage(theme.getResourceIcon(tileType), xOffset, 0, null);
if (resources.containsKey(tileType)) {
// TODO fix integer to string hack
g
.drawString("" + resources.get(tileType),
xOffset + 10, 15);
}
xOffset += theme.getResourceIcon(tileType).getWidth();
}
}
return resourcesImage;
}
@Override
public void paint(Graphics g) {
g.drawImage(theme.getMapBackground(), mapScreenOrigin[0] - 36,
mapScreenOrigin[1] - 21, null);
// draw the background image
g.drawImage(tileMapImage, mapScreenOrigin[0], mapScreenOrigin[1], null);
// draw the map
g.drawImage(mapObjectsImage, mapObjectsScreenOrigin[0],
mapObjectsScreenOrigin[1], null);
g.drawImage(resourcesImage, 0, this.getHeight()
- resourcesImage.getHeight(), null);
g.drawImage(playerInfo,mapScreenOrigin[0], mapScreenOrigin[1], null);
}
public void updateMap(SettlerMap map) {
if (map != null) {
tileMapImage = MapArea.drawMap(map, theme);
} else {
tileMapImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
}
}
/*
* Draw map to the tileMapImage off screen buffer
*/
private static BufferedImage drawMap(SettlerMap map, SettlersTheme theme) {
BufferedImage mapImage = new BufferedImage(map.width
* theme.X_TILE_OFFSET + theme.TRIANGLE_AREA_WIDTH, map.height
* theme.Y_TILE_OFFSET, BufferedImage.TYPE_INT_ARGB);
Graphics g = mapImage.createGraphics();
int currentYOffset;
for (int x = 0; x < map.width; x++) {
if (SettlerMap.isPartofDownRow(map.isOriginDown, x)) {
currentYOffset = theme.Y_TILE_OFFSET / 2;
} else {
currentYOffset = 0;
}
for (int y = 0; y < map.height; y++) {
// draw the tile
g.drawImage(theme.getTile(map.getTileAt(x, y)),
theme.X_TILE_OFFSET * x, theme.Y_TILE_OFFSET * y
+ currentYOffset, null);
// draw the chance token on top
g.drawImage(theme
.getChanceTokenImage(map.chance[x][y]),
theme.X_TILE_OFFSET * x + 26, theme.Y_TILE_OFFSET * y
+ currentYOffset + 21, null);
}
}
return mapImage;
}
/**
* @returns the map coordinates that corresponds to a location on the map
* image
*/
public MapCoord[] coordsClicked(int xOnScreen, int yOnScreen,
SettlersTheme theme, boolean isOriginDown) {
// TODO nathan fixed this.
MapCoord[] coords;
int xOrd, yOrd;
int xStorage = xOnScreen; // X variable for roads
int yStorage = yOnScreen;// Y variable for roads
coords = new MapCoord[3];
xOrd = (xOnScreen) / theme.X_TILE_OFFSET;
if ((((xOnScreen - 10) + theme.X_TILE_OFFSET / 2) / theme.X_TILE_OFFSET) % 2 == 1) // checks
// if row is up or down
yOnScreen += 33;
yOrd = yOnScreen / theme.Y_TILE_OFFSET;
if ((xOnScreen + 10) % theme.X_TILE_OFFSET - 16 <= (theme.TRIANGLE_AREA_WIDTH)) {// x
// of
// settlements
if ((yOnScreen + 12) % (theme.Y_TILE_OFFSET / 2) <= 20) {// y of
// settlements
if ((yOnScreen + 12) % theme.Y_TILE_OFFSET <= 20) {// selects
// settlements on the right side
if ((((xOnScreen - 10) + theme.X_TILE_OFFSET / 2) / theme.X_TILE_OFFSET) % 2 == 1) {// checks
// if row is up or down (this one is down)
coords[0] = new MapCoord(
(((xOnScreen - 10) + theme.X_TILE_OFFSET / 2) / theme.X_TILE_OFFSET) - 1,
(yOnScreen + 20) / theme.Y_TILE_OFFSET - 1);
coords[1] = new MapCoord(
(((xOnScreen - 10) + theme.X_TILE_OFFSET / 2) / theme.X_TILE_OFFSET),
(yOnScreen + 20) / theme.Y_TILE_OFFSET - 2);
coords[2] = new MapCoord(
(((xOnScreen - 10) + theme.X_TILE_OFFSET / 2) / theme.X_TILE_OFFSET),
(yOnScreen + 20) / theme.Y_TILE_OFFSET - 1);
} else { // this one is up
coords[0] = new MapCoord(
(((xOnScreen - 10) + theme.X_TILE_OFFSET / 2) / theme.X_TILE_OFFSET) - 1,
(yOnScreen + 20) / theme.Y_TILE_OFFSET - 1);
coords[1] = new MapCoord(
(((xOnScreen - 10) + theme.X_TILE_OFFSET / 2) / theme.X_TILE_OFFSET),
(yOnScreen + 20) / theme.Y_TILE_OFFSET - 1);
coords[2] = new MapCoord(
(((xOnScreen - 10) + theme.X_TILE_OFFSET / 2) / theme.X_TILE_OFFSET),
(yOnScreen + 20) / theme.Y_TILE_OFFSET);
}
}
if ((yOnScreen + 45) % 66 <= 20) {// selects settlements on the
// left side
if ((((xOnScreen - 10) + theme.X_TILE_OFFSET / 2) / theme.X_TILE_OFFSET) % 2 == 1) {// checks
// if row is up or down (this one is down)
coords[0] = new MapCoord(
(((xOnScreen - 10) + theme.X_TILE_OFFSET / 2) / theme.X_TILE_OFFSET) - 1,
(yOnScreen + 20) / theme.Y_TILE_OFFSET - 1);
coords[1] = new MapCoord(
(((xOnScreen - 10) + theme.X_TILE_OFFSET / 2)
/ theme.X_TILE_OFFSET - 1),
(yOnScreen + 20) / theme.Y_TILE_OFFSET);
coords[2] = new MapCoord(
(((xOnScreen - 10) + theme.X_TILE_OFFSET / 2) / theme.X_TILE_OFFSET),
(yOnScreen + 20) / theme.Y_TILE_OFFSET - 1);
} else {// this one is up
coords[0] = new MapCoord(
(((xOnScreen - 10) + theme.X_TILE_OFFSET / 2) / theme.X_TILE_OFFSET) - 1,
(yOnScreen + 20) / theme.Y_TILE_OFFSET - 1);
coords[1] = new MapCoord(
(((xOnScreen - 10) + theme.X_TILE_OFFSET / 2)
/ theme.X_TILE_OFFSET - 1),
(yOnScreen + 20) / theme.Y_TILE_OFFSET);
coords[2] = new MapCoord(
(((xOnScreen - 10) + theme.X_TILE_OFFSET / 2) / theme.X_TILE_OFFSET),
(yOnScreen + 20) / theme.Y_TILE_OFFSET);
}
}
// System.out.println(Arrays.toString(coords));
return coords;
}
}
xOnScreen = xStorage;
yOnScreen = yStorage;
if (SettlerMap.isPartofDownRow(isOriginDown, xOrd))
yOnScreen -= 33;
if ((xOnScreen) % theme.X_TILE_OFFSET > theme.TRIANGLE_AREA_WIDTH) {// horizontal
// pieces
if ((yOnScreen + 10) % theme.Y_TILE_OFFSET <= 22) {
coords = new MapCoord[2];
coords[0] = new MapCoord(xOrd, (yOnScreen + 46) / 66 - 1);
coords[1] = new MapCoord(xOrd, (yOnScreen + 46) / 66);
} else {
coords = new MapCoord[1];
coords[0] = new MapCoord(xOrd, yOrd);
}
} else {// is part of the central rectangle (diagonal pieces)
coords = new MapCoord[2];
coords[0] = new MapCoord();
coords[1] = new MapCoord();
coords[0].setX(xOrd - 1);
coords[1].setX(xOrd);
if (SettlerMap.isPartofDownRow(isOriginDown, xOrd)) {// part of down
// row
if ((yOnScreen + 66) % theme.Y_TILE_OFFSET <= theme.Y_TILE_OFFSET / 2) {
// Diagonal Left
coords[0] = new MapCoord(xOrd - 1, yOrd - 1);
coords[1] = new MapCoord(xOrd, yOrd - 1);
} else {
// Diagonal Right
coords[0] = new MapCoord(xOrd - 1, yOrd);
coords[1] = new MapCoord(xOrd, yOrd - 1);
}
} else {// part of up row
if (yOnScreen % theme.Y_TILE_OFFSET <= theme.Y_TILE_OFFSET / 2) {
// Diagonal Left
coords[0] = new MapCoord(xOrd - 1, yOrd - 1);
coords[1] = new MapCoord(xOrd, yOrd);
} else {
// Diagonal Right
coords[0] = new MapCoord(xOrd - 1, yOrd);
coords[1] = new MapCoord(xOrd, yOrd);
}
}
}
return coords;
}
public void mouseMoved(MouseEvent me) {
// needed for the map moving to function
lastPoint = me.getPoint();
}
public void mouseDragged(MouseEvent me) {
// Allows for the movement of the map and mapobjects
mapScreenOrigin[0] -= (lastPoint.getX() - me.getX());
mapScreenOrigin[1] -= (lastPoint.getY() - me.getY());
mapObjectsScreenOrigin[0] -= (lastPoint.getX() - me.getX());
mapObjectsScreenOrigin[1] -= (lastPoint.getY() - me.getY());
lastPoint = me.getPoint();
repaint();
}
public void getCurrentTheme() {
System.out.println(super.getClass().toString());
}
class AddCommand implements Runnable {
String command;
AddCommand(String command) {
this.command = command;
}
public void run() {
try {
gameCommandQueue.put(command);
} catch (InterruptedException e) {
System.err.println("Could not put command: " + command);
}
}
}
}