Package cz.cuni.mff.abacs.burglar.visual.play_state

Source Code of cz.cuni.mff.abacs.burglar.visual.play_state.PlayState$Screen

/**
*
*/
package cz.cuni.mff.abacs.burglar.visual.play_state;

import cz.cuni.mff.abacs.burglar.logics.DataMap;
import cz.cuni.mff.abacs.burglar.logics.ExecutingMap;
import cz.cuni.mff.abacs.burglar.logics.GameMap;
import cz.cuni.mff.abacs.burglar.logics.Player;
import cz.cuni.mff.abacs.burglar.logics.objects.BaseInterface;
import cz.cuni.mff.abacs.burglar.logics.objects.BaseObject;
import cz.cuni.mff.abacs.burglar.logics.objects.agents.Agent;
import cz.cuni.mff.abacs.burglar.logics.objects.agents.Burglar;
import cz.cuni.mff.abacs.burglar.logics.objects.agents.Guard;
import cz.cuni.mff.abacs.burglar.logics.objects.positions.Active;
import cz.cuni.mff.abacs.burglar.logics.objects.positions.Lockable;
import cz.cuni.mff.abacs.burglar.logics.objects.positions.Vender;
import cz.cuni.mff.abacs.burglar.logics.planning.instructions.Instruction;
import cz.cuni.mff.abacs.burglar.visual.VisualBurglar;
import cz.cuni.mff.abacs.burglar.visual.multithreading.LoadingListener;
import cz.cuni.mff.abacs.burglar.visual.multithreading.LoadingThread;
import cz.cuni.mff.abacs.burglar.visual.multithreading.PlanningListener;
import cz.cuni.mff.abacs.burglar.visual.multithreading.PlanningThread;
import cz.cuni.mff.abacs.burglar.visual.multithreading.PlanningThread.Type;
import java.util.List;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;


