package net.alcuria.umbracraft.engine.map; import net.alcuria.umbracraft.Config; import net.alcuria.umbracraft.Game; import net.alcuria.umbracraft.definitions.tileset.TilesetDefinition; import net.alcuria.umbracraft.util.O; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.ObjectMap; /** Manages all of the game's tile texture regions needed to render a map, both * standard and auto-tiled. Only one instance of this class is needed per map * object. * @author Andrew Keturi */ public class TileView { private static final int[] xOffsets = { 0, 1, 0, 1 }; private static final int[] yOffsets = { 1, 1, 0, 0, }; private final ObjectMap<Integer, Array<TextureRegion>> autoTiles; private final Array<TextureRegion> tiles; public TileView(String filename, TilesetDefinition definition) { // ensure we have everything we need O.notNull(filename); O.notNull(definition); // add regular tile textures tiles = new Array<TextureRegion>(); final Texture texture = Game.assets().get("tiles/" + filename + ".png", Texture.class); //FIXME: hardcoded, bad andrew !! for (int i = 0; i < Math.pow(Config.tilesetWidth / Config.tileWidth, 2); i++) { final int x = (i * Config.tileWidth) % Config.tilesetWidth; final int y = (i / Config.tileWidth) * Config.tileWidth; final int w = Config.tileWidth; tiles.add(new TextureRegion(texture, x, y, w, w)); } // create autotile object map, mapping a texture id from the editor to an array of its regions autoTiles = new ObjectMap<Integer, Array<TextureRegion>>(); final int[] terrainIds = { definition.terrain1, definition.terrain2, definition.terrain3, definition.terrain4, definition.overlay }; // for each of the terrain types we have, if it's valid, add it to the map for (int j = 0; j < terrainIds.length; j++) { if (terrainIds[j] > 0) { // we have a valid terrain id, let's get it's absolute pixel coordinates on the tileset image Game.debug("Valid terrain: " + terrainIds[j]); final int absX = (terrainIds[j] * Config.tileWidth) % Config.tilesetWidth; final int absY = (terrainIds[j] / Config.tileWidth) * Config.tileWidth; Game.debug(String.format("got abs x=%d y=%d", absX, absY)); // now, let's get a series zero-based local x and y coordinates for the autotiles Array<TextureRegion> regions = new Array<TextureRegion>(); for (int i = 0; i < 48; i++) { final int locX = (i % 6) * Config.tileWidth / 2; final int locY = (i / 6) * Config.tileWidth / 2; // we can add each of these to the absolute pixel coordinates and get the location of the autotile region on the tileset Game.debug(String.format("Adding texture region at x=%d y=%d", absX + locX, absX + locY)); regions.add(new TextureRegion(texture, absX + locX, absY + locY, Config.tileWidth / 2, Config.tileWidth / 2)); } // lastly, add the newly-created array of autotile texture regions to our autotile object map autoTiles.put(terrainIds[j], regions); } } } /** Draws either the autotile or regular tile at this coordinate * @param attributes tile attributes for this location * @param x x coordinate * @param y y coordinate */ public void draw(AutoTileAttributes attributes, int x, int y) { final int type = attributes.getType(); final int w = Config.tileWidth / 2; if (autoTiles.containsKey(type)) { Array<TextureRegion> autoTileRegions = autoTiles.get(type); // for each corner (top left, top right, bot left, bot right, we want to draw the autotile for (int idx = 0; idx < xOffsets.length; idx++) { int corner = attributes.getCorner(idx); Game.batch().draw(autoTileRegions.get(corner), x + xOffsets[idx] * w, y + yOffsets[idx] * w, w, w); } } else { Game.batch().draw(get(type), x, y, w * 2, w * 2); } } public TextureRegion get(int id) { return tiles.get(id); } }