diff --git a/src/de/teamteamteam/spacescooter/level/LevelConfig.java b/src/de/teamteamteam/spacescooter/level/LevelConfig.java new file mode 100644 index 0000000..e6d43da --- /dev/null +++ b/src/de/teamteamteam/spacescooter/level/LevelConfig.java @@ -0,0 +1,99 @@ +package de.teamteamteam.spacescooter.level; + +import java.util.ArrayList; +import java.util.List; + +public class LevelConfig { + + public String name; + public String background; + public String backgroundMusic; + public String bossEnemy; + + /** + * Intervals have a start and an end. + * They are put within this list in a sorted manner, ascending in values. + * They are guaranteed to not overlap. + */ + public List intervalList; + + /** + * The entitySpawnRules are encoded here. + * The first index is simply the number of the rule. + * The second index reveals the values of the rule: + * - 0: Interval this rule belongs to + * - 1: EntityNumber - This helps to find out what Entity to actually spawn. + * - 2: Amount - The amount of Entities to spawn at a time. + * - 3: SpawnRate - The rate at which the Entities are supposed to be spawned. + */ + public List ruleList; + + + public LevelConfig() { + this.intervalList = new ArrayList(); + this.ruleList = new ArrayList(); + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("[LevelConfig"); + sb.append(" name="); + sb.append(this.name); + sb.append(" background="); + sb.append(this.background); + sb.append(" backgroundMusic="); + sb.append(this.backgroundMusic); + sb.append(" bossEnemy="); + sb.append(this.bossEnemy); + sb.append("\\\n\tRules:\n"); + for(int[] rule : this.ruleList) { + sb.append("\t"); + sb.append(rule); + sb.append("\n"); + } + sb.append("]"); + return sb.toString(); + } + + /** + * Add a given interval to the list in case it is not a duplicate. + * TODO: Catch overlapping intervals and more! + */ + public void addIntervalToList(int intervalStart, int intervalEnd) { + if(this.getIntervalByBorders(intervalStart, intervalEnd) != -1) { + System.err.println("Duplicate interval - not added!"); + } else { + int[] newInterval= {intervalStart, intervalEnd}; + this.intervalList.add(newInterval); + } + } + + /** + * Return index of given interval. + * Returns -1 in case the interval is not in the list. + */ + public int getIntervalByBorders(int intervalStart, int intervalEnd) { + for(int[] interval : this.intervalList) { + if(interval[0] == intervalStart && interval[1] == intervalEnd) { + return this.intervalList.indexOf(interval); + } + } + return -1; + } + + /** + * Add a given EntitySpawnRule to the ruleList. + */ + public void addEntitySpawnRule(int intervalStart, int intervalEnd, String enemyName, int amount, int spawnRate) { + System.out.println("Adding rule for " + intervalStart + " to " + intervalEnd + ": " + enemyName + ", " + amount + ", " + spawnRate); + if(this.getIntervalByBorders(intervalStart, intervalEnd) == -1) { + System.err.println("No Interval for rule found!"); + System.err.println("Rule: " + intervalStart + " to " + intervalEnd + ": " + enemyName + ", " + amount + ", " + spawnRate); + } else { + int enemyNumber = -1; //TODO: implement this! + int[] newRule = {enemyNumber, amount, spawnRate}; + this.ruleList.add(newRule); + } + } + +} diff --git a/src/de/teamteamteam/spacescooter/level/LevelConfigParser.java b/src/de/teamteamteam/spacescooter/level/LevelConfigParser.java new file mode 100644 index 0000000..aa22479 --- /dev/null +++ b/src/de/teamteamteam/spacescooter/level/LevelConfigParser.java @@ -0,0 +1,137 @@ +package de.teamteamteam.spacescooter.level; + +import java.io.File; +import java.util.Scanner; + +public class LevelConfigParser { + + /* DEBUG */ + public static void main(String[] args) { + LevelConfigParser lcp = new LevelConfigParser(); + LevelConfig lc = lcp.parse("/home/stud/timmeja/Programmierprojekt/SpaceScooter/src/de/teamteamteam/spacescooter/level/temp.properties"); + System.out.println(lc); + } + + + /** + * Internal LevelConfig instance to fill with data. + */ + private LevelConfig levelConfig; + + /** + * Internal Scanner instance on the current file. + */ + private Scanner scanner; + + /** + * Parse mode determining what to look out for. + */ + private int parseMode; + + /** + * The start of the last read interval. + */ + private int currentIntervalStart; + + /** + * The end of the last read interval. + */ + private int currentIntervalEnd; + + + /** + * Constructor. Initialize most internals to a safe state. + */ + public LevelConfigParser() { + this.reset(); + } + + + /** + * Takes a given configFile and turns it into a LevelConfig object. + */ + public LevelConfig parse(String configFile) { + this.reset(); + this.prepareScanner(configFile); + while (this.scanner.hasNextLine()) { + String line = this.scanner.nextLine().trim(); // Get next line trimmed. + if(line.startsWith("#") || line.equals("")) continue; // Skip comments and empty lines. + if(line.equals("-")) { //increase parse mode and continue. + this.parseMode++; + continue; + } + switch(parseMode) { + case 0: + // Handle configurable attributes + if (line.contains(":")) { + String[] linePieces = line.split(":", 2); + // If the attribute is known, set it. + if (linePieces[0].equals("name")) { + this.levelConfig.name = linePieces[1]; + } else if (linePieces[0].equals("background")) { + this.levelConfig.background = linePieces[1]; + } else if (linePieces[0].equals("backgroundMusic")) { + this.levelConfig.backgroundMusic = linePieces[1]; + } else if (linePieces[0].equals("bossEnemy")) { + this.levelConfig.bossEnemy = linePieces[1]; + } else { + System.err.println("[LevelConfigParser] Unknown attribute in line: '" + line + "'"); + } + } + break; + case 1: + if (line.startsWith("[") && line.endsWith("]")) { //Handle interval definition + String interval = line.substring(1, line.length() - 1); + String[] intervalBorder = interval.split("-", 2); + this.currentIntervalStart = Integer.parseInt(intervalBorder[0]); + this.currentIntervalEnd = Integer.parseInt(intervalBorder[1]); + this.levelConfig.addIntervalToList(this.currentIntervalStart, this.currentIntervalEnd); + } else { + String[] entitySpawnRule = line.split(",", 3); + this.levelConfig.addEntitySpawnRule(this.currentIntervalStart, this.currentIntervalEnd, entitySpawnRule[0], Integer.parseInt(entitySpawnRule[1]), Integer.parseInt(entitySpawnRule[2])); + } + break; + default: + System.err.println("[LevelConfigParser] Where am i?!"); + this.printUnknownLine(line); + break; + } + } + return this.levelConfig; + } + + /** + * Prepares a Scanner for the file to parse. + */ + private void prepareScanner(String filename) { + try { + this.scanner = new Scanner(new File(filename)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Reset internal parser state. + */ + private void reset() { + this.parseMode = 0; + this.levelConfig = new LevelConfig(); + this.currentIntervalStart = -1; + this.currentIntervalEnd = -1; + if(this.scanner != null) { + this.scanner.close(); + this.scanner = null; + } + } + + /** + * Debugging method - print an unknown line read. + */ + private void printUnknownLine(String line) { + System.err.println("[LevelConfigParser] Unknown line?"); + System.err.println(line); + System.err.println(); + } + +} diff --git a/src/de/teamteamteam/spacescooter/level/temp.properties b/src/de/teamteamteam/spacescooter/level/temp.properties new file mode 100644 index 0000000..2b2c261 --- /dev/null +++ b/src/de/teamteamteam/spacescooter/level/temp.properties @@ -0,0 +1,10 @@ +name:Lustiger Levelname +backgroundMusic:music/bla.wav +background:FooBackground +bossEnemy:TheBigOne +- +[0-2025] +GegnerOne,2,6 +[2026-2168] +GegnerOne,2,4 +GegnerTwo,5,6 \ No newline at end of file