/**
* Base of the game play implementation. It contains the game logics.
*
* @author abacs
*
*/
public abstract class PlayState
    extends BasicGameState
    implements PlanningListener, LoadingListener {

  // constants:
 
  /** Time spent in milliseconds between two movement steps. */
  protected static int DEFAULT_MOVEMENT_DELAY = 600;
  /** Time change in milliseconds when game speed is lowered or increased. */
  protected static int GAME_SPEED_DELTA = 200;
 
  protected static final String DEFAULT_MAP = null;
 
  /**  */
  public static enum MapState {
    UNSET,
    UNLOADED,
    SELECING_TRAP_ROOMS,
    PLANNING,
    PLANNED,
    UNSOLVABLE,
    SOLVED,
    LOST,
  };
 
 
  /**  */
  public static enum RuningState {
    PAUSED,
    MOVING,
  }
 
 
  // -------------------------------------------------------------------------
  // properties:
 
  // game engine properties:
 
  /** Id of the current state. */
  private final int _stateID;
  /** Pointer to the main game container. */
  protected GameContainer _container = null;
  /** Pointer to the whole program. */
  protected StateBasedGame _stateBasedGame = null;
 
 
  // game states:
 
  /**  */
  protected MapState _mapState = MapState.UNSET;
  /**  */
  protected RuningState  _runingState  = RuningState.PAUSED;
 
 
  /** Name of the map file. */
  protected String _mapName = null;
 
  /** The loaded map file. */
  protected GameMap _map = null;
  /** Secondary map file.
   * (currently not in use) */
  protected GameMap _secondaryMap = null;
 
  /** Implements the player interaction with the map. */
  protected Player _player;
 
 
  /** The thread executing the planning. */
  protected PlanningThread _planningThread = null
 
 
  /** Selection rectangle on the game map. */
  protected Selection _selection = null;
  /** Screen representation on the game map. */
  protected Screen _screen = null;
 
 
  /** Milliseconds to wait between two game moves. */
  protected int _movementDelay = DEFAULT_MOVEMENT_DELAY;
  /** Milliseconds to wait until the next game move. */
  protected int _msToWait = 0;
  /**  */
  public int _trapsAvioded = 0;
 
 
  // -------------------------------------------------------------------------
  // constructor:
 
 
  /**
   *
   * @param stateID
   */
  protected PlayState(int stateID) throws SlickException
    this._stateID = stateID;
  }
 
 
  // -------------------------------------------------------------------------
 
 
  @Override
  public int getID() {
    return this._stateID;
  }
 

  /**
   * Initialize any needed data before the game loop.
   * Warning: it may be called multiple times:
   *
   * @param container
   * @param game
   * */
  @Override
  public void init(GameContainer container, StateBasedGame game)
      throws SlickException {
   
    this._container = container;
    this._stateBasedGame = game;
   
    // view settings:
    this._selection = new Selection(this);
    this._screen = new Screen(
        this,
        container.getWidth()  / VisualBurglar.RESOURCE_BLOCK_SIZE,
        container.getHeight() / VisualBurglar.RESOURCE_BLOCK_SIZE
    );
  }
 
 
  /**
   * Resets the map if the state is lost.
   */
  @Override
  public void leave(GameContainer container, StateBasedGame game) throws SlickException {
    super.leave(container, game);
    if(this._mapState == MapState.LOST || this._mapState == MapState.SOLVED)
      this.reload();
    this._movementDelay = DEFAULT_MOVEMENT_DELAY;
  }
 
 
  /**
   * Called during the game to update the logic in our world,
   * within this method we obtain the user input,
   * calculate the world response to the input, do the calculation.
   *
   * @param container
   * @param game
   * @param delta
   * */
  @Override
  public void update(GameContainer container, StateBasedGame game, int delta)
      throws SlickException {
   
    this._msToWait -= delta;
   
    // before and after the gameplay do nothing:
    if(this._mapState != MapState.PLANNED)
      return;
   
    if(this._map.needsReplanning()){
      this._planningThread =
      new PlanningThread(
          this._map,
          this,
          this._map.getAgentsToReplan()
      );
      this._planningThread.start();
     
      this._map.clearAgentsToReplan();
     
      this._mapState = MapState.PLANNING;
    }
   
    // if the game is not paused - redraw:
    if(
      this._runingState == RuningState.MOVING &&
      this._msToWait <= 0
    ){ 
      // reset delay:
      this._msToWait = this._movementDelay;
     
      // controls:
     
      if(this._map.getBurglar().isSatisfied()){
        this._mapState = MapState.SOLVED;
        System.out.println("- Solved");
        return;
      }
     
      if(this._map.isBurglarTrapped()){
        this._mapState = MapState.LOST;
        System.out.println("- Lost");
        return;
      }
     
      // actions:
     
      this._map.executeStep();
      this._map.lookAround();
     
    }
  }
 
 
  // -------------------------------------------------------------------------
 
 
  /**
   * shortcuts:
   * - directions: moves the selection-box
   * - exit: quits the program
   * - space bar: pauses the game
   * - + increase game speed
   * - - decrease game speed
   *
   * @param key
   * @param c
   */
  @Override
  public void keyReleased(int key, char c) {
    //
    switch(key){
    case Input.KEY_UP:
      if(VisualBurglar.FLAG_PLAYER_CONTROL_MODE){
        if(this._player.moveBurglar(GameMap.Direction.NORTH))
          this._screen.moveUp();
        break;
      }
      this._screen.moveUp();
      break;
    case Input.KEY_DOWN:
      if(VisualBurglar.FLAG_PLAYER_CONTROL_MODE){
        if(this._player.moveBurglar(GameMap.Direction.SOUTH))
          this._screen.moveDown();
        break;
      }
      this._screen.moveDown();
      break;
    case Input.KEY_LEFT:
      if(VisualBurglar.FLAG_PLAYER_CONTROL_MODE){
        if(this._player.moveBurglar(GameMap.Direction.WEST))
          this._screen.moveLeft();
        break;
      }
      this._screen.moveLeft();
      break;
    case Input.KEY_RIGHT:
      if(VisualBurglar.FLAG_PLAYER_CONTROL_MODE){
        if(this._player.moveBurglar(GameMap.Direction.EAST))
          this._screen.moveRight();
        break;
      }
      this._screen.moveRight();
      break;
    case Input.KEY_SPACE:
      this.pauseUnpause();
      break;
    case Input.KEY_ADD:
      this.increaseSpeed();
      break;
    case Input.KEY_SUBTRACT:
      this.decreaseSpeed();
      break;
    case Input.KEY_ESCAPE:
      this._container.exit();
      break;
    default:
    }
  }
 
 
  @Override
  public void mouseMoved(int oldX, int oldY, int newX, int newY){
    super.mouseMoved(oldX, oldY, newX, newY);
   
    int mapX = this._screen.screenXToMapX(newX);
    int mapY = this._screen.screenYToMapY(newY);
   
    this._selection.set(mapX, mapY);
  }
 
 
  @Override
  public void mouseClicked(int button, int x, int y, int clickCount) {
   
  }
 
 
  // -------------------------------------------------------------------------
 
 
  /**
   * Pause or continue the plan execution.
   */
  public void pauseUnpause() {
    switch(this._runingState){
    case PAUSED:
      this._runingState = RuningState.MOVING;
      break;
    case MOVING:
      this._runingState = RuningState.PAUSED;
      break;
    default:
      break;
    }
  }
 
 
  /**
   * Increase the speed of the plan execution.
   *
   * @return success indicator
   */
  public boolean increaseSpeed() {
    if(this._movementDelay > 2 * GAME_SPEED_DELTA){
      this._movementDelay -= GAME_SPEED_DELTA;
      return true;
    }else{
      this._movementDelay = GAME_SPEED_DELTA;
    }
    return false;
  }
 
 
  /**
   * Decrease the speed of the plan execution.
   *
   * @return success indicator
   */
  public boolean decreaseSpeed() {
    this._movementDelay += GAME_SPEED_DELTA;
    return true;
  }
 
 
  /**
   * Reloads the current map.
   */
  public void reload() {
    this._secondaryMap = null;
    this._planningThread = null;
    this._trapsAvioded = 0;
   
    this._screen.resetPosition();
   
    // load the map:
    this._mapState = MapState.UNLOADED;
    this._map = null;
    this._secondaryMap = null;
    LoadingThread loader = new LoadingThread(this._mapName, this);
    loader.start();
  }
 
 
  /**
   * Loads a new map.
   */
  public void load(String mapName) {
    if(this._mapName != null && this._mapName.equals(mapName))
      return;
    this._mapName = mapName;
    this.reload();
  }
 
 
  /**
   * Open any Lockable object in selection.
   */
  public void closeOpenSelection() {
    List<BaseObject> objects =
      this._map.getObjectsOnPosition(
          this._selection.getX(),
          this._selection.getY()
      );
    for(BaseObject object : objects){
      switch(object.getType()){
      case DOOR:
      case CONTAINER:
        this._player.openClosePosition((Lockable)object);
        break;
      }
    }
   
    if(VisualBurglar.FLAG_PLAYER_CONTROL_MODE)
      this._map.getBurglar().lookAround();
  }
 
 
  /**
   * Lock any lockable object in selection.
   */
  public void lockUnlockSelection() {
    List<BaseObject> objects =
      this._map.getObjectsOnPosition(
          this._selection.getX(),
          this._selection.getY()
      );
    for(BaseObject object : objects){
      switch(object.getType()){
      case DOOR:
      case CONTAINER:
        this._player.lockUnlockPosition((Lockable)object);
        break;
      }
    }
  }
 
 
  /**
   * Activates or deactivates any Active position in selection.
   */
  public void activateDeactivateSelection() {
    List<BaseObject> objects =
      this._map.getObjectsOnPosition(
          this._selection.getX(),
          this._selection.getY()
      );
    for(BaseObject object : objects){
      switch(object.getType()){
      case CAMERA:
      case SWITCH:
      case PHONE:
        this._player.activateDeactivatePosition((Active)object);
        break;
      case VENDER:
        this._player.activateVender((Vender)object);
        break;
      }
    }
  }
 
 
  /**
   * Dazes any Guard in selection.
   */
  public void dazeSelected() {
    int mapX = this._selection.getX();
    int mapY = this._selection.getY();
   
    for(BaseObject object : this._map.getObjectsOnPosition(mapX, mapY)){
      if(object.isTypeOf(BaseInterface.Type.GUARD))
        this._player.dazeAgent((Guard)object);
    }
  }
 
 
  // -------------------------------------------------------------------------
 
 
  /**
   * Not in use
   */
  protected void synchronizeSecondaryMap() {
    // TODO
  }
 
 
  // -------------------------------------------------------------------------
  // callbacks:
 
 
  @Override
  public void planningFinished(
      List<Instruction> resultedInstructions,
      PlanningThread thread
  ) {
    // do nothing, if not the most recent planning
    if(this._planningThread != thread)
      return;
   
    this._map.addInstructions(resultedInstructions);
  }
 
 
  @Override
  public void planningFinished(
      List<Instruction> resultedInstructions,
      List<Integer> avoidedTrapRooms,
      PlanningThread thread
  ) {
    // do nothing, if not the most recent planning
    if(this._planningThread != thread)
      return;
   
    this._map.addInstructions(resultedInstructions);
   
    this._trapsAvioded = avoidedTrapRooms.size();
  }
 
 
  @Override
  public void planningFinished(
      PlanningThread thread
  ) {
    this._mapState = MapState.PLANNED;
   
    Burglar burglar = this._map.getBurglar();
    if(
      burglar.hasInstructions() == false &&
      burglar.isSatisfied() == false
    ){
      this._mapState = MapState.LOST;
      System.out.println("- Lost");
    }
  }
 
 
  @Override
  public void loadingFinished(ExecutingMap map, ExecutingMap secondaryMap) {
    this._map = map;
    this._secondaryMap = secondaryMap;
   
    if(VisualBurglar.FLAG_IN_GAME_LEVEL_DESIGN){
      // start placing guards on the map:
      this._mapState = MapState.SELECING_TRAP_ROOMS;
      this._planningThread =
          new PlanningThread(
              this._map,
              Type.SELECTING_TRAP_ROOMS,
              this
              );
      this._planningThread.start();
    }else{
      for(Agent agent : this._map.getAgents())
        this._map.addAgentToReplan(agent);
      this._mapState = MapState.PLANNED;
    }
  }
 
 
  @Override
  public void selectingTrapRoomsFinished(
      List<Integer> trapRooms,
      PlanningThread thread
  ) {
    if(thread != this._planningThread)
      return;
   
    DataMap map = (DataMap)this._map;
   
    List<List<Integer>> components = map.breakToComponents(trapRooms);
    for(List<Integer> component : components){
      if(component.size() > 1){
        ((ExecutingMap)map).addGuardPatrol(component);
      }else{
        map.addCameraToRoom(component.get(0));
      }
    }
   
    for(Agent agent : this._map.getAgents())
        this._map.addAgentToReplan(agent);
    this._mapState = MapState.PLANNED;
  }
 
 
  // =========================================================================
  // subclasses:
 
 
  /**
   * Representation of the mouse cursor's position on the screen.
   */
  protected class Selection {
 
    // properties:
   
    /** selection's horizontal position on the game map */
    protected int _x = 0;
    /** selection's vertical position on the game map */
    protected int _y = 0;
    /**  */
    protected PlayState _parent = null;
   
   
    // ---------------------------------------------------------------------
    // constructors:
   
   
    /**
     *
     *
     * @param parent
     */
    protected Selection(PlayState parent) {
      this._parent = parent;
    }
   
   
    // ---------------------------------------------------------------------
   
   
    /**
     * Allows the selection to move to the left on the map.
     *
     * If the selection reaches the left edge of the map, does nothing.
     *
     * @return success indicator
     */
    public boolean moveLeft() {
      if(this._parent._map == null)
        return false;
     
      if(this._x > 1){
        this._x--;
        return true;
      }
      return false;
    }

   
    /**
     * Allows the selection to move to the right left the map.
     *
     * If the selection reaches the right edge of the map, does nothing.
     *
     * @return success indicator
     */
    public boolean moveRight() {
      if(this._parent._map == null)
        return false;
     
      if(this._x < this._parent._map.getWidth() + 1){
        this._x++;
        return true;
      }
      return false;
    }
   
   
    /**
     * Allows the selection to move up to the top of the map.
     *
     * If the selection reaches the top of the map, does nothing.
     *
     * @return success indicator
     */
    public boolean moveUp() {
      if(this._parent._map == null)
        return false;
     
      if(this._y > 1){
        this._y--;
        return true;
      }
      return false;
    }
   
   
    /**
     * Allows the selection to move down to the bottom of the map.
     *
     * If the selection reaches the bottom of the map, does nothing.
     *
     * @return success indicator
     */
    public boolean moveDown() {
      if(this._parent._map == null)
        return false;
     
      if(this._y < this._parent._map.getHeight() + 1){
        this._y++;
        return true;
      }
      return false;
    }
   
   
    /**
     * Sets the position of the selection on the map.
     *
     * @param val x coordinate on the map.
     * @return success indicator
     */
    public boolean setX(int val) {
      if(this._parent._map == null)
        return false;
     
      if(val > 0 && val < this._parent._map.getWidth() + 1){
        this._x = val;
        return true;
      }
      return false;
    }
   
   
    /**
     * Sets the position of the selection on the map.
     *
     * @param val y coordinate on the map.
     * @return success indicator
     */
    public boolean setY(int val) {
      if(this._parent._map == null)
        return false;
     
      if(val > 0 && val < this._parent._map.getHeight() + 1){
        this._y = val;
        return true;
      }
      return false;
    }
   
   
    /**
     * Sets the position of the selection on the map.
     *
     * @param x x coordinate on the map.
     * @param y y coordinate on the map.
     * @return success indicator
     */
    public boolean set(int x, int y) {
      if(this._parent._map == null)
        return false;
       
      if(x > 0 && x < this._parent._map.getWidth() + 1 &&
         y > 0 && y < this._parent._map.getHeight() + 1){
        this._x = x;
        this._y = y;
        return true;
      }
      return false;
    }
   
   
    // ---------------------------------------------------------------------
   
   
    /** selection's horizontal position on the game map */
    public int getX() {
      return this._x;
    }
   
   
    /** selection's vertical position on the game map */
    public int getY() {
      return this._y;
    }
   
  }
 
 
  /**
   * Representation of the visible part of the GameMap.
   */
  protected class Screen {
 
    // properties:
   
    /** Left screen corner on the game map. */
    protected int _x = 0;
    /** Top screen corner on the game map. */
    protected int _y = 0;
    /** Screen width in game map positions. */
    protected int _width = 0;
    /** Screen height in game map positions. */
    protected int _height = 0;
    /** Parent object holding the map. */
    protected PlayState _parent = null;
   
   
    // ---------------------------------------------------------------------
    // constructors:
   
   
    /**
     *
     *
     * @param parent
     * @param width
     * @param height
     */
    protected Screen(PlayState parent, int width, int height) {
      this._parent = parent;
      this._width  = width;
      this._height = height;
    }
   
   
    // ---------------------------------------------------------------------
   
   
    /**
     * Resets the screen position to the upper left corner of the map.
     */
    public void resetPosition() {
      this._x = 0;
      this._y = 0;
    }
   
   
    /**
     * Allows to move left to show the most right and one unused
     * wall position.
     *
     * If the screen reaches the left border of the map, does nothing.
     *
     * @return success indicator
     */
    public boolean moveLeft() {
      if(this._x > 0){
        this._x--;
        return true;
      }
      return false;
    }
   
   
    /**
     * Allows to move right to show the most right and one unused
     * wall position.
     *
     * If the screen reaches the right border of the map, does nothing.
     *
     * @return success indicator
     */
    public boolean moveRight() {
      if(this._x + this._width < this._parent._map.getWidth() + 2){
        this._x++;
        return true;
      }
      return false;
    }
   
   
    /**
     * Allows to move up to show the highest and one unused wall position.
     *
     * If the screen reaches the top of the map, does nothing.
     *
     * @return success indicator
     */
    public boolean moveUp() {
      if(this._y > 0){
        this._y--;
        return true;
      }
      return false;
    }
   
   
    /**
     * Allows to move down to show the lowest and one unused wall position.
     *
     * If the screen reaches the bottom of the map, does nothing.
     *
     * @return success indicator
     */
    public boolean moveDown() {
      if(this._y + this._height < this._parent._map.getHeight() + 2){
        this._y++;
        return true;
      }
      return false;
    }
   
   
    /**
     * Sets the width of the game map.
     *
     * If the value is invalid (less than 1), does nothing, prints to error
     * output.
     *
     * @param value new width.
     */
    public void setWidth(int value) {
      if(value < 1){
        System.err.println(value + " is not a valid game map width.");
        return;
      }
      this._width = value;
    }
   
   
    /**
     * Sets the height of the game map.
     *
     * If the value is invalid (less than 1), does nothing, prints to error
     * output.
     *
     * @param value new height.
     */
    public void setHeight(int value) {
      if(value < 1){
        System.err.println(value + " is not a valid game map height.");
        return;
      }
      this._height = value;
    }
   
   
    // ---------------------------------------------------------------------
   
   
    /** Screen's left corner on the game map. */
    public int getX() {
      return this._x;
    }
   
   
    /** Screen's top corner on the game map. */
    public int getY() {
      return this._y;
    }
   
   
    /** Screen's width in game map positions. */
    public int getWidth() {
      return this._width;
    }
   
   
    /** Screen's height in game map positions. */
    public int getHeight() {
      return this._height;
    }
   
   
    // ---------------------------------------------------------------------
   
   
    /**
     * Converts the screen position to the map position.
     *
     * @param screenX x coordinate on the screen
     * @return x coordinate on the map
     */
    public int screenXToMapX(int screenX) {
      return screenX / VisualBurglar.RESOURCE_BLOCK_SIZE + this._x;
    }
   
   
    /**
     * Converts the screen position to the map position.
     *
     * @param screenX x coordinate on the screen
     * @return x coordinate on the map
     */
    public int screenXToMapX(float screenX) {
      return this.screenXToMapX((int)screenX);
    }
   
   
    /**
     * Converts the screen position to the map position.
     *
     * @param screenY y coordinate on the screen
     * @return y coordinate on the map
     */
    public int screenYToMapY(int screenY) {
      return screenY / VisualBurglar.RESOURCE_BLOCK_SIZE + this._y;
    }
   
   
    /**
     * Converts the screen position to the map position.
     *
     * @param screenY y coordinate on the screen
     * @return y coordinate on the map
     */
    public int screenYToMapY(float screenY) {
      return this.screenYToMapY((int)screenY);
    }
   
   
    /**
     * Converts the map position to the screen position.
     *
     * @param mapX x coordinate on the map
     * @return x coordinate on the screen
     */
    public int mapXToScreenX(int mapX) {
      return (mapX - this._x) * VisualBurglar.RESOURCE_BLOCK_SIZE;
    }
   
   
    /**
     * Converts the map position to the screen position.
     *
     * @param mapY y coordinate on the map
     * @return y coordinate on the screen
     */
    public int mapYToScreenY(int mapY) {
      return (mapY - this._y) * VisualBurglar.RESOURCE_BLOCK_SIZE;
    }
   
  }

TOP

Related Classes of cz.cuni.mff.abacs.burglar.visual.play_state.PlayState$Screen

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.
to:coftware@gmail.com">coftware#gmail.com.