package vooga.rts.state;
import java.awt.Color;
import java.awt.Graphics2D;
import java.util.HashMap;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import java.util.Timer;
import java.util.TimerTask;
import util.input.Input;
import vooga.rts.commands.Command;
import vooga.rts.controller.InputController;
import vooga.rts.game.RTSGame;
import vooga.rts.gui.Window;
import vooga.rts.gui.menus.MultiMenu;
import vooga.rts.util.Scale;
import vooga.rts.util.TimeIt;
/**
* The main state of the game. It keeps track of which sub-state the game is in
* (Loading, menu or game state), and switches between them as needed.
*
* @author challenherzberg-brovold
*
*/
public class MainState implements State, Observer {
private final static String DEFAULT_INPUT_LOCATION = "vooga.rts.resources.properties.Input";
private Window myWindow;
private Map<SubState, SubState> myStates;
private SubState myActiveState;
private Timer myTimer;
private InputController myController;
private boolean myReady;
private String myMapFile;
private GameState myGame;
public MainState () {
myReady = false;
myStates = new HashMap<SubState, SubState>();
myWindow = new Window();
myWindow.setFullscreen(true);
LoadingState loader = new LoadingState(this);
setActiveState(loader);
render();
MenuState menu = new MenuState(this, getWindow().getJFrame());
myStates.put(loader, menu);
myGame = new GameState(this);
myStates.put(menu, myGame);
Input input = new Input(DEFAULT_INPUT_LOCATION, myWindow.getCanvas());
myController = new InputController(this);
input.addListenerTo(myController);
}
@Override
public void receiveCommand (Command command) {
myActiveState.receiveCommand(command);
}
@Override
public void update (double elapsedTime) {
myController.processCommands();
myActiveState.update(elapsedTime);
}
@Override
public void paint (Graphics2D pen) {
Scale.scalePen(pen);
myActiveState.paint(pen);
}
@Override
public void update (Observable o, Object arg) {
if (o instanceof SubState) {
if (myStates.containsKey(o)) {
setActiveState(myStates.get(o));
}
if (arg instanceof GameOver) {
setActiveState(new GameOverState(this, (GameOver) arg));
}
}
}
/**
* Sets the substate of the game to the next one.
*/
private void setActiveState (SubState s) {
myActiveState = s;
s.activate();
}
private void render () {
Graphics2D graphics = myWindow.getCanvas().getGraphics();
graphics.setColor(Color.BLACK);
graphics.fillRect(0, 0, myWindow.getCanvas().getWidth(), myWindow.getCanvas().getHeight());
if (myActiveState instanceof MenuState) {
MenuState m = (MenuState) myActiveState;
if (m.getCurrentMenu() instanceof MultiMenu) {
myWindow.getCanvas().repaint();
return;
}
}
paint(graphics);
myWindow.getCanvas().render();
}
/**
* Returns whether the Main State is ready yet.
* This means that all the sub states have been created
* and the timer is ticking.
*
* @return the ready state
*/
public boolean isReady () {
return myReady;
}
/**
* @return the window
*/
public Window getWindow () {
return myWindow;
}
public void start () {
myTimer = new Timer();
myTimer.scheduleAtFixedRate(new TimerTask() {
private long lastNano = System.nanoTime();
@Override
public void run () {
long curNano = System.nanoTime();
double change = curNano - lastNano;
change /= 1000000000;
update(change);
if (myWindow.hasFocus()) {
render();
}
lastNano = curNano;
}
}, 500, (long) (RTSGame.TIME_PER_FRAME() * 1000));
myReady = true;
}
public void stop () {
myTimer.cancel();
}
// Added so that we can actually get a game to create itself....
public void setMapFile (String map) {
myMapFile = map;
myGame.setupMap(map);
}
}