package byow.lab12; import byow.TileEngine.TERenderer; import byow.TileEngine.TETile; import byow.TileEngine.Tileset; import java.util.Random; /** * Draws a world consisting of hexagonal regions. * * @source HexWorld live coding video */ public class HexWorld { private static final int WIDTH = 50; private static final int HEIGHT = 50; private static final long SEED = 3333333; private static final Random RANDOM = new Random(SEED); /** * draw row of tiles to board, anchored at given position */ public static void drawRow(TETile[][] tiles, Position p, TETile tile, int length) { for (int dx = 0; dx < length; dx++) { tiles[p.x + dx][p.y] = tile; } } /** * Fills the given 2D array of tiles with RANDOM tiles. * @param tiles */ public static void fillBoardWithNothing(TETile[][] tiles) { int height = tiles[0].length; int width = tiles.length; for (int x = 0; x < width; x += 1) { for (int y = 0; y < height; y += 1) { tiles[x][y] = Tileset.NOTHING; } } } /** * Gets the position of top/bottom right neighbor of hexagon at Position p. * N is size of hexagon we are tessellating. */ public static Position getTopRightNeighbor(Position p, int n) { return p.shift(2*n - 1, n); } public static Position getBottomRightNeighbor(Position p, int n) { return p.shift(2*n - 1, -n); } /** * Gets position of bottom neighbor of a hexagon at position p. * @param p base hexagon * @param n size of hexagons we are tessellating. * @return position of the bottom neighbor by shifting p. */ public static Position getBottomNeighbor(Position p, int n) { return p.shift(0, -2 * n); } //private helper class for positions private static class Position { int x; int y; Position(int x, int y) { this.x = x; this.y = y; } public Position shift(int dx, int dy) { return new Position(this.x + dx, this.y + dy); } } /** Picks a RANDOM tile with a 33% change of being * a wall, 33% chance of being a flower, and 33% * chance of being empty space. */ private static TETile randomTile() { int tileNum = RANDOM.nextInt(5); switch (tileNum) { case 0: return Tileset.TREE; case 1: return Tileset.FLOWER; case 2: return Tileset.GRASS; case 3: return Tileset.MOUNTAIN; case 4: return Tileset.SAND; default: return Tileset.NOTHING; } } public static void addHexagonHelper(TETile[][] tiles, Position p, TETile tile,int b, int t) { // draw first row Position startOfRow = p.shift(b, 0); drawRow(tiles, startOfRow, tile, t); // draw remaining recursively until last row if (b > 0) { Position nextP = p.shift(0, -1); addHexagonHelper(tiles, nextP, tile, b - 1, t + 2); } // draw last row Position startOfReflectedRow = startOfRow.shift(0, -(2 * b + 1)); drawRow(tiles, startOfReflectedRow, tile, t); } public static void addHexagon(TETile[][] tiles, Position p, TETile t, int s) { if (s <= 2) return; addHexagonHelper(tiles, p, t, s - 1, s); } /** * Adds a column of n hexagons, each of whose biomes are chosen randomly * to the world at position p. Each of the hexagons are size s. */ public static void addHexColumn(TETile[][] tiles, Position p, int s, int n) { if (n < 1) return; // draw this hexagon addHexagon(tiles, p, randomTile(), s); // draw n - 1 hexagons below it if (n > 1) { Position bottomNeighbor = getBottomNeighbor(p, s); addHexColumn(tiles, bottomNeighbor, s, n - 1); } } /** * draws hexagonal world * @param tiles */ public static void drawWorld(TETile[][] tiles, Position p, int hexSize, int tessSize) { // draw first hexagon addHexColumn(tiles, p, hexSize, tessSize); // expand up and right for (int i = 1; i < tessSize; i++) { p = getTopRightNeighbor(p, hexSize); addHexColumn(tiles, p, hexSize, tessSize + i); } // expand down and right for (int i = tessSize - 2; i >= 0; i--) { p = getBottomRightNeighbor(p, hexSize); addHexColumn(tiles, p, hexSize, tessSize + i); } } public static void main(String[] args) { TERenderer ter = new TERenderer(); ter.initialize(WIDTH, HEIGHT); TETile[][] world = new TETile[WIDTH][HEIGHT]; fillBoardWithNothing(world); Position anchor = new Position(15, 30); drawWorld(world, anchor, 2, 3); ter.renderFrame(world); } }