package com.jonathan.survivor;
import java.util.ArrayList;
import java.util.Random;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.utils.Array;
import com.jonathan.survivor.entity.Box;
import com.jonathan.survivor.entity.GameObject;
import com.jonathan.survivor.entity.InteractiveObject.InteractiveState;
import com.jonathan.survivor.entity.ItemObject;
import com.jonathan.survivor.entity.Tree;
import com.jonathan.survivor.entity.Zombie;
import com.jonathan.survivor.managers.GameObjectManager;
import com.jonathan.survivor.math.Vector2;
/**
* Defines the geometry for a layer of terrain. A TerrainLevel contains these layers and manages them.
* @author Clementine
*
*/
public class TerrainLayer
{
/** Stores the row and column of the layer. Note that the row defines the layer's geometry. */
private int row, col;
/** Stores the width and height of a layer. The width is measured from the left end of the layer to the right end. The height
* goes from the bottom y-position to the top y-position of any x-position on the layer. If it is a cosine layer, it does not
* go from the bottom-most point to the top-most point; it is the same regardless. */
public static final float LAYER_WIDTH = 20, LAYER_HEIGHT = 3.5f;
/** Stores the height from any bottom point of the layer to its ground point where the user walks */
public static final float GROUND_HEIGHT = 0.5f;
/** Stores the bottom height of objects on the layer. Increasing this places objects higher on the layer. */
public static final float OBJECT_HEIGHT = 1.0f;
/** Stores the minimum horizontal spacing between GameObjects on a layer. */
public static final float OBJECT_SPACING = 2.0f;
/** Stores the maximum slope a linear layer can have */
public static final float MAX_SLOPE = 0.33f;
/** Stores the minimum slope a linear layer can have */
public static final float MIN_SLOPE = 0.1f;
/** Stores the maximum amplitude a cosine layer can have. (Note that amplitude = half-height of cosine function) */
public static final float MAX_AMPLITUDE = 1;
/** Stores the minimum amplitude a cosine layer can have. (Note that amplitude = half-height of cosine function) */
public static final float MIN_AMPLITUDE = 0.2f;
/** Stores the b-value in a cosine function, the frequency, found by 2pi/period, where the period is the width of the cosine function. */
public static final float COSINE_FREQUENCY = 2 * (float) Math.PI / LAYER_WIDTH;
/** Holds the distance in meters. Determines how close a GameObject has to be to the layer's edge be considered "near" the edge. Used in closeToEdge(...) */
public static final float EDGE_MARGIN = 2;
/** Holds the probability rate (0: lowest chance, 1: highest chance) that a zombie gets spawned on the TerrainLayer. */
public static final float ZOMBIE_PROBABILITY_RATE = 0.5f;
/** Stores the position of the bottom-left and bottom-right ends of the layer. */
private final Vector2 leftPoint, rightPoint;
/** Stores the slope of the layer if it is linear */
private float slope;
/** Stores the amplitude of the layer if it is a cosine function */
private float amplitude;
/** Stores the 'h' variable of the cosine function if the layer is a cosine function */
private float cosineXOffset;
/** Stores the 'k' variable of the cosine function if the layer is a cosine function */
private float cosineYOffset;
public enum TerrainType {
CONSTANT, LINEAR, COSINE
}
/** Stores the type of the terrain layer */
private TerrainType terrainType;
public enum TerrainDirection {
RIGHT, LEFT
};
/** Stores whether the terrain goes from left to right or from right to left. */
private TerrainDirection terrainDirection;
/** Stores the world seed used to randomly generate the geometry of the layer. */
private int worldSeed;
/** Stores the GameObjectManager used to fetch GameObjects to populate the TerrainLayer with objects. */
private GameObjectManager goManager;
/** Stores the random object used to define the terrain geometry of the layer. */
private Random terrainRand;
/** Stores the random object used to define the objects stacked on the layer. */
private Random objectRand;
/** Stores the profile used to create the TerrainLayer. Specifies the world seed, and the GameObjects already scavenged on each layer. */
private Profile profile;
/** Stores an array of all the GameObjects that are on this layer. If gameObjectsStored==true, the array is already populated. Helper array to avoid GC. */
private Array<GameObject> gameObjects = new Array<GameObject>();
/** Stores true if the gameObjects array has already been populated with the correct objects. Prevents having to re-populate the array every frame. */
private boolean gameObjectsStored = false;
/** Holds arrays containing the different types of GameObjects on the layer. */
private Array<Tree> trees = new Array<Tree>();
private Array<Box> boxes = new Array<Box>();
private Array<Zombie> zombies = new Array<Zombie>();
/** Stores an array of all the ItemObjects that have been dropped on this TerrainLayer. These items can be picked up. */
private Array<ItemObject> itemObjects = new Array<ItemObject>();
/** Constructor used to create a terrain layer.
*
* @param row The row of the layer
* @param col The column of the layer
* @param startX The starting x-position of the layer, specified as the left-most x-position of the layer if terrainDirection = RIGHT or the right-most
* x-position of the layer if terrainDirection == LEFT.
* @param startY The starting y-position of the layer, specified as the bottom y-position of either end of the layer.
* @param terrainDirection The direction the terrain faces. If TerrainDirection.RIGHT is specified, the (startX,startY) parameters specify the bottom-left
* end-point of the layer
* @param profile Profile where the layer retrieves the world seed, along with information on which GameObjects have already been scavenged.
* @param goManager The GameObjectManager which manages the World's GameObjects. Used to populate the layer with objects.
*/
public TerrainLayer(int row, int col, float startX, float startY, TerrainDirection terrainDirection, Profile profile, GameObjectManager goManager)
{
//Stores the row and column of the layer
this.row = row;
this.col = col;
//Creates new Vector2s to store the left end-point of the layer and the right end-point of the layer.
leftPoint = new Vector2();
rightPoint = new Vector2();
//Sets the start position of the layer, essentially specifying where in world coordinates the layer should be placed.
setStartPosition(startX, startY, terrainDirection);
//Stores the profile used to revert the layer back to its save-game state.
this.profile = profile;
//Stores the world seed in its respective member variable.
this.worldSeed = profile.getWorldSeed();
//Stores the GameObjectManager instance used by the world in order to populate the terrain with GameObjects.
this.goManager = goManager;
//Creates a new Random object to define the geometry of the layer and the objects it contains.
terrainRand = new Random();
objectRand = new Random();
//Resets the layer by computing its geometry and the objects placed on it.
resetLayer();
}
/** Resets the layer. Re-computes the geometry of the layer and the objects it contains depending on its row and column. Must be called any time the
* layer is re-purposed to fit another row or column. */
public void resetLayer()
{
//Resets the terrain geometry of the layer
resetTerrain();
//Resets the objects placed on the layer.
resetObjects();
}
/** Resets and re-calculates the terrain geometry according to the world seed and the column number of the layer. */
public void resetTerrain()
{
//Stores the seed used for the terrain's geometry. Only the column and the worldSeed are used so that layers in the same column will have the same geometry.
int terrainSeed = col * worldSeed;
//Sets the seed of the terrainRand instance to the new seed. Numbers will be generated to define the geometry of the layer.
terrainRand.setSeed(terrainSeed);
//Gets a random float from [0,1] to define the type of the terrain.
float randType = terrainRand.nextFloat();
//If the random number is above this value
if(randType > 0.5f) //Original: 0.5f
{
//Make the terrain layer have a COSINE geometry by setting its type to COSINE.
terrainType = TerrainType.COSINE;
//Generates a random amplitude for the cosine function between MIN_AMPLITUDE and MAX_AMPLITUDE.
amplitude = MIN_AMPLITUDE + (terrainRand.nextFloat() * (MAX_AMPLITUDE - MIN_AMPLITUDE));
//If a new random float is greater than '0.5', make the amplitude negative to flip the cosine function.
if(terrainRand.nextFloat() > 0.5f)
//Flip the cosine function upside down.
amplitude *= -1;
//If the terrain goes from left to right
if(terrainDirection == TerrainDirection.RIGHT)
{
//Set the right end-point of the layer to the left end-point, plus the width of the layer. Needs to be set since only leftPoint contains a valid value.
rightPoint.set(leftPoint).add(LAYER_WIDTH, 0);
}
//If the terrain goes from right to left
else
{
//Set the left end-point of the layer to be the right end-point, minus layer's width. Needs to be initialized since only 'leftPoint' contains a valid value.
leftPoint.set(rightPoint).sub(LAYER_WIDTH, 0);
}
//Offsets the cosine function by the x-position of the left of the layer. This places the cosine function at the right place in the world.
cosineXOffset = leftPoint.x;
//Offsets the cosine function by the y-position of either end point of the layer, minus the cosine's amplitude. This places the cosine function at the right yPos.
cosineYOffset = leftPoint.y - amplitude;
}
//Else, if the random float is greater than this value
else if(randType > 0.2f)
{
//Make the terrain a linear terrain, modeled by a linear equation.
terrainType = TerrainType.LINEAR;
//Generate a random slope for the layer.
slope = MIN_SLOPE + (terrainRand.nextFloat() * (MAX_SLOPE-MIN_SLOPE));
//if(terrainRand.nextFloat() > 0.5f)
//slope *= -1;
//If the terrain goes from left to right
if(terrainDirection == TerrainDirection.RIGHT)
{
//Find the x-position of the right end point of the layer by adding the layer width to the left end-point's x-position.
float x = leftPoint.x + LAYER_WIDTH;
//Find the y-position of the right end point of the layer using y = ax + b, by multiplying the line's slope by the x position from the y-intercept, which
//is LAYER_WIDTH, since the left end-point's x-position is the origin, and leftPoint.y is the y-intercept.
float y = slope * LAYER_WIDTH + leftPoint.y;
//Set the right end-point of the layer to the calculated position.
rightPoint.set(x, y);
}
//If the terrain goes from right to left
else
{
//Find the x-position of the left end point of the layer by subtracting the layer width from the right end-point's x-position.
float x = rightPoint.x - LAYER_WIDTH;
//Find the y-position of the left end point of the layer using y = ax + b, by multiplying the line's slope by the x position from the y-intercept, which
//is x = -LAYER_WIDTH, since the right end-point's x-position is the origin, and leftPoint.x is at x = 0.
float y = slope * -LAYER_WIDTH + rightPoint.y;
//Sets the left end-point's position for the layer to the computed position above.
leftPoint.set(x, y);
}
}
//Else, if we are here, the random number stored in randType:float dictates that the layer should be a constant function.
else
{
//Set the terrain type of the layer to be a constant function.
terrainType = TerrainType.CONSTANT;
//Set the slope of the line to zero.
slope = 0;
//If the terrain goes from left to right
if(terrainDirection == TerrainDirection.RIGHT)
{
//Set the right end-point of the layer to the left end-point, plus the width of the layer. Needs to be set since only leftPoint contains a valid value.
rightPoint.set(leftPoint).add(LAYER_WIDTH, 0);
}
//If the terrain goes from right to left
else
{
//Set the left end-point of the layer to be the right end-point, minus layer's width. Needs to be initialized since only 'leftPoint' contains a valid value.
leftPoint.set(rightPoint).sub(LAYER_WIDTH, 0);
}
}
}
/** Resets the objects placed on the layer. This essentially places the correct objects on the layer depending on its column and row. */
public void resetObjects()
{
//The object seed is determined by the row and the column of the layer. To make sure every world's layers have different objects, we
//add the world seed to the sum of the row and the column.
int objectSeed = row + col + worldSeed;
//Sets the seed of the objectRand instance to the new seed. Numbers will be generated to define the which objects are on the layer.
objectRand.setSeed(objectSeed);
//Stores a list of objectIds for the GameObjects that have already been scavenged on this layer.
ArrayList<Integer> scavengedObjects = profile.getScavengedLayerObjects(row, col);
//Stores the index of the object being placed on the layer. Starts at 0 for the left-most object, and increments by one for each object.
int objectIndex = 0;
//Cycles from the left-most x-point of the layer, plus an offset, and increments by the object spacing until the end x-point is reached.
for(float x = leftPoint.x + OBJECT_SPACING; x < rightPoint.x; x += OBJECT_SPACING)
{
//Stores a random number between 0 and 1 to determine which object will be placed next on the layer.
float randObject = objectRand.nextFloat();
if(randObject > 0.5f)
{
//If the object we want to place has not been scavenged, place it on the TerrainLayer.
if(!scavengedObjects.contains(objectIndex))
{
//Retrieves a tree GameObject from a pool inside the GameObjectManager.
Tree tree = goManager.getGameObject(Tree.class);
//Tell the tree that it has just spawned
tree.setInteractiveState(InteractiveState.SPAWN);
//Sets the terrain cell to the layer's row and column so that the tree knows which layer it is in.
tree.setTerrainCell(row, col);
//Positions the tree at the current x-position, and the correct y-position according to the object height at the given x-position.
tree.setPosition(x, getObjectHeight(x));
//Set the object id of the tree to the current object index. Used to identify a scavenged GameObject in save data.
tree.setObjectId(objectIndex);
//Add the tree GameObject to the array of trees held by the layer.
trees.add(tree);
}
//Increment the object index for the next GameObject to be placed on the layer.
objectIndex++;
//Increment x by the width of the tree so that the next object doesn't overlap.
x += Tree.COLLIDER_WIDTH / 2;
}
else if(randObject > 0.45f)
{
//If the object we want to place has not yet been scavenged, place it on the TerrainLayer.
if(!scavengedObjects.contains(objectIndex))
{
//Retrieves a box GameObject from a pool inside the GameObjectManager.
Box box = goManager.getGameObject(Box.class);
//Tell the box that it has just spawned
box.setInteractiveState(InteractiveState.SPAWN);
//Sets the terrain cell to the layer's row and column so that the box knows which layer it is in.
box.setTerrainCell(row, col);
//Positions the box at the current x-position, and the correct y-position according to the object height at the given x-position.
box.setPosition(x, getObjectHeight(x));
//Set the object id of the box to the current object index. Used to identify a scavenged GameObject in save data.
box.setObjectId(objectIndex);
//Add the box GameObject to the array of boxes held by the layer.
boxes.add(box);
}
//Increment the object index for the next GameObject to be placed on the layer.
objectIndex++;
//Increment x by the width of the box's collider so that the next object doesn't overlap with this box.
x += Box.COLLIDER_WIDTH / 2;
}
}
//Generates a new random number between 0 and 1 which dictates whether or not a zombie will be spawned in the center of the TerrainLayer.
float randZombie = objectRand.nextFloat();
//If the random number is less than the zombie probability rate, place a zombie on the layer. However, the layer has to be checked to make sure that a zombie can spawn on it.
if(randZombie < ZOMBIE_PROBABILITY_RATE && canSpawnZombie())
{
//If the zombie has not yet been killed on the TerrainLayer, spawn him there.
if(!scavengedObjects.contains(objectIndex))
{
//Retrieves a Zombie GameObject from the GameObjectManager.
Zombie zombie = goManager.getGameObject(Zombie.class);
//Sets the zombie's terrain cell to the layer's row and column so that the zombie knows which layer it is in.
zombie.setTerrainCell(row, col);
//Places the zombie at the center of the TerrainLayer.
zombie.setPosition(getCenterX() - 2, getGroundHeight(getCenterX() - 2));
//Set the object id of the box to the current object index. Used to identify a scavenged GameObject in save data.
zombie.setObjectId(objectIndex);
//Add the zombie into the list of zombies inside the layer.
zombies.add(zombie);
}
//Increment the object index for the next GameObject that is placed on the layer.
objectIndex++;
}
}
/** Returns true if a zombie can be spawned on this layer. The only reason it could not spawn is if this layer is the one where the player has spawned. */
private boolean canSpawnZombie()
{
//Retrieves the terrain coordinates where the player is first spawned.
int playerSpawnRow = profile.getTerrainRowOffset() + TerrainLevel.NUM_LAYER_ROWS/2;
int playerSpawnCol = profile.getTerrainColOffset() + TerrainLevel.NUM_LAYER_COLS/2;
//If this layer is the same layer where the player is spawned
if(row == playerSpawnRow && col == playerSpawnCol)
{
//Return false, since a zombie should not spawn right next to the player when the game starts.
return false;
}
//If this statement is reached, the zombie can be spawned on this layer. In fact, this layer is not the one where the player first spawns.
return true;
}
/** Frees the GameObjects stored inside the layer. Puts them back into the GameObjectManager's pools, so that they can be reused. Called when the layer
* should be re-purposed into another layer. */
public void freeGameObjects()
{
//Cycles through the array of tree GameObjects belonging to the layer
for(int i = 0; i < trees.size; i++)
//Frees the trees back into the pool of the GameObjectManager for later reuse.
goManager.freeGameObject(trees.get(i), Tree.class);
//Cycles through the array of box GameObjects belonging to the layer
for(int i = 0; i < boxes.size; i++)
//Frees the boxes back into the pool of the GameObjectManager for later reuse.
goManager.freeGameObject(boxes.get(i), Box.class);
//Cycles through the array of Zombies, which must be freed back into the GameObjectManager's internal pools.
for(int i = 0; i < zombies.size; i++)
//Frees the Zombies back into their respective pool inside the GameObjectManager so that they can be reused once more Zombies are spawned.
goManager.freeGameObject(zombies.get(i), Zombie.class);
//Cycles through the array of ItemObjects, which must be freed back into the GameObjectManager's internal pools.
for(int i = 0; i < itemObjects.size; i++)
//Frees the ItemObjects back into their respective pool inside the GameObjectManager so that they can be reused once more ItemObjects are dropped.
goManager.freeGameObject(itemObjects.get(i), ItemObject.class);
//Clears the array of all the GameObjects contained by the TerrainLayer so that they can be re-populated with new GameObjects when resetLayer() is called.
trees.clear();
boxes.clear();
zombies.clear();
itemObjects.clear();
//Clears the array which contains a list of all the GameObjects on this layer. Allows us to repopulate the array once the layer is reused.
gameObjects.clear();
//Tells the getGameObjects() that it has to re-populate its gameObjects array since there we just cleared it.
gameObjectsStored = false;
}
/** Adds the given GameObject to the list of GameObjects contained by the TerrainLayer. This way, the GameObjectRenderer will know to render this GameObject. */
public void addGameObject(GameObject gameObject)
{
//If the GameObject we want to add is an ItemObject, then a collectible has just been dropped on the ground.
if(gameObject instanceof ItemObject)
//Add the ItemObject to the list of Item GameObjects contained by this TerrainLayer.
itemObjects.add((ItemObject)gameObject);
//Else, if the GameObject to add to the layer is a zombie
else if(gameObject instanceof Zombie)
//Adds the zombie to the list of zombies contained in the layer.
zombies.add((Zombie)gameObject);
//Add the GameObject to the list of all GameObjects contained in the TerrainLayer.
gameObjects.add(gameObject);
}
/** Removes the given GameObject from the list of GameObjects contained by the TerrainLayer. The GameObjectRenderer will know that it should not render the GameObject. */
public void removeGameObject(GameObject gameObject)
{
//If the GameObject we want to add is an ItemObject, then a collectible has just been removed from the ground. NEVER CALLED. Pre-mature implementation.
if(gameObject instanceof ItemObject)
{
//Removes the ItemObject from the list of Item GameObjects contained by this TerrainLayer.
itemObjects.removeValue((ItemObject)gameObject, true);
}
//Else, if the GameObject to remove is a zombie
else if(gameObject instanceof Zombie)
{
//Removes the zombie from the list of zombies contained in the layer.
zombies.removeValue((Zombie)gameObject, true);
}
//Removes the GameObject from the list of all GameObjects contained in the TerrainLayer.
gameObjects.removeValue(gameObject, true);
}
/** Returns an array of all GameObjects contained in this layer. */
public Array<GameObject> getGameObjects()
{
//If the gameObjects array hasn't yet been populated
if(!gameObjectsStored)
{
//Add all the GameObjects from the layer into the gameObjects array.
gameObjects.addAll(trees);
gameObjects.addAll(boxes);
gameObjects.addAll(zombies);
gameObjects.addAll(itemObjects);
//Tell the layer that all of its GameObjects have been stored inside the array, to avoid doing so every frame.
gameObjectsStored = true;
}
//Returns the array containing all of the layer's GameObjects.
return gameObjects;
}
/** Returns an array consisting of all the Tree GameObjects that are on this layer. */
public Array<Tree> getTrees()
{
//Returns the trees array, which contains all of the trees held by the layer.
return trees;
}
/** Returns an array containing all the Box GameObjects that are on this layer. */
public Array<Box> getBoxes()
{
//Returns the boxes array, which contains all of the boxes held by the layer.
return boxes;
}
/** Returns an array containing all the Zombies GameObjects that are on this layer. */
public Array<Zombie> getZombies()
{
//Returns the 'zombies' array, which contains all of the zombies held by the layer.
return zombies;
}
/** Returns an array consisting of all the Item GameObjects that have been dropped on this layer and have yet to be picked up. */
public Array<ItemObject> getItemObjects()
{
//Returns the itemObjects array, which contains all of the itemObjects held by the layer.
return itemObjects;
}
/** Returns true if the given GameObject is close to the edge of this TerrainLayer. */
public boolean closeToEdge(GameObject gameObject)
{
//Stores the gameObject's x-position. The y-position is irrelevant in check if the GameObject is close to the layer's edge.
float xPos = gameObject.getX();
//If the GameObject is within 'EDGE_MARGIN' distance from either end point of the layer, it is considered "close to the edge"
if(rightPoint.x - xPos < EDGE_MARGIN || xPos - leftPoint.x < EDGE_MARGIN)
{
//Thus, return true, since the GameObject is close to the edge
return true;
}
//If this statement is reached, the GameObject is not close to the edge of the layer. Thus, return false.
return false;
}
/** Gets the world x-position at the center of the terrain layer */
public float getCenterX()
{
//Returns the x-position of the left end-point, plus half the width of the layer.
return leftPoint.x + LAYER_WIDTH/2;
}
/** Gets the height of the ground at the center of the layer in world units. */
public float getCenterGroundHeight()
{
//Returns the ground height at the center of the layer.
return getGroundHeight(getCenterX());
}
/** Gets the ground height at any given x-position of the layer in world units. */
public float getGroundHeight(float xPos)
{
//Returns the height of the bottom of the layer, plus the height of the ground.
return getBottomLayerHeight(xPos) + GROUND_HEIGHT;
}
/** Gets the GameObject height at any given x-position on the layer in world units. */
public float getObjectHeight(float xPos)
{
//Returns the height of the bottom of the layer, plus the height of the GameObjects from the bottom of the layer.
return getBottomLayerHeight(xPos) + OBJECT_HEIGHT;
}
/** Returns the y-position of the top of the layer at any given x-position in world units. */
public float getTopLayerHeight(float xPos)
{
//Returns the y-position of the bottom of the layer at the given x-position, plus the height of the layer, which is the distance from
//the bottom to the top of the layer at any x-position.
return getBottomLayerHeight(xPos) + LAYER_HEIGHT;
}
/** Retrieves the height of the bottom portion of the layer at a specified x-position. */
public float getBottomLayerHeight(float xPos)
{
//If the x-position is beyond the bounds of the layer, throw an exception.
if(xPos < leftPoint.x || xPos > rightPoint.x)
throw new IllegalArgumentException("X-Position out of bounds of level layer (" + row + ", " + col + "). Position "
+ xPos + " not between " + leftPoint.x + " and " + rightPoint.x);
//If the terrain is modeled using a cosine function
if(terrainType == TerrainType.COSINE)
{
//Return the y-position of the layer at a specified x-position using the equation y = acos(b(x - h)) + k. This is the bottom portion since cosineYOffset
//specifies the y-position of the bottom-most point of the layer.
return amplitude * MathUtils.cos(COSINE_FREQUENCY * (xPos - cosineXOffset)) + cosineYOffset;
}
else if(terrainType == TerrainType.LINEAR)
{
//Retrieve and return the y-position of the bottom portion of the layer at a given x using y = ax + b, where 'b' is the y-position of the left end-point.
return slope * (xPos - leftPoint.x) + leftPoint.y;
}
//Else, if we are here, the layer is modeled using a constant function. Thus, the y-position of any point on the bottom half of the layer is left/rightPoint.y
return leftPoint.y;
}
/** Sets the cell coordinates of the layer. The resetLayer() method must be called after this. */
public void setCell(int row, int col)
{
this.row = row;
this.col = col;
}
/** Sets the row of the layer. The resetLayer() method must be called after this. */
public void setRow(int row)
{
this.row = row;
}
/** Gets the row of the layer. */
public int getRow()
{
return row;
}
/** Sets the column of the layer. The resetLayer() method must be called after this. */
public void setCol(int col)
{
this.col = col;
}
/** Gets the column placement of the layer. */
public int getCol()
{
return col;
}
/** Sets the start position of the terrain layer. Note that the specified position must either be the coordinates for the bottom-left or bottom-right position
* of the layer in world coordinates. If terrainDirection == TerrainDirection.RIGHT, the left coordinate must be specified. If TerrainDirection.LEFT is passed,
* the right end-position must be specified.
*/
public void setStartPosition(float startX, float startY, TerrainDirection terrainDirection)
{
//Stores the terrainDirection passed from the method.
this.terrainDirection = terrainDirection;
//If the desired terrain direction is from left to right
if(terrainDirection == TerrainDirection.RIGHT)
{
//The (startX,startY) parameters specify the bottom-left point of the layer.
leftPoint.set(startX, startY);
}
//Else, if the desired terrain direction is from right to left
else
{
//The (startX,startY) parameters specify the bottom-right end-point of the layer.
rightPoint.set(startX, startY);
}
}
/** Returns the bottom-left end point of the layer in world coordinates. */
public Vector2 getLeftPoint()
{
return leftPoint;
}
/** Returns the bottom-right end point of the layer in world coordinates. */
public Vector2 getRightPoint()
{
return rightPoint;
}
/** Gets the terrain type of the layer, dictating what type of equation models its geometry. */
public TerrainType getTerrainType()
{
return terrainType;
}
public String toString()
{
return "Left Point: " + leftPoint + ", Right Point: " + rightPoint;
}
}