From 903437b7272299f585ca9a116759922a21d24221 Mon Sep 17 00:00:00 2001 From: Woody Folsom Date: Tue, 6 Mar 2012 15:10:33 -0500 Subject: [PATCH] Added 'MyNewLevel' as a possible value for the 'generator' arg. To run it, ant clean ant cd dist java -jar CS8803_P3.jar generator=MyNewLevel --- src/dk/itu/mario/engine/ParsedArgs.java | 3 + src/dk/itu/mario/level/MyNewLevel.java | 386 ++++++++++++++++++ .../level/generator/MyNewLevelGenerator.java | 27 ++ 3 files changed, 416 insertions(+) create mode 100644 src/dk/itu/mario/level/MyNewLevel.java create mode 100644 src/dk/itu/mario/level/generator/MyNewLevelGenerator.java diff --git a/src/dk/itu/mario/engine/ParsedArgs.java b/src/dk/itu/mario/engine/ParsedArgs.java index 727b67e..8065f12 100644 --- a/src/dk/itu/mario/engine/ParsedArgs.java +++ b/src/dk/itu/mario/engine/ParsedArgs.java @@ -3,6 +3,7 @@ package dk.itu.mario.engine; import dk.itu.mario.MarioInterface.LevelGenerator; import dk.itu.mario.level.generator.CustomizedLevelGenerator; import dk.itu.mario.level.generator.MyLevelGenerator; +import dk.itu.mario.level.generator.MyNewLevelGenerator; import dk.itu.mario.level.generator.RandomLevelGenerator; public class ParsedArgs { @@ -21,6 +22,8 @@ public class ParsedArgs { } if ("MyLevel".equals(generatorClass)) { return new MyLevelGenerator(); + } else if ("MyNewLevel".equals(generatorClass)) { + return new MyNewLevelGenerator(); } else if ("CustomizedLevel".equalsIgnoreCase(generatorClass)) { return new CustomizedLevelGenerator(); } else if ("RandomLevel".equalsIgnoreCase(generatorClass)) { diff --git a/src/dk/itu/mario/level/MyNewLevel.java b/src/dk/itu/mario/level/MyNewLevel.java new file mode 100644 index 0000000..9138dde --- /dev/null +++ b/src/dk/itu/mario/level/MyNewLevel.java @@ -0,0 +1,386 @@ +package dk.itu.mario.level; + +import java.util.Random; + +import dk.itu.mario.MarioInterface.GamePlay; +import dk.itu.mario.MarioInterface.LevelInterface; +import dk.itu.mario.engine.sprites.Enemy; +import dk.itu.mario.engine.sprites.SpriteTemplate; + +public class MyNewLevel extends Level { + public static long lastSeed; + private static Random levelSeedRandom = new Random(); + public int BLOCKS_COINS = 0; // the number of coin blocks + public int BLOCKS_EMPTY = 0; // the number of empty blocks + public int BLOCKS_POWER = 0; // the number of power blocks + + public int COINS = 0; // These are the coins in boxes that Mario collect + // Store information about the level + public int ENEMIES = 0; // the number of enemies the level contains + + private int difficulty; + + private int gaps; + private int type; + Random random; + + public MyNewLevel(int width, int height) { + super(width, height); + } + + public MyNewLevel(int width, int height, long seed, int difficulty, + int type, GamePlay playerMetrics) { + this(width, height); + creat(seed, difficulty, type); + } + + @Override + public RandomLevel clone() throws CloneNotSupportedException { + + RandomLevel clone = new RandomLevel(width, height); + + clone.xExit = xExit; + clone.yExit = yExit; + byte[][] map = getMap(); + SpriteTemplate[][] st = getSpriteTemplate(); + + for (int i = 0; i < map.length; i++) + for (int j = 0; j < map[i].length; j++) { + clone.setBlock(i, j, map[i][j]); + clone.setSpriteTemplate(i, j, st[i][j]); + } + clone.BLOCKS_COINS = BLOCKS_COINS; + clone.BLOCKS_EMPTY = BLOCKS_EMPTY; + clone.BLOCKS_POWER = BLOCKS_POWER; + clone.ENEMIES = ENEMIES; + clone.COINS = COINS; + + return clone; + + } + + public void creat(long seed, int difficulty, int type) { + this.type = type; + this.difficulty = difficulty; + + lastSeed = seed; + random = new Random(seed); + + // create the start location + int length = buildStraight(0, width, true); + length += buildPipe(length, width - length, false); + length += buildStraight(length, width, true); + length += buildPipe(length, width - length, true); + + // create all of the medium sections + while (length < width - 64) { + length += buildStraight(length, width, true); + } + + // set the end piece + int floor = height - 1 - random.nextInt(4); + + xExit = length + 8; + yExit = floor; + + // fills the end piece + for (int x = length; x < width; x++) { + for (int y = 0; y < height; y++) { + if (y >= floor) { + setBlock(x, y, GROUND); + } + } + } + + if (type == LevelInterface.TYPE_CASTLE + || type == LevelInterface.TYPE_UNDERGROUND) { + int ceiling = 0; + int run = 0; + for (int x = 0; x < width; x++) { + if (run-- <= 0 && x > 4) { + ceiling = random.nextInt(4); + run = random.nextInt(4) + 4; + } + for (int y = 0; y < height; y++) { + if ((x > 4 && y <= ceiling) || x < 1) { + setBlock(x, y, GROUND); + } + } + } + } + + fixWalls(); + + } + + private void addEnemyLine(int x0, int x1, int y) { + for (int x = x0; x < x1; x++) { + if (random.nextInt(35) < difficulty + 1) { + int type = random.nextInt(4); + + if (difficulty < 1) { + type = Enemy.ENEMY_GOOMBA; + } else if (difficulty < 3) { + type = random.nextInt(3); + } + + setSpriteTemplate(x, y, + new SpriteTemplate(type, + random.nextInt(35) < difficulty)); + ENEMIES++; + } + } + } + + private void blockify(Level level, boolean[][] blocks, int width, int height) { + int to = 0; + if (type == LevelInterface.TYPE_CASTLE) { + to = 4 * 2; + } else if (type == LevelInterface.TYPE_UNDERGROUND) { + to = 4 * 3; + } + + boolean[][] b = new boolean[2][2]; + + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + for (int xx = x; xx <= x + 1; xx++) { + for (int yy = y; yy <= y + 1; yy++) { + int _xx = xx; + int _yy = yy; + if (_xx < 0) + _xx = 0; + if (_yy < 0) + _yy = 0; + if (_xx > width - 1) + _xx = width - 1; + if (_yy > height - 1) + _yy = height - 1; + b[xx - x][yy - y] = blocks[_xx][_yy]; + } + } + + if (b[0][0] == b[1][0] && b[0][1] == b[1][1]) { + if (b[0][0] == b[0][1]) { + if (b[0][0]) { + level.setBlock(x, y, (byte) (1 + 9 * 16 + to)); + } else { + // KEEP OLD BLOCK! + } + } else { + if (b[0][0]) { + // down grass top? + level.setBlock(x, y, (byte) (1 + 10 * 16 + to)); + } else { + // up grass top + level.setBlock(x, y, (byte) (1 + 8 * 16 + to)); + } + } + } else if (b[0][0] == b[0][1] && b[1][0] == b[1][1]) { + if (b[0][0]) { + // right grass top + level.setBlock(x, y, (byte) (2 + 9 * 16 + to)); + } else { + // left grass top + level.setBlock(x, y, (byte) (0 + 9 * 16 + to)); + } + } else if (b[0][0] == b[1][1] && b[0][1] == b[1][0]) { + level.setBlock(x, y, (byte) (1 + 9 * 16 + to)); + } else if (b[0][0] == b[1][0]) { + if (b[0][0]) { + if (b[0][1]) { + level.setBlock(x, y, (byte) (3 + 10 * 16 + to)); + } else { + level.setBlock(x, y, (byte) (3 + 11 * 16 + to)); + } + } else { + if (b[0][1]) { + // right up grass top + level.setBlock(x, y, (byte) (2 + 8 * 16 + to)); + } else { + // left up grass top + level.setBlock(x, y, (byte) (0 + 8 * 16 + to)); + } + } + } else if (b[0][1] == b[1][1]) { + if (b[0][1]) { + if (b[0][0]) { + // left pocket grass + level.setBlock(x, y, (byte) (3 + 9 * 16 + to)); + } else { + // right pocket grass + level.setBlock(x, y, (byte) (3 + 8 * 16 + to)); + } + } else { + if (b[0][0]) { + level.setBlock(x, y, (byte) (2 + 10 * 16 + to)); + } else { + level.setBlock(x, y, (byte) (0 + 10 * 16 + to)); + } + } + } else { + level.setBlock(x, y, (byte) (0 + 1 * 16 + to)); + } + } + } + } + + private int buildPipe(int xo, int maxLength, boolean pits) { + int numPipes = 4; + int floor = height - 1; + int length = numPipes * 4; + int height; + + int[] pitLens = new int[numPipes]; + int[] pipeGrad = new int[numPipes]; + + for (int i = 0; i < numPipes; i++) { + pitLens[i] = random.nextInt(6) + 1; + pipeGrad[i] = random.nextInt(5) - 2; + + length += pitLens[i]; + } + + if (length > maxLength) { + return 0; + } + + length = 0; + height = pipeGrad[0]; + + for (int i = 0; i < numPipes; i++) { + if (height < 1) { + height = 1; + } + + setBlock(xo + length, floor, pits ? Level.HILL_TOP_LEFT + : Level.GROUND); + setBlock(xo + length + 1, floor, pits ? Level.HILL_TOP_RIGHT + : Level.GROUND); + + for (int h = 0; h < height; h++) { + setBlock(xo + length, floor - 1 - h, Level.TUBE_SIDE_LEFT); + setBlock(xo + length + 1, floor - 1 - h, Level.TUBE_SIDE_RIGHT); + } + + setBlock(xo + length, floor - 1 - height, Level.TUBE_TOP_LEFT); + setBlock(xo + length + 1, floor - 1 - height, Level.TUBE_TOP_RIGHT); + + for (int j = 0; j < pitLens[i]; j++) { + if (!pits) { + setBlock(xo + length + 2 + j, floor, Level.GROUND); + } + } + + length += (2 + pitLens[i]); + height += (i == numPipes - 1) ? 0 : pipeGrad[i + 1]; + } + + return length; + } + + private int buildStraight(int xo, int maxLength, boolean safe) { + int length = random.nextInt(10) + 2; + + if (safe) + length = 10 + random.nextInt(5); + + if (length > maxLength) + length = maxLength; + + int floor = height - 1 - random.nextInt(4); + + // runs from the specified x position to the length of the segment + for (int x = xo; x < xo + length; x++) { + for (int y = 0; y < height; y++) { + if (y >= floor) { + setBlock(x, y, GROUND); + } + } + } + + if (!safe) { + if (length > 5) { + decorate(xo, xo + length, floor); + } + } + + return length; + } + + private void decorate(int xStart, int xLength, int floor) { + // if its at the very top, just return + if (floor < 1) + return; + + // boolean coins = random.nextInt(3) == 0; + boolean rocks = true; + + // add an enemy line above the box + addEnemyLine(xStart + 1, xLength - 1, floor - 1); + + int s = random.nextInt(4); + int e = random.nextInt(4); + + if (floor - 2 > 0) { + if ((xLength - 1 - e) - (xStart + 1 + s) > 1) { + for (int x = xStart + 1 + s; x < xLength - 1 - e; x++) { + setBlock(x, floor - 2, COIN); + COINS++; + } + } + } + + s = random.nextInt(4); + e = random.nextInt(4); + + // this fills the set of blocks and the hidden objects inside them + if (floor - 4 > 0) { + if ((xLength - 1 - e) - (xStart + 1 + s) > 2) { + for (int x = xStart + 1 + s; x < xLength - 1 - e; x++) { + if (rocks) { + if (x != xStart + 1 && x != xLength - 2 + && random.nextInt(3) == 0) { + if (random.nextInt(4) == 0) { + setBlock(x, floor - 4, BLOCK_POWERUP); + BLOCKS_POWER++; + } else { // the fills a block with a hidden coin + setBlock(x, floor - 4, BLOCK_COIN); + BLOCKS_COINS++; + } + } else if (random.nextInt(4) == 0) { + if (random.nextInt(4) == 0) { + setBlock(x, floor - 4, (byte) (2 + 1 * 16)); + } else { + setBlock(x, floor - 4, (byte) (1 + 1 * 16)); + } + } else { + setBlock(x, floor - 4, BLOCK_EMPTY); + BLOCKS_EMPTY++; + } + } + } + } + } + } + + private void fixWalls() { + boolean[][] blockMap = new boolean[width + 1][height + 1]; + + for (int x = 0; x < width + 1; x++) { + for (int y = 0; y < height + 1; y++) { + int blocks = 0; + for (int xx = x - 1; xx < x + 1; xx++) { + for (int yy = y - 1; yy < y + 1; yy++) { + if (getBlockCapped(xx, yy) == GROUND) { + blocks++; + } + } + } + blockMap[x][y] = blocks == 4; + } + } + blockify(this, blockMap, width + 1, height + 1); + } + +} diff --git a/src/dk/itu/mario/level/generator/MyNewLevelGenerator.java b/src/dk/itu/mario/level/generator/MyNewLevelGenerator.java new file mode 100644 index 0000000..e62883c --- /dev/null +++ b/src/dk/itu/mario/level/generator/MyNewLevelGenerator.java @@ -0,0 +1,27 @@ +package dk.itu.mario.level.generator; + +import java.util.Random; + +import dk.itu.mario.MarioInterface.GamePlay; +import dk.itu.mario.MarioInterface.LevelGenerator; +import dk.itu.mario.MarioInterface.LevelInterface; +import dk.itu.mario.level.MyLevel; +import dk.itu.mario.level.MyNewLevel; + +public class MyNewLevelGenerator extends CustomizedLevelGenerator implements + LevelGenerator { + + public LevelInterface generateLevel(GamePlay playerMetrics) { + System.out.println("Generating my new level"); + LevelInterface level = new MyNewLevel(320, 15, new Random().nextLong(), 1, + LevelInterface.TYPE_OVERGROUND, playerMetrics); + return level; + } + + @Override + public LevelInterface generateLevel(String detailedInfo) { + // TODO Auto-generated method stub + return null; + } + +}