package net.alcuria.umbracraft.engine.map; import net.alcuria.umbracraft.definitions.tileset.TilesetDefinition; /** This object is created on a per-tile basis to store any terrain information * necessary to render an aut-tile * @author Andrew */ public class AutoTileAttributes { private final int[] corners = new int[4]; private final TilesetDefinition tilesetDefinition; private int type; public AutoTileAttributes(TilesetDefinition tilesetDefinition) { this.tilesetDefinition = tilesetDefinition; } public int getCorner(int idx) { return corners[idx]; } public int getType() { return type; } public boolean isInitialized() { return type > 0; } /** This passes in a bitmask describing the neighboring tiles. From that, we * assign each of the autotile corners to their respective index. This index * is not specific to any particular terrain, instead it's a very generic * subtiling system as seen in RM2k3. I am not a smart man, so for now this * is just going to be a huge switch. Thankfully, this is only called once * upon map initialization so performance is not as critical. * @param neighborMask the bitmask describing neighbors. Each bit * corresponds to a surrounding tile. Since there are 8 surrounding * tiles, masks are 8 bits long. The neighbor order used is: top * topright right rightdown _ down downleft left lefttop */ public void setMask(int neighborMask) { if (type <= 0) { throw new IllegalStateException("Tile type must be set first"); } // each corner is concerned with its three neighboring tiles. To elaborate: // Corner 0 (Top Left) | ?000_00?? | LEFT, LEFT TOP, TOP // Corner 1 (Top Right) | ???0_0000 | TOP, TOP_RIGHT, RIGHT // Corner 2 (Bottom Left) | 0000_???0 | BOTTOM, BOTTOM_LEFT, LEFT // Corner 3 (Bottom Right) | 00??_?000 | RIGHT, BOTTOM_RIGHT, BOTTOM for (int i = 0; i < corners.length; i++) { // i'm not smart enough to do this without a switch // but the end goal is to get the bits we care about to the least significant digits // an excercise for the reader: please make this cleaner for me and I'll buy you a coffee :) int edgeMask = neighborMask; if (i == 0) { edgeMask = edgeMask << 1; if ((edgeMask & 0b10000_0000) > 0) { edgeMask++; } edgeMask = edgeMask & 0b0000_0111; switch (edgeMask) { case 0b000: case 0b010: corners[i] = 12; break; case 0b001: case 0b011: corners[i] = 24; break; case 0b100: case 0b110: corners[i] = 14; break; case 0b111: corners[i] = 26; break; case 0b101: corners[i] = 4; break; } } else if (i == 1) { edgeMask = edgeMask >> 5; edgeMask = edgeMask & 0b0000_0111; switch (edgeMask) { case 0b000: case 0b010: corners[i] = 17; break; case 0b001: case 0b011: corners[i] = 15; break; case 0b100: case 0b110: corners[i] = 29; break; case 0b101: corners[i] = 5; break; case 0b111: corners[i] = 27; break; } } else if (i == 2) { edgeMask = edgeMask >> 1; edgeMask = edgeMask & 0b0000_0111; switch (edgeMask) { case 0b000: case 0b010: corners[i] = 42; break; case 0b001: case 0b011: corners[i] = 44; break; case 0b100: case 0b110: corners[i] = 30; break; case 0b101: corners[i] = 10; break; case 0b111: corners[i] = 32; break; } } else if (i == 3) { edgeMask = edgeMask >> 3; edgeMask = edgeMask & 0b0000_0111; switch (edgeMask) { case 0b000: case 0b010: corners[i] = 47; break; case 0b001: case 0b011: corners[i] = 35; break; case 0b100: case 0b110: corners[i] = 45; break; case 0b101: corners[i] = 11; break; case 0b111: corners[i] = 33; break; } } } /* * corners[0] = 0; corners[1] = 0; corners[2] = 0; corners[3] = 0; */ } /** Given an ID from the editor (1-6) this sets the TYPE of terrain for the * particular tilesetDefinition. This is how we decouple map data and * tileset data. * @param id the id from the map editor * @param isOverlay if <code>true</code>, we'll use the overlay types */ public void setType(int id, boolean isOverlay) { if (!isOverlay) { if (id == 1) { type = tilesetDefinition.terrain1; } else if (id == 2) { type = tilesetDefinition.terrain2; } else if (id == 3) { type = tilesetDefinition.terrain3; } else if (id == 4) { type = tilesetDefinition.terrain4; } else if (id == 5) { type = tilesetDefinition.stairs; } else if (id == 6) { type = tilesetDefinition.treeWall; } } else { if (id == 1) { type = tilesetDefinition.overlay; } } } }