| @@ -99,6 +99,11 @@ public void setZ(int z) { | ||
| this.z = z; | ||
| } | ||
|
|
||
| @Override | ||
| public int getPriority() { | ||
| return 1; | ||
| } | ||
|
|
||
| public long getId() { | ||
| return id; | ||
| } | ||
| @@ -0,0 +1,153 @@ | ||
| /* | ||
| * The MIT License (MIT) | ||
| * | ||
| * Copyright (c) 2016 Tellerva, Marc Lawrence | ||
| * | ||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| * of this software and associated documentation files (the "Software"), to deal | ||
| * in the Software without restriction, including without limitation the rights | ||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| * copies of the Software, and to permit persons to whom the Software is | ||
| * furnished to do so, subject to the following conditions: | ||
| * | ||
| * The above copyright notice and this permission notice shall be included in all | ||
| * copies or substantial portions of the Software. | ||
| * | ||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| * SOFTWARE. | ||
| */ | ||
|
|
||
| package me.scarlet.undertailor.overworld.map; | ||
|
|
||
| import com.badlogic.gdx.utils.Disposable; | ||
| import me.scarlet.undertailor.Undertailor; | ||
| import me.scarlet.undertailor.util.ConfigurateUtil; | ||
| import me.scarlet.undertailor.wrappers.TilemapWrapper; | ||
| import ninja.leaping.configurate.ConfigurationNode; | ||
|
|
||
| import java.util.Collection; | ||
| import java.util.HashMap; | ||
| import java.util.Map; | ||
| import java.util.Map.Entry; | ||
|
|
||
| public class RoomMap implements Disposable { | ||
|
|
||
| public static class TileData implements Cloneable { | ||
|
|
||
| public static final String KEY_VISIBLE = "visible"; | ||
| public static final String KEY_TRAVERSABLE = "traversable"; | ||
|
|
||
| private Map<String, Float> values; | ||
|
|
||
| public TileData() { | ||
| this.values = new HashMap<>(); | ||
| this.values.put(KEY_VISIBLE, 1.0F); | ||
| this.values.put(KEY_TRAVERSABLE, 1.0F); | ||
| } | ||
|
|
||
| public boolean getBoolean(String key) { | ||
| if(values.containsKey(key)) { | ||
| return values.get(key) > 0.0F; | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| public void setBoolean(String key, boolean flag) { | ||
| values.put(key, flag ? 1.0F : 0.0F); | ||
| } | ||
|
|
||
| public float getNumber(String key) { | ||
| if(values.containsKey(key)) { | ||
| return values.get(key); | ||
| } | ||
|
|
||
| return 0.0F; | ||
| } | ||
|
|
||
| public void setNumber(String key, float num) { | ||
| values.put(key, num); | ||
| } | ||
|
|
||
| public boolean isTraversable() { | ||
| return this.getBoolean(KEY_TRAVERSABLE); | ||
| } | ||
|
|
||
| public boolean isVisible() { | ||
| return this.getBoolean(KEY_VISIBLE); | ||
| } | ||
|
|
||
| @Override | ||
| public TileData clone() { | ||
| TileData data = new TileData(); | ||
| data.values = new HashMap<>(values); | ||
| return data; | ||
| } | ||
| } | ||
|
|
||
| public static final int DEFAULT_FLOOR_Z = 0; | ||
| public static final int DEFAULT_OBJECT_Z = 1; | ||
| public static final int DEFAULT_CEILING_Z = 2; | ||
|
|
||
| public static RoomMap fromConfig(ConfigurationNode node) { | ||
| RoomMap map = new RoomMap(); | ||
| map.sizeX = ConfigurateUtil.processInt(node.getNode("sizeX"), null); | ||
| map.sizeY = ConfigurateUtil.processInt(node.getNode("sizeY"), null); | ||
| String[] tilemapNames = ConfigurateUtil.processStringArray(node.getNode("tilemaps"), null); | ||
|
|
||
| map.tilemaps = new TilemapWrapper[tilemapNames.length]; | ||
| for(int i = 0; i < map.tilemaps.length; i++) { | ||
| TilemapWrapper wrapper = Undertailor.getTilemapManager().getTilemap(tilemapNames[i]); | ||
| if(wrapper == null) { | ||
| Undertailor.instance.error(RoomLoader.MANAGER_TAG, "failed to load room: map data referenced non-existing tilemap (" + tilemapNames[i] + ")"); | ||
| return null; | ||
| } | ||
|
|
||
| map.tilemaps[i] = wrapper; | ||
| } | ||
|
|
||
| Map<Object, ? extends ConfigurationNode> layerMapping = node.getNode("map").getChildrenMap(); | ||
| for(Entry<Object, ? extends ConfigurationNode> entry : layerMapping.entrySet()) { | ||
| RoomMapLayer loaded = new RoomMapLayer(map, entry.getValue()); | ||
| map.layers.put(loaded.getName(), loaded); | ||
| } | ||
|
|
||
| return map; | ||
| } | ||
|
|
||
| private int sizeX, sizeY; | ||
| private Map<String, RoomMapLayer> layers; | ||
| private TilemapWrapper[] tilemaps; | ||
|
|
||
| public RoomMap() { | ||
| this.layers = new HashMap<>(); // don't need to organize; worldroom already tries to organize for rendering | ||
| } | ||
|
|
||
| public Collection<RoomMapLayer> getLayers() { | ||
| return layers.values(); | ||
| } | ||
|
|
||
| public int getSizeX() { | ||
| return sizeX; | ||
| } | ||
|
|
||
| public int getSizeY() { | ||
| return sizeY; | ||
| } | ||
|
|
||
| public Tilemap getTilemap(int index) { | ||
| return tilemaps[index].getReference(); | ||
| } | ||
|
|
||
| @Override | ||
| public void dispose() { | ||
| for(TilemapWrapper wrapper : tilemaps) { | ||
| wrapper.removeReference(this); | ||
| } | ||
| } | ||
| } |
| @@ -0,0 +1,144 @@ | ||
| /* | ||
| * The MIT License (MIT) | ||
| * | ||
| * Copyright (c) 2016 Tellerva, Marc Lawrence | ||
| * | ||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| * of this software and associated documentation files (the "Software"), to deal | ||
| * in the Software without restriction, including without limitation the rights | ||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| * copies of the Software, and to permit persons to whom the Software is | ||
| * furnished to do so, subject to the following conditions: | ||
| * | ||
| * The above copyright notice and this permission notice shall be included in all | ||
| * copies or substantial portions of the Software. | ||
| * | ||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| * SOFTWARE. | ||
| */ | ||
|
|
||
| package me.scarlet.undertailor.overworld.map; | ||
|
|
||
| import me.scarlet.undertailor.exception.BadConfigurationException; | ||
| import me.scarlet.undertailor.util.ConfigurateUtil; | ||
| import me.scarlet.undertailor.util.Layerable; | ||
| import ninja.leaping.configurate.ConfigurationNode; | ||
|
|
||
| public class RoomMapLayer implements Layerable, Cloneable { | ||
|
|
||
| private int z; | ||
| private String name; | ||
| private int priority; | ||
| private RoomMap parent; | ||
| private Tile[][] mapping; | ||
| private boolean visible; | ||
|
|
||
| private RoomMapLayer() {} // for clones; | ||
|
|
||
| // tilemapid:tileid | ||
| public RoomMapLayer(RoomMap parent, ConfigurationNode layerData) { | ||
| this.parent = parent; | ||
| this.priority = ConfigurateUtil.processBoolean(layerData.getNode("wallLayer"), false) ? 1 : 0; | ||
| this.name = layerData.getKey().toString(); | ||
| this.mapping = new Tile[parent.getSizeY()][parent.getSizeX()]; | ||
| this.visible = true; | ||
|
|
||
| this.z = ConfigurateUtil.processInt(layerData.getNode("z"), 0); | ||
|
|
||
| String[] mapping = ConfigurateUtil.processStringArray(layerData.getNode("mapping"), null); | ||
| for(int y = 0; y < parent.getSizeY(); y++) { | ||
| String[] tiles = mapping[y].split(","); | ||
| for(int x = 0; x < parent.getSizeX(); x++) { | ||
| this.mapping[y][x] = parseTileMapping(tiles[x]); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public int getZ() { | ||
| return z; | ||
| } | ||
|
|
||
| @Override | ||
| public void setZ(int z) { | ||
| this.z = z; | ||
| } | ||
|
|
||
| @Override | ||
| public int getPriority() { | ||
| return priority; | ||
| } | ||
|
|
||
| public boolean isVisible() { | ||
| return visible; | ||
| } | ||
|
|
||
| public void setVisible(boolean flag) { | ||
| this.visible = flag; | ||
| } | ||
|
|
||
| public String getName() { | ||
| return name; | ||
| } | ||
|
|
||
| public RoomMap getParent() { | ||
| return parent; | ||
| } | ||
|
|
||
| public Tile getTileAt(int x, int y) { | ||
| return mapping[y][x]; | ||
| } | ||
|
|
||
| public RoomMapLayer clone() { | ||
| RoomMapLayer clone = new RoomMapLayer(); | ||
| clone.z = this.z; | ||
| clone.name = this.name; | ||
| clone.parent = this.parent; | ||
| clone.priority = this.priority; | ||
| clone.visible = true; | ||
| clone.mapping = new Tile[parent.getSizeY()][parent.getSizeX()]; | ||
|
|
||
| for(int y = 0; y < parent.getSizeY(); y++) { | ||
| for(int x = 0; x < parent.getSizeX(); x++) { | ||
| clone.mapping[y][x] = this.mapping[y][x].clone(); | ||
| } | ||
| } | ||
|
|
||
| return clone; | ||
| } | ||
|
|
||
| public void render() { | ||
| if(visible) { | ||
| for(int x = 0; x < parent.getSizeX(); x++) { | ||
| for(int y = 0; y < parent.getSizeY(); y++) { | ||
| Tile tile = mapping[y][x]; | ||
| if(tile != null) { | ||
| float xPos = x * 20F; | ||
| float yPos = y * 20F; | ||
| tile.getCurrentState().getSprite().draw(xPos, yPos, 1F, 1F, 0F, false, false, 20, 20, true); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| Tile parseTileMapping(String mapping) { | ||
| try { | ||
| String[] mappingSplit = mapping.split(":"); | ||
| Tilemap map = parent.getTilemap(Integer.parseInt(mappingSplit[0])); | ||
| System.out.println(mappingSplit[1]); | ||
| Tile returned = map.getTile(mappingSplit[1]).clone(); | ||
|
|
||
| return returned; | ||
| } catch(NullPointerException e) { | ||
| BadConfigurationException thrown = new BadConfigurationException("bad map data: data requested non-existing tilemap or tile"); | ||
| thrown.initCause(e); | ||
| throw thrown; | ||
| } | ||
| } | ||
| } |
| @@ -0,0 +1,112 @@ | ||
| /* | ||
| * The MIT License (MIT) | ||
| * | ||
| * Copyright (c) 2016 Tellerva, Marc Lawrence | ||
| * | ||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| * of this software and associated documentation files (the "Software"), to deal | ||
| * in the Software without restriction, including without limitation the rights | ||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| * copies of the Software, and to permit persons to whom the Software is | ||
| * furnished to do so, subject to the following conditions: | ||
| * | ||
| * The above copyright notice and this permission notice shall be included in all | ||
| * copies or substantial portions of the Software. | ||
| * | ||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| * SOFTWARE. | ||
| */ | ||
|
|
||
| package me.scarlet.undertailor.overworld.map; | ||
|
|
||
| import me.scarlet.undertailor.gfx.Sprite; | ||
| import ninja.leaping.configurate.ConfigurationNode; | ||
|
|
||
| import java.util.HashMap; | ||
| import java.util.Map; | ||
|
|
||
| public class Tile implements Cloneable { | ||
|
|
||
| public static class TileState { | ||
|
|
||
| public static TileState fromConfig(ConfigurationNode config) { | ||
| return null; // TODO; | ||
| } | ||
|
|
||
| private Tile parent; | ||
| private Sprite sprite; // TODO tile animation | ||
| private String stateName; | ||
|
|
||
| public TileState(String stateName, Tile parent, Sprite sprite) { | ||
| this.sprite = sprite; | ||
| this.parent = parent; | ||
| this.stateName = stateName; | ||
| } | ||
|
|
||
| public Tile getParent() { | ||
| return parent; | ||
| } | ||
|
|
||
| public String getStateName() { | ||
| return stateName; | ||
| } | ||
|
|
||
| public Sprite getSprite() { | ||
| return sprite; | ||
| } | ||
| } | ||
|
|
||
| private String tileName; | ||
| private String currentState; | ||
| private Map<String, TileState> states; | ||
|
|
||
| private Tile() { | ||
| this.tileName = null; | ||
| this.currentState = null; | ||
| this.states = new HashMap<String, TileState>(); | ||
| } | ||
|
|
||
| public Tile(String tileName) { | ||
| this.tileName = tileName; | ||
| this.currentState = null; | ||
| this.states = new HashMap<String, TileState>(); | ||
| } | ||
|
|
||
| public String getTileName() { | ||
| return tileName; | ||
| } | ||
|
|
||
| public void addState(TileState state) { | ||
| this.addStates(state); | ||
| } | ||
|
|
||
| public void addStates(TileState... states) { | ||
| for(TileState state : states) { | ||
| this.states.put(state.getStateName(), state); | ||
| } | ||
| } | ||
|
|
||
| public TileState getCurrentState() { | ||
| return states.get(currentState); | ||
| } | ||
|
|
||
| public void setCurrentState(String stateId) { | ||
| if(states.containsKey(stateId)) { | ||
| this.currentState = stateId; | ||
| } | ||
| } | ||
|
|
||
| public Tile clone() { | ||
| Tile returned = new Tile(); | ||
| returned.tileName = this.tileName; | ||
| returned.currentState = this.currentState; | ||
| returned.states = new HashMap<>(this.states); | ||
|
|
||
| return returned; | ||
| } | ||
| } |
| @@ -0,0 +1,135 @@ | ||
| /* | ||
| * The MIT License (MIT) | ||
| * | ||
| * Copyright (c) 2016 Tellerva, Marc Lawrence | ||
| * | ||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| * of this software and associated documentation files (the "Software"), to deal | ||
| * in the Software without restriction, including without limitation the rights | ||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| * copies of the Software, and to permit persons to whom the Software is | ||
| * furnished to do so, subject to the following conditions: | ||
| * | ||
| * The above copyright notice and this permission notice shall be included in all | ||
| * copies or substantial portions of the Software. | ||
| * | ||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| * SOFTWARE. | ||
| */ | ||
|
|
||
| package me.scarlet.undertailor.overworld.map; | ||
|
|
||
| import com.badlogic.gdx.Gdx; | ||
| import com.badlogic.gdx.graphics.Texture; | ||
| import com.badlogic.gdx.utils.Disposable; | ||
| import me.scarlet.undertailor.Undertailor; | ||
| import me.scarlet.undertailor.exception.TextureTilingException; | ||
| import me.scarlet.undertailor.gfx.SpriteSheet; | ||
| import me.scarlet.undertailor.gfx.SpriteSheet.SpriteSheetMeta; | ||
| import me.scarlet.undertailor.manager.TilemapManager; | ||
| import me.scarlet.undertailor.overworld.map.Tile.TileState; | ||
| import me.scarlet.undertailor.util.ConfigurateUtil; | ||
| import ninja.leaping.configurate.ConfigurationNode; | ||
| import ninja.leaping.configurate.json.JSONConfigurationLoader; | ||
|
|
||
| import java.io.File; | ||
| import java.io.FileNotFoundException; | ||
| import java.io.IOException; | ||
| import java.util.HashMap; | ||
| import java.util.Map; | ||
| import java.util.Map.Entry; | ||
|
|
||
| import javax.naming.ConfigurationException; | ||
|
|
||
| public class Tilemap implements Disposable { | ||
|
|
||
| public static final String TILEMAP_SHEET_PREFIX = "$ttlm-"; | ||
| public static final String ILLEGAL_CHARACTERS = ",;:="; | ||
|
|
||
| public static float getPropertyValue(String str) { | ||
| try { | ||
| return Float.parseFloat(str); | ||
| } catch(NumberFormatException e) { | ||
| if(str.equalsIgnoreCase("true")) { | ||
| return 1.0F; | ||
| } | ||
|
|
||
| return 0.0F; | ||
| } | ||
| } | ||
|
|
||
| private String name; | ||
| private SpriteSheet sheet; | ||
| private Map<String, Tile> tiles; | ||
|
|
||
| public Tilemap(String name, File texture, File meta) throws TextureTilingException, FileNotFoundException, ConfigurationException, IOException { | ||
| this.name = name; | ||
| this.tiles = new HashMap<>(); | ||
|
|
||
| if(!texture.exists() || !meta.exists()) { | ||
| throw new FileNotFoundException("texture/meta file not found (" + texture.getName() + "/" + meta.getName() + ")"); | ||
| } | ||
|
|
||
| Texture tx = new Texture(Gdx.files.absolute(texture.getAbsolutePath())); | ||
| if(tx.getWidth() % 20 != 0 || tx.getHeight() % 20 != 0) { | ||
| throw new TextureTilingException("texture does not contain 20x20 tiled sprites"); | ||
| } | ||
|
|
||
| SpriteSheetMeta smeta = new SpriteSheetMeta(); | ||
| smeta.gridX = tx.getWidth() / 20; | ||
| smeta.gridY = tx.getHeight() / 20; | ||
| this.sheet = new SpriteSheet(TILEMAP_SHEET_PREFIX + name, tx, smeta); | ||
|
|
||
| JSONConfigurationLoader loader = JSONConfigurationLoader.builder().setFile(meta).build(); | ||
| ConfigurationNode node = loader.load(); | ||
|
|
||
| Map<Object, ? extends ConfigurationNode> map = node.getNode("tiles").getChildrenMap(); | ||
| for(Entry<Object, ? extends ConfigurationNode> entry : map.entrySet()) { | ||
| ConfigurationNode tileConfig = entry.getValue(); | ||
| String tileName = tileConfig.getKey().toString(); | ||
| String defaultState = null; | ||
| Tile tile = new Tile(tileName); | ||
|
|
||
| for(int i = 0; i < ILLEGAL_CHARACTERS.length(); i++) { | ||
| char ch = ILLEGAL_CHARACTERS.charAt(i); | ||
| if(tileName.contains(ch + "")) { | ||
| throw new ConfigurationException("tile name \"" + tileName + "\" contained illegal character '" + ch + "'"); | ||
| } | ||
| } | ||
|
|
||
| Map<Object, ? extends ConfigurationNode> states = tileConfig.getNode("states").getChildrenMap(); | ||
| for(Entry<Object, ? extends ConfigurationNode> stateEntry : states.entrySet()) { | ||
| TileState state = new TileState(stateEntry.getKey().toString(), tile, this.sheet.getSprite(ConfigurateUtil.processInt(stateEntry.getValue().getNode("sprite"), null))); | ||
| tile.addState(state); | ||
|
|
||
| if(defaultState == null) { | ||
| defaultState = state.getStateName(); | ||
| tile.setCurrentState(defaultState); | ||
| } | ||
|
|
||
| Undertailor.instance.debug(TilemapManager.MANAGER_TAG, "loading tilestate " + tileName + ":" + state.getStateName()); | ||
| } | ||
|
|
||
| Undertailor.instance.debug(TilemapManager.MANAGER_TAG, "loaded tile " + this.name + ":" + tileName); | ||
| this.tiles.put(tileName, tile); | ||
| } | ||
| } | ||
|
|
||
| public String getName() { | ||
| return this.name; | ||
| } | ||
|
|
||
| public Tile getTile(String id) { | ||
| return tiles.get(id); | ||
| } | ||
|
|
||
| @Override | ||
| public void dispose() { | ||
| this.sheet.dispose(); | ||
| } | ||
| } |
| @@ -32,5 +32,6 @@ public interface Layerable { | ||
|
|
||
| public int getZ(); | ||
| public void setZ(int z); | ||
| public int getPriority(); // floors should be 0; everything else should be 1 | ||
|
|
||
| } | ||
| @@ -0,0 +1,18 @@ | ||
| package me.scarlet.undertailor.util; | ||
|
|
||
| import java.util.Comparator; | ||
| import java.util.Map; | ||
|
|
||
| public abstract class ValueComparator<T1, T2> implements Comparator<T1> { | ||
|
|
||
| private Map<T1, T2> map; | ||
| public ValueComparator(Map<T1, T2> map) { | ||
| this.map = map; | ||
| } | ||
|
|
||
| public Map<T1, T2> getMap() { | ||
| return map; | ||
| } | ||
|
|
||
| public abstract int compare(T1 o1, T1 o2); | ||
| } |