diff --git a/src/dk/itu/mario/level/LevelComponent.java b/src/dk/itu/mario/level/LevelComponent.java index 161c838..f68064d 100644 --- a/src/dk/itu/mario/level/LevelComponent.java +++ b/src/dk/itu/mario/level/LevelComponent.java @@ -1,30 +1,40 @@ package dk.itu.mario.level; public class LevelComponent { - public enum TYPE { FLAT, PIPES, MAZE}; - + public enum TYPE { + FLAT, PIPE_JUMP, PLATFORM_JUMP, MAZE + }; + + public enum MazeLevel { + BOT, MID, TOP + } + + public enum PlatformLevel { + BOT, MID_D, MID_U, TOP + } + private TYPE type; private int start; private int end; - + public LevelComponent(TYPE type, int start, int end) { this.type = type; this.end = end; this.start = start; } - + public TYPE getType() { return type; } - + public int getStart() { return start; } - + public int getEnd() { return end; } - + @Override public String toString() { return type + "[" + start + ".." + end + "]"; diff --git a/src/dk/itu/mario/level/PCGLevel.java b/src/dk/itu/mario/level/PCGLevel.java index e261698..4ae60a6 100644 --- a/src/dk/itu/mario/level/PCGLevel.java +++ b/src/dk/itu/mario/level/PCGLevel.java @@ -43,8 +43,8 @@ public class PCGLevel extends Level { super(width, height); } - public PCGLevel(int width, int height, long seed, int difficulty, - int type, GamePlay playerMetrics) { + public PCGLevel(int width, int height, long seed, int difficulty, int type, + GamePlay playerMetrics) { this(width, height); System.out @@ -54,8 +54,8 @@ public class PCGLevel extends Level { generateLevel(seed, playerMetrics); } - public PCGLevel(int width, int height, long seed, int difficulty, - int type, GamePlay playerMetrics, DataRecorder dataRecorder) { + public PCGLevel(int width, int height, long seed, int difficulty, int type, + GamePlay playerMetrics, DataRecorder dataRecorder) { this(width, height); System.out @@ -128,42 +128,48 @@ public class PCGLevel extends Level { System.out.println("Generating level for component list: "); LevelParseTree parseTree = grammar.generateRandomTree(seed, width); List levelTemplate = parseTree.getLevelTemplate(); - + int length = 0; - + for (LevelComponent lcomp : levelTemplate) { LevelComponent.TYPE lctype = lcomp.getType(); System.out.println("Building for: " + lcomp); switch (lctype) { - case FLAT: - while (length < Math.min(width-64,lcomp.getEnd())) { - length += buildStraight(length, lcomp.getEnd(), true); - } + case FLAT: + length += buildStraight(length, lcomp.getEnd(), true); break; - default : - System.out.println("Cannot build level segment for unrecognized LevelComponent type: " + type); + case PIPE_JUMP: + length += buildPipeJump(length, width-64-length); + break; + case PLATFORM_JUMP: + length += buildPlatformJump(length, width-64-length); + break; + case MAZE: + length += buildMaze(length, width-64-length); + break; + default: + System.out + .println("Cannot build level segment for unrecognized LevelComponent type: " + + type); } } - - System.out.println("Total length built: " + length); - - /* Original non-PCG code: - // create the start location - int length = buildStraight(0, width, true); - length += buildPipeJump(length, width - length); - // length += buildMaze(length, width - length); - // create all of the medium sections - while (length < width - 64) { - length += buildStraight(length, width - length, true); - } - */ + System.out.println("Total length built: " + length); + + /* + * Original non-PCG code: // create the start location int length = + * buildStraight(0, width, true); length += buildPipeJump(length, width + * - length); // length += buildMaze(length, width - length); + * + * // create all of the medium sections while (length < width - 64) { + * length += buildStraight(length, width - length, true); } + */ // set the end piece int floor = height - 1 - random.nextInt(4); xExit = length + 8; yExit = floor; - + fillEndPiece(length, floor); } @@ -196,6 +202,7 @@ public class PCGLevel extends Level { fixWalls(); } + private void addEnemyLine(int x0, int x1, int y) { for (int x = x0; x < x1; x++) { if (random.nextInt(35) < difficulty + 1) { @@ -310,36 +317,42 @@ public class PCGLevel extends Level { private int buildMaze(int xo, int maxLength) { int length = random.nextInt(maxLength - 19) + 20; - int soFar = 0; + int soFar = 6; int next; - // MazeLevel last = MazeLevel.BOT; + // boolean skipUp = false; + // boolean skipDown = false; class Stretch { public int len; - public PCGLevel.MazeLevel lvl; + public LevelComponent.MazeLevel lvl; public Stretch(int lngth) { len = lngth; switch (random.nextInt(3)) { case 0: - lvl = MazeLevel.TOP; + lvl = LevelComponent.MazeLevel.TOP; break; case 1: - lvl = MazeLevel.MID; + lvl = LevelComponent.MazeLevel.MID; break; default: - lvl = MazeLevel.BOT; + lvl = LevelComponent.MazeLevel.BOT; } } } ArrayList maze = new ArrayList(); - while (soFar < length - 3) { - next = random.nextInt(length / 2) + 1; + loop: while (soFar < length) { + if (soFar + 3 > length) { + length = soFar; + break loop; + } - if (soFar + next > length - 3) { + next = random.nextInt(18) + 5; + + if (soFar + next > length) { next = length - soFar; } @@ -348,54 +361,104 @@ public class PCGLevel extends Level { soFar += next; } - soFar = 0; setBlock(xo, this.height - 1, Level.GROUND); setBlock(xo + 1, this.height - 1, Level.GROUND); setBlock(xo + 2, this.height - 1, Level.GROUND); + soFar = 3; + + Stretch str; + // Stretch nxt; + boolean stretchEnd; + boolean midLine; + for (int i = 0; i < maze.size(); i++) { + + str = maze.get(i); + + // if (i < maze.size() - 1) { + // nxt = maze.get(i + 1); + // } else { + // nxt = null; + // } + + // if (nxt != null) { + // skipUp = ((nxt.lvl != MazeLevel.TOP) && (str.lvl == + // MazeLevel.TOP)) + // || ((nxt.lvl == MazeLevel.TOP) && (str.lvl != MazeLevel.TOP)); + // + // skipDown = ((nxt.lvl != MazeLevel.BOT) && (str.lvl == + // MazeLevel.BOT)) + // || ((str.lvl != MazeLevel.BOT) && (nxt.lvl == MazeLevel.BOT)); + // } + // + // else { + // skipUp = false; + // skipDown = false; + // } - for (Stretch str : maze) { for (int x = 0; x < str.len; x++) { - setBlock(xo + 3 + soFar + x, this.height - 1, Level.GROUND); - setBlock(xo + 3 + soFar + x, this.height - 4, Level.BLOCK_EMPTY); - setBlock(xo + 3 + soFar + x, this.height - 7, Level.BLOCK_EMPTY); - if (x == str.len / 2) { + setBlock(xo + soFar + x, this.height - 1, Level.GROUND); - if (str.lvl != MazeLevel.BOT) { - setBlock(xo + 3 + soFar + x, this.height - 2, - Level.BLOCK_EMPTY); - setBlock(xo + 3 + soFar + x, this.height - 3, - Level.BLOCK_EMPTY); - } - if (str.lvl != MazeLevel.MID) { - setBlock(xo + 3 + soFar + x, this.height - 5, - Level.BLOCK_EMPTY); - setBlock(xo + 3 + soFar + x, this.height - 6, - Level.BLOCK_EMPTY); - } - if (str.lvl != MazeLevel.TOP) { - setBlock(xo + 3 + soFar + x, this.height - 8, - Level.BLOCK_EMPTY); - setBlock(xo + 3 + soFar + x, this.height - 9, - Level.BLOCK_EMPTY); - setBlock(xo + 3 + soFar + x, this.height - 10, - Level.BLOCK_EMPTY); - setBlock(xo + 3 + soFar + x, this.height - 11, - Level.BLOCK_EMPTY); - setBlock(xo + 3 + soFar + x, this.height - 12, - Level.BLOCK_EMPTY); - setBlock(xo + 3 + soFar + x, this.height - 13, - Level.BLOCK_EMPTY); - setBlock(xo + 3 + soFar + x, this.height - 14, - Level.BLOCK_EMPTY); - } + // skipUp = (skipUp && (x == str.len - 2)) + // || (str.len >= 5 && x == (str.len / 2)); + // skipDown = (skipDown && (x == str.len - 2)) + // || (str.len >= 5 && x == (str.len / 2)); + midLine = (str.len >= 5 && x == (str.len / 2) - 1); + stretchEnd = (x == str.len - 1); + + if // ((stretchEnd && nxt != null && nxt.lvl != MazeLevel.BOT) + // || + (midLine && str.lvl != LevelComponent.MazeLevel.BOT) // ) + { + setBlock(xo + soFar + x, this.height - 2, Level.BLOCK_EMPTY); + setBlock(xo + soFar + x, this.height - 3, Level.BLOCK_EMPTY); + } + if // ((stretchEnd && nxt != null && nxt.lvl != MazeLevel.MID) + // || + (midLine && str.lvl != LevelComponent.MazeLevel.MID)// ) + { + setBlock(xo + soFar + x, this.height - 5, Level.BLOCK_EMPTY); + setBlock(xo + soFar + x, this.height - 6, Level.BLOCK_EMPTY); + } + if // ((stretchEnd && nxt != null && nxt.lvl != MazeLevel.TOP) + // || + (midLine && str.lvl != LevelComponent.MazeLevel.TOP)// ) + { + setBlock(xo + soFar + x, this.height - 8, Level.BLOCK_EMPTY); + setBlock(xo + soFar + x, this.height - 9, Level.BLOCK_EMPTY); + setBlock(xo + soFar + x, this.height - 10, + Level.BLOCK_EMPTY); + setBlock(xo + soFar + x, this.height - 11, + Level.BLOCK_EMPTY); + setBlock(xo + soFar + x, this.height - 12, + Level.BLOCK_EMPTY); + setBlock(xo + soFar + x, this.height - 13, + Level.BLOCK_EMPTY); + setBlock(xo + soFar + x, this.height - 14, + Level.BLOCK_EMPTY); + setBlock(xo + soFar + x, this.height - 15, + Level.BLOCK_EMPTY); + } + + if (!stretchEnd) { + setBlock(xo + soFar + x, this.height - 7, Level.BLOCK_EMPTY); + } + + if (!stretchEnd) { + setBlock(xo + soFar + x, this.height - 4, Level.BLOCK_EMPTY); } } + + soFar += str.len; } + setBlock(xo + length - 1, this.height - 1, Level.GROUND); + setBlock(xo + length - 2, this.height - 1, Level.GROUND); + setBlock(xo + length - 3, this.height - 1, Level.GROUND); + return length; } - + private int buildPipeJump(int xo, int maxLength) { int numPipes = 4; int length = numPipes * 2; @@ -461,6 +524,106 @@ public class PCGLevel extends Level { return length; } + private int buildPlatformJump(int xo, int maxLength) { + int length = 0; + int numPlatforms = random.nextInt((maxLength - 3) / 8); + + if (numPlatforms > 1) { + boolean found = false; + MazeLevel nextDir = MazeLevel.TOP; + LevelComponent.PlatformLevel last; + LevelComponent.PlatformLevel next; + ArrayList jumps = new ArrayList(); + int heightMod; + + jumps.add(random.nextBoolean() ? LevelComponent.PlatformLevel.BOT + : LevelComponent.PlatformLevel.MID_D); + + for (int i = 1; i < numPlatforms; i++) { + last = jumps.get(i - 1); + found = false; + + while (!found) { + switch (random.nextInt(5)) { + case 0: + case 1: + nextDir = MazeLevel.BOT; + break; + case 2: + case 3: + nextDir = MazeLevel.TOP; + break; + default: + nextDir = MazeLevel.MID; + } + + found = !((last == LevelComponent.PlatformLevel.TOP && nextDir == MazeLevel.TOP) || (last == LevelComponent.PlatformLevel.BOT && nextDir == MazeLevel.BOT)); + } + + if ((last == LevelComponent.PlatformLevel.BOT && nextDir == MazeLevel.MID) + || (last == LevelComponent.PlatformLevel.MID_D && nextDir == MazeLevel.BOT)) { + next = LevelComponent.PlatformLevel.BOT; + } + + else if ((last == LevelComponent.PlatformLevel.MID_D && nextDir == MazeLevel.MID) + || (last == LevelComponent.PlatformLevel.MID_U && nextDir == MazeLevel.BOT) + || (last == LevelComponent.PlatformLevel.BOT && nextDir == MazeLevel.TOP)) { + next = LevelComponent.PlatformLevel.MID_D; + } + + else if ((last == LevelComponent.PlatformLevel.MID_U && nextDir == MazeLevel.MID) + || (last == LevelComponent.PlatformLevel.TOP && nextDir == MazeLevel.BOT) + || (last == LevelComponent.PlatformLevel.MID_D && nextDir == MazeLevel.TOP)) { + next = LevelComponent.PlatformLevel.MID_U; + } + + else // if ((last == PlatformLevel.TOP && nextDir == + // MazeLevel.MID) + // || (last == PlatformLevel.MID_U && nextDir == + // MazeLevel.TOP)) + { + next = LevelComponent.PlatformLevel.TOP; + } + + jumps.add(next); + } + + setBlock(xo, this.height - 1, Level.GROUND); + setBlock(xo + 1, this.height - 1, Level.GROUND); + setBlock(xo + 2, this.height - 1, Level.GROUND); + length = 3; + + for (int x = 0; x < jumps.size(); x++) { + switch (jumps.get(x)) { + case TOP: + heightMod = 12; + break; + case MID_U: + heightMod = 9; + break; + case MID_D: + heightMod = 6; + break; + default: + heightMod = 3; + } + + setBlock(xo + length, this.height - heightMod, + Level.BLOCK_EMPTY); + setBlock(xo + length + 1, this.height - heightMod, + Level.BLOCK_EMPTY); + setBlock(xo + length + 2, this.height - heightMod, + Level.BLOCK_EMPTY); + setBlock(xo + length + 3, this.height - heightMod, + Level.BLOCK_EMPTY); + + length += 8; + } + } + + return length; + } + private int buildStraight(int xo, int maxLength, boolean safe) { int length = random.nextInt(10) + 2;