Package ponkOut.logic

Source Code of ponkOut.logic.BlockFace

/* Copyright 2010 Christian Matt
*
* This file is part of PonkOut.
*
* PonkOut is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PonkOut is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PonkOut.  If not, see <http://www.gnu.org/licenses/>.
*/

package ponkOut.logic;

import java.util.LinkedList;
import java.util.List;

import org.lwjgl.util.vector.Vector2f;

import ponkOut.logic.Block.CornerPlace;

/**
* Used for collision detection. Contains a list of all blocks which share a
* face and the two end points.
*/
public class BlockFace {
  private LinkedList<Block> blocks;
  private Block.FacePlace facePlace;

  /** position of left or top end point */
  private Vector2f firstCorner;

  /** position of right or bottom end point */
  private Vector2f secondCorner;

  /**
   * creates a new face containing only one block
   */
  public BlockFace(Block block, Block.FacePlace facePlace) {
    blocks = new LinkedList<Block>();
    blocks.add(block);
    this.facePlace = facePlace;
    firstCorner = getFirstCorner(block);
    secondCorner = getSecondCorner(block);
    block.setFace(this);
  }

  /**
   * @param block
   *            an arbitrary block
   * @return position of the first corner of the face with the same facePlace
   *         as this the block induces
   */
  private Vector2f getFirstCorner(Block block) {
    switch (facePlace) {
    case LEFT:
      return block.getCornerPos(CornerPlace.TOP_LEFT);

    case RIGHT:
      return block.getCornerPos(CornerPlace.TOP_RIGHT);

    case TOP:
      return block.getCornerPos(CornerPlace.TOP_LEFT);

    case BOTTOM:
      return block.getCornerPos(CornerPlace.BOTTOM_LEFT);

    default:
      throw new IllegalArgumentException("face does not have a valid value");
    }
  }

  /**
   * @param block
   *            an arbitrary block
   * @return position of the second corner of the face with the same facePlace
   *         as this the block induces
   */
  private Vector2f getSecondCorner(Block block) {
    switch (facePlace) {
    case LEFT:
      return block.getCornerPos(CornerPlace.BOTTOM_LEFT);

    case RIGHT:
      return block.getCornerPos(CornerPlace.BOTTOM_RIGHT);

    case TOP:
      return block.getCornerPos(CornerPlace.TOP_RIGHT);

    case BOTTOM:
      return block.getCornerPos(CornerPlace.BOTTOM_RIGHT);

    default:
      throw new IllegalArgumentException("face does not have a valid value");
    }
  }

  /**
   * @param block
   *            this block is added to the front of this block's list
   */
  public void addFront(Block block) {
    blocks.add(0, block);
    firstCorner = getFirstCorner(block);
    block.setFace(this);
  }

  /**
   * @param block
   *            this block is added to the end of this block's list
   */
  public void addBack(Block block) {
    blocks.add(block);
    secondCorner = getSecondCorner(block);
    block.setFace(this);
  }

  /**
   * @param block
   *            all blocks in this face are added to the front of this face's
   *            list
   */
  public void addFront(BlockFace face) {
    for (int i = face.blocks.size() - 1; i >= 0; --i) {
      Block block = face.blocks.get(i);
      blocks.add(0, block);
      block.setFace(this);
    }

    firstCorner = face.firstCorner;
  }

  /**
   * @param block
   *            all blocks in face are added to the end of this face's list
   */
  public void addBack(BlockFace face) {
    for (int i = 0; i < face.blocks.size(); ++i) {
      Block block = face.blocks.get(i);
      blocks.add(block);
      block.setFace(this);
    }

    secondCorner = face.secondCorner;
  }

  /**
   * @param block
   *            block to remove
   * @param createdFace
   *            will be set to the newly created or to null if no face was
   *            created
   * @return true if this was the last block in this face, false if there are
   *         still blocks in this face
   */
  /**
   * @param block
   *            block to remove
   * @param faces
   *            List to all faces of the same facePlace as this. Faces may be
   *            removed or added.
   */
  public void remove(Block block, List<BlockFace> faces) {
    BlockFace createdFace = null;

    int index = blocks.indexOf(block);
    if (index < 0)
      throw new IllegalArgumentException(block + " is not part of this face.");

    Vector2f blockFirstCorner = getFirstCorner(block);
    Vector2f blockSecondCorner = getSecondCorner(block);

    // adjust corner of block to remove if at one end of the face
    if (blocks.size() == 1) {
      faces.remove(this);
    } else if (index == 0) {
      firstCorner = blockSecondCorner;
    } else if (index == blocks.size() - 1) {
      secondCorner = blockFirstCorner;
    } else {
      // split the face into two parts
      secondCorner = blockFirstCorner;
      createdFace = new BlockFace(blocks.get(index + 1), facePlace);
      blocks.remove(index + 1);
      while (blocks.size() > index + 1) {
        createdFace.addBack(blocks.get(index + 1));
        blocks.remove(index + 1);
      }
    }

    if (createdFace != null)
      faces.add(createdFace);

    block.removeFace(facePlace);
    blocks.remove(index);
  }

  public Block.FacePlace getFacePlace() {
    return facePlace;
  }

  public Vector2f getFirstCorner() {
    return firstCorner;
  }

  public Vector2f getSecondCorner() {
    return secondCorner;
  }

  /**
   * Sets new corner position and removes all blocks which are outside the new
   * corners.
   *
   * @param firstCorner
   *            New position of the first corner. Must not be beyond second
   *            corner.
   */
  public void setFirstCorner(Vector2f firstCorner) {
    switch (facePlace) {
    case LEFT:
    case RIGHT:
      while (blocks.getFirst().getCornerPos(CornerPlace.BOTTOM_RIGHT).y >= firstCorner.y) {
        blocks.getFirst().removeFace(facePlace);
        blocks.removeFirst();
      }
      break;

    case TOP:
    case BOTTOM:
      while (blocks.getFirst().getCornerPos(CornerPlace.BOTTOM_RIGHT).x <= firstCorner.x) {
        blocks.getFirst().removeFace(facePlace);
        blocks.removeFirst();
      }
      break;
    }

    this.firstCorner = new Vector2f(firstCorner.x, firstCorner.y);
  }

  /**
   * Sets new corner position and removes all blocks which are outside the new
   * corners.
   *
   * @param secondCorner
   *            New position of the second corner. Must not be beyond first
   *            corner.
   */
  public void setSecondCorner(Vector2f secondCorner) {
    switch (facePlace) {
    case LEFT:
    case RIGHT:
      while (blocks.getLast().getCornerPos(CornerPlace.TOP_LEFT).y <= secondCorner.y) {
        blocks.getLast().removeFace(facePlace);
        blocks.removeLast();
      }
      break;

    case TOP:
    case BOTTOM:
      while (blocks.getLast().getCornerPos(CornerPlace.TOP_LEFT).x >= secondCorner.x) {
        blocks.getLast().removeFace(facePlace);
        blocks.removeLast();
      }
      break;
    }

    this.secondCorner = new Vector2f(secondCorner.x, secondCorner.y);
  }

  public List<Block> getBlocks() {
    return blocks;
  }

  /**
   * @param position
   *            the position of the block
   * @return block nearest to position
   */
  public Block getBlockAt(Vector2f position) {
    Block block = blocks.get(0);

    switch (facePlace) {
    case LEFT:
    case RIGHT:
      // go down until upper corner of block is below position
      for (Block b : blocks) {
        if (b.getCornerPos(CornerPlace.TOP_LEFT).y >= position.y)
          block = b;
        else
          break;
      }
      break;

    case TOP:
    case BOTTOM:
      // go right until left corner of block is to the right of position
      for (Block b : blocks) {
        if (b.getCornerPos(CornerPlace.TOP_LEFT).x <= position.x)
          block = b;
        else
          break;
      }
      break;
    }

    return block;
  }
}
TOP

Related Classes of ponkOut.logic.BlockFace

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.