TFGGame/src/tfg/Map.java

186 lines
6.1 KiB
Java

package tfg;
import org.jsfml.graphics.Drawable;
import org.jsfml.graphics.PrimitiveType;
import org.jsfml.graphics.RenderStates;
import org.jsfml.graphics.RenderTarget;
import org.jsfml.graphics.RenderWindow;
import org.jsfml.graphics.Texture;
import org.jsfml.graphics.Vertex;
import org.jsfml.graphics.VertexArray;
import org.jsfml.system.Vector2f;
import org.jsfml.system.Vector2i;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
/**
* A map or level for the player to interact in. Can be created
* manually or procedurally.
* @author Ritchie Cunningham
*/
public class Map implements Drawable {
/**
* The size (length, width) of the map.
*/
private Vector2i dimensions = new Vector2i(0, 0);
private Tile[][] tileArray;
/**
* The tilesheet texture.
*/
private Texture tilesheetTexture = new Texture();
/**
* Vertex array for the tile map.
* This is a streamlined way to draw many sprites at once.
*/
private VertexArray vertexArray = new VertexArray();
private final ArrayList<Entity> entitiesOnMap = new ArrayList<Entity>();
/**
* Create a new map of specified size and tile type.
* @param l Map length.
* @param w Map width.
* @param t Default tile to auto-pupulate map.
*/
public Map(int l, int w, Tile t) {
dimensions = new Vector2i(l,w);
tileArray = new Tile[dimensions.x][dimensions.y];
try {
tilesheetTexture.loadFromFile(Paths.get("res/terrain.png"));
} catch(IOException ex) {
ex.printStackTrace();
}
/* Set vertex array to use quads because the tiles are square. */
vertexArray.setPrimitiveType(PrimitiveType.QUADS);
initializeMap(t); /* Auto-populate the map with specified tile. */
}
/**
* Create a new map of speceified size that default to grass.
* @param l Map length.
* @param w Map width.
*/
public Map(int l, int w) {
this(l,w,Tile.GRASS);
}
/**
* Fill the entire map to the specified tile.
* @param initialTile The tile to populate the map with.
*/
public void initializeMap(Tile initialTile) {
/**
* Arrays.fill does not work with matrices,
* therefore we have to loop through the outer level to fill the inner.
*/
for(Tile[] row : tileArray) {
/* Set each tile in the row to the specified tile. */
Arrays.fill(row,initialTile);
}
}
/**
* Draw the map onto the window.
*/
public void draw(RenderTarget target, RenderStates states) {
vertexArray.clear(); /* empty array from previous draw. */
final int tileSize = Tile.getSize();
/* Iterate through every tile in the map. */
for(int i = 0; i < dimensions.x; i++) {
for(int j = 0; j < dimensions.y; j++) {
Tile tileType = tileArray[i][j]; /* Grab current tile in the loop. */
/* Grab texture coord to render the tile. */
Vector2f textureCoords = Tile.getTextureCoords(tileType);
/*
* Add each corner of the tile to the vertex array
* counter-clockwise.
*/
/* Top left. */
vertexArray.add(new Vertex(
new Vector2f(i*tileSize, j* tileSize), textureCoords));
/* Bottom left. */
vertexArray.add(new Vertex(
new Vector2f(i*tileSize,(j*tileSize)+tileSize),
Vector2f.add(textureCoords, new Vector2f(tileSize,tileSize))));
/* Bottom right. */
vertexArray.add(new Vertex(
new Vector2f((i*tileSize)+tileSize, (j*tileSize)+tileSize),
Vector2f.add(textureCoords, new Vector2f(tileSize,tileSize))));
/* Top right. */
vertexArray.add(new Vertex(
new Vector2f((i*tileSize)+tileSize, j*tileSize),
Vector2f.add(textureCoords, new Vector2f(tileSize,0))));
}
}
/* Apply texture to the vertex array. */
RenderStates newStates = new RenderStates(tilesheetTexture);
vertexArray.draw(target, newStates); /* Draw vertex array. */
}
/**
* Return the tile at specified location.
* @param l Location of the tile to get.
* @return Tile at the specified location.
*/
public Tile getTile(Location l) {
Vector2i position = l.getPosition(); /* Get pos from loc. */
Tile t = tileArray[position.x][position.y]; /* Get tile at this pos. */
return t;
}
/**
* Determine whether or not the location fits within the map.
* @param l Location to test.
* @return If location is valid.
*/
public boolean isValidLocation(Location l) {
Vector2i coordinates = l.getPosition(); /* Pos from last location. */
/* Return true if the location is greater than 0. */
return ((coordinates.x >= 0) && (coordinates.y >=0) &&
(coordinates.x < dimensions.x) &&
(coordinates.y < dimensions.y) &&
Tile.getCanWalkOn(getTile(l)) &&
(getEntityatLocation(l) == null));
}
public Entity getEntityatLocation(Location l) {
Iterator<Entity> it = entitiesOnMap.iterator();
while(it.hasNext()) {
Entity e = it.next();
if(e.getLocation().equals(1)) {
return e;
}
}
return null;
}
public void addEntity(Entity e) {
if(getEntityatLocation(e.getLocation()) == null) {
e.setParentMap(this);
entitiesOnMap.add(e);
}
}
public void drawAllEntities(RenderWindow w) {
for(Entity e : entitiesOnMap) {
w.draw(e);
}
}
public void updateAllEntities() {
Collections.sort(entitiesOnMap);
for(Entity e : entitiesOnMap) {
e.update();
}
}
}