package ch.sahits.game.graphic.display.gameplay;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.util.Map;
import java.util.TreeMap;
import ch.sahits.game.event.EViewChangeEvent;
import ch.sahits.game.event.Event;
import ch.sahits.game.event.IEventListener;
import ch.sahits.game.event.MouseClickEvent;
import ch.sahits.game.event.ViewChangeEvent;
import ch.sahits.game.graphic.display.model.CityPlayerProxy;
import ch.sahits.game.graphic.display.util.NamedPolygon;
import ch.sahits.game.graphic.display.util.OffsetCalculator;
import ch.sahits.game.graphic.image.ImagesLoader;
import ch.sahits.game.image.ImageUtil;
import ch.sahits.game.openpatrician.client.IClient;
import ch.sahits.game.openpatrician.model.ship.IShip;
import ch.sahits.game.rendering.AbstractRenderPart;
/**
* This represents the main game screen
* @author Andi Hotz, (c) Sahits GmbH, 2011
* Created on Sep 30, 2011
*
*/
public class MainView extends AbstractRenderPart implements IEventListener {
/** This image holds the background of the currently rendered View */
private final BufferedImage img;
private OpenPatricianGameDialog dialog=null;
/** Scale of the dialog */
private final double dialogScale;
private final static String[] polyNames = {"LoadingCrane"};
private final static String[] imageNames = {"portScene","fringe", "waxseal","sealingWaxFlattend",
"barrel_icon","bale_icon"};
private final ImagesLoader loader;
/**
* Store the polygons for checking against clicking them
* Using a TreeMap so it may be possible do define polygons that cover the same
* are but in a different z-order.
*/
private Map<Integer, NamedPolygon> portPolygons = new TreeMap<Integer, NamedPolygon>();
/**
* Indicate that currently the port scene is displayed
*/
private static final byte PORT_SCENE = 0x00;
/**
* Use low level byte to indicate what is displayed instead of an enum.
*/
private byte viewState = PORT_SCENE;
/** Model of the city currently displayed. May be null if no city is displayed */
private CityPlayerProxy city;
/**
* Instantiate the main view with the port scene of the players home town
* @param rect
* @param loader
* @param cl
*/
public MainView(Rectangle rect, ImagesLoader loader, IClient cl) {
super(rect);
this.loader = loader;
city = new CityPlayerProxy(cl.getPlayer().getHometown(), cl.getPlayer());
IShip ship = cl.getPlayer().getFleet().get(0);
city.arrive(ship);
System.out.println("MainView: "+rect);
BufferedImage tmpImg = loader.getImage(imageNames[0]);
img = ImageUtil.scale(tmpImg, getBounds().getSize());
dialogScale = ImageUtil.computeScaleFactor(getBounds().getSize(), tmpImg.getWidth(), tmpImg.getHeight());
Rectangle bounds = ImageUtil.computeBounds(getBounds().getSize(),img.getWidth(),img.getHeight());
initPortPolygons(dialogScale, bounds);
loader.replaceSingleImage(imageNames[0], img);
resetDialog();
Event.add(this);
}
/**
* Scale the dialog so it has the correct proportions
*/
private void resetDialog() {
BufferedImage tmpImg = loader.getImage(imageNames[1]);
Dimension dim = new Dimension(getBounds().width*2/3, 600);
BufferedImage frame = ImageUtil.scaleUnBounded(tmpImg, dim);
double scale = ImageUtil.computeScaleFactor(dim, tmpImg.getWidth(), tmpImg.getHeight());
loader.replaceSingleImage(imageNames[1], frame);
tmpImg = loader.getImage(imageNames[2]);
loader.replaceSingleImage(imageNames[2], ImageUtil.scale(tmpImg, scale));
tmpImg = loader.getImage(imageNames[3]);
loader.replaceSingleImage(imageNames[3], ImageUtil.scale(tmpImg, scale));
int height = loader.getImage(imageNames[3]).getHeight();
tmpImg = loader.getImage(imageNames[4]); // barrel
tmpImg = ImageUtil.scaleUnBounded(tmpImg, new Dimension(height, height));
loader.replaceSingleImage(imageNames[4], tmpImg);
tmpImg = loader.getImage(imageNames[5]); // bale
tmpImg = ImageUtil.scaleUnBounded(tmpImg, new Dimension(height, height));
loader.replaceSingleImage(imageNames[5], tmpImg);
}
@Override
public void gameRender(Graphics gScr) {
Color oldColor = gScr.getColor();
// gScr.setColor(Color.BLACK);
// gScr.fillRect(rect.x, rect.y, rect.width, rect.height);
// gScr.setColor(Color.WHITE);
// final int x = 20+rect.x;
// final int y = rect.y+rect.height/2;
// gScr.drawString("MainScreen", x, y);
gScr.drawImage(img, rect.x, rect.y, null);
if (dialog!=null){
dialog.gameRender(gScr);
}
gScr.setColor(oldColor);
}
@Override
public void gameUpdate(Event e, Object eventNotice) {
if (e instanceof MouseClickEvent){
Point p = (Point) eventNotice;
String polyName = findPolygon(p.x, p.y);
// Use the same string instance
if (polyName==polyNames[0]){ // loading crane
if (city.getActiveShip()!=null){ // if there is an active ship
BufferedImage img = loader.getImage(imageNames[1]);
Point topLeft = new Point(getBounds().x+(getBounds().width-img.getWidth())/2,getBounds().y+(getBounds().height-600)/2);
dialog = new TradeDialog(topLeft, loader,dialogScale,city);
}
}
} else if (e instanceof ViewChangeEvent){
if (((ViewChangeEvent)e).getAddresse()==getClass()){
EViewChangeEvent change = (EViewChangeEvent) eventNotice;
switch (change) {
case CLOSE_DIALOG:
dialog=null;
break;
default:
break;
}
}
}
// TODO Auto-generated method stub
}
/**
* Find the polygon name that contains the coordinates. It is expected that the polygons
* are not overlapping. Is this not the case the first found polygon name is returned.
* @param x coordinate
* @param y coordinate
* @return name of the polygon
*/
private String findPolygon(int x, int y) { // Use a better algo
switch (viewState) {
case PORT_SCENE:
for (NamedPolygon poly : portPolygons.values()) {
if (poly.contains(x, y)) {
return poly.getName();
}
}
return null;
default:
throw new IllegalStateException("Unknown view state: "+viewState);
}
}
/**
* Setting the positions of the polygons on the screen
*/
private void initPortPolygons(double scale,Rectangle bounds) {
// TODO implement PolygonLoader
OffsetCalculator offsetter = new OffsetCalculator(getBounds().x+bounds.x, getBounds().y+bounds.y); // top left corner of this view plus any black borders
NamedPolygon poly = new NamedPolygon(polyNames[0]);
poly.addPoint(offsetter.computeXOffset(508, scale), offsetter.computeYOffset(678, scale));
poly.addPoint(offsetter.computeXOffset(574, scale), offsetter.computeYOffset(520, scale));
poly.addPoint(offsetter.computeXOffset(534, scale), offsetter.computeYOffset(546, scale));
poly.addPoint(offsetter.computeXOffset(736, scale), offsetter.computeYOffset(586, scale));
poly.addPoint(offsetter.computeXOffset(702, scale), offsetter.computeYOffset(672, scale));
poly.addPoint(offsetter.computeXOffset(786, scale), offsetter.computeYOffset(758, scale));
poly.addPoint(offsetter.computeXOffset(526, scale), offsetter.computeYOffset(756, scale));
int meanY = (poly.ypoints[1] + poly.ypoints[5]) / 2;
portPolygons.put(meanY, poly); // maybe we should use meanX instead
}
}