You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

241 lines
6.3 KiB

/**
* Copyright 2022 Jamie Munro, Distributed under the Common Public Attribution License Version 1.0 (CPAL-1.0)
* Tile engine
*/
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
/**
* Level class
* Represents a level/map
*/
class Level {
private Configuration conf;
private TileProperties props;
private String name;
private int startX;
private int startY;
private int cols;
private int rows;
private Tile[][] tileset;
private Tile emptyTile;
/**
* Constructor
*/
public Level(Configuration config, TileProperties properties) {
conf = config;
props = properties;
emptyTile = new Tile(conf.emptyTile, -1, -1, props);
}
/**
* Retrives the tile at the specified location (0-indexed)
* Returns the empty tile (id=0) if there is no tile at that location
* @param col column (x co-ordinate)
* @param row row (y co-ordainate)
* @return tile at (col, row)
* @throws IOException
*/
public Tile getTile(int col, int row) {
if ((col >= 0) && (col < this.cols) && (row >= 0) && (row < this.rows)) {
return this.tileset[row][col];
}
else {
return emptyTile;
}
}
/**
* Getter for level name
* @return name of level
*/
public String getName() {
return this.name;
}
/**
* Getter for cols
* @return total number of columns (0-indexed)
*/
public int getCols() {
return this.cols;
}
/**
* Getter for rows
* @return total number of rows (0-indexed)
*/
public int getRows() {
return this.rows;
}
/**
* Getter for startX
* @return intended starting row/x-position for player
*/
public int getStartX() {
return this.startX;
}
/**
* Getter for startY
* @return intended starting col/y-position for player
*/
public int getStartY() {
return this.startY;
}
/**
* Loads a level from CSV into this instance
* @param filepath filepath to load from
* @throws Exception if file cannot be found or level is invalid
*/
public void loadLevel(String filepath) throws Exception {
BufferedReader reader;
//try to load properties file from filepath, and failing that try to load from jar
if (new File(filepath).exists()) {
reader = new BufferedReader(new FileReader(filepath));
}
else {
reader = new BufferedReader(new InputStreamReader(this.getClass().getResourceAsStream("/" + filepath)));
}
String firstLine = reader.readLine();
if (firstLine == null) {
reader.close();
throw new IOException("Invalid Level");
}
else {
String[] metaData = firstLine.split(",");
this.name = metaData[0];
this.startX = Integer.parseInt(metaData[1]);
this.startY = Integer.parseInt(metaData[2]);
}
List<List<Tile>> tileMatrix = new ArrayList<List<Tile>>();
String line;
int row = 0;
while((line = reader.readLine()) != null) {
String[] lineItems = line.split(",");
List<Tile> tileRow = new ArrayList<Tile>();
for (int col = 0; col < lineItems.length; col++) {
int id = Integer.parseInt(lineItems[col]);
Tile tile = new Tile(id, col, row, props);
tileRow.add(tile);
}
tileMatrix.add(tileRow);
row++;
}
reader.close();
this.rows = tileMatrix.size();
this.cols = tileMatrix.get(0).size();
this.tileset = new Tile[this.rows][this.cols];
for (row = 0; row < this.rows; row++) {
for (int col = 0; col < this.cols; col++) {
this.tileset[row][col] = tileMatrix.get(row).get(col);
}
}
}
/**
* Generates an empty level with a border
* @param levelWidth width in tiles of generated level
* @param levelHeight height in tiles of generated level
* @param emptyTileId id of tile to place in interior of level
* @param boundaryTileId of tile to place around the edge of the level
*/
public void generateEmptyLevel(int levelWidth, int levelHeight, int emptyTileId, int boundaryTileId) {
this.cols = levelWidth;
this.rows = levelHeight;
this.tileset = new Tile[this.rows][this.cols];
for (int row = 0; row < this.rows; row++) {
for (int col = 0; col < this.cols; col++) {
if ((row == 0) || (row == this.rows - 1) || (col == 0) || (col == this.cols - 1)) {
this.tileset[row][col] = new Tile(boundaryTileId, col, row, props);
}
else {
this.tileset[row][col] = new Tile(emptyTileId, col, row, props);
}
}
}
this.name = "Empty Level";
this.startX = this.cols / 2;
this.startY = this.rows / 2;
}
/**
* Generates a level consisting of random tiles with a border
* @param levelWidth width in tiles of generated level
* @param levelHeight height in tiles of generated level
* @param minId minimum id of tiles to place in interior of level
* @param maxId maximum id of tiles to place in interior of level
* @param boundaryTileId of tile to place around the edge of the level
* @param probability of selecting tile with ID minID %
*/
public void generateRandomLevel(int levelWidth, int levelHeight, int minId, int maxId, int boundaryTileId, int p0) {
this.cols = levelWidth;
this.rows = levelHeight;
this.tileset = new Tile[this.rows][this.cols];
for (int row = 0; row < this.rows; row++) {
for (int col = 0; col < this.cols; col++) {
if ((row == 0) || (row == this.rows - 1) || (col == 0) || (col == this.cols - 1)) {
this.tileset[row][col] = new Tile(boundaryTileId, col, row, props);
}
else {
int randomId = minId;
int r1 = int(random(0, 101));
if (r1 > p0) {
randomId = int(random(minId+1, maxId + 1));
}
this.tileset[row][col] = new Tile(randomId, col, row, props);
}
}
}
this.name = "Randomly generated";
this.startX = this.cols / 2;
this.startY = this.rows / 2;
}
@Override
public String toString() {
String str = "";
for (int row = 0; row < this.rows; row++) {
for (int col = 0; col < this.cols; col++) {
str += this.getTile(col, row) + ",";
}
str += "\n";
}
return str;
}
}