Java tutorial
/******************************************************************************* * Copyright (c) HALive, 2015. * For Licence information see LICENSE.md ******************************************************************************/ package halive.shootinoutside.common.core.game.map; import halive.shootinoutside.common.core.game.entities.player.Teams; import halive.shootinoutside.common.util.Vector2D; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.nio.file.Files; import java.util.ArrayList; import java.util.Base64; import java.util.Collections; import java.util.List; import java.util.Random; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; /** * This Class describes the Tile based Map. */ public class GameMap { public static final int TILE_WIDTH = 32; public static final int TILE_HEIGHT = 32; private String mapName; private int width; private int height; private GameMapTileType[][] tiles; private byte[] textureSheet; private ItemLayer itemLayer; private List<Vector2D>[] spawnPositions = new List[Teams.values().length]; private Random rnd; private GameMap() { rnd = new Random(); clearSpawnPositions(); } public static GameMap createFromByteArray(byte[] b) throws IOException, ParseException { ByteArrayInputStream in = new ByteArrayInputStream(b); GZIPInputStream input = new GZIPInputStream(in); ByteArrayOutputStream out = new ByteArrayOutputStream(); int j; while ((j = input.read()) != -1) { out.write(j); } String s = new String(out.toByteArray()); return loadGameMapFromJSONString(s); } public static GameMap createEmptyMap(int width, int height) { GameMap map = new GameMap(); map.setMapName("EmptyMap"); map.setSize(width, height); map.initTileArray(); map.itemLayer = new ItemLayer(); for (int x = 0; x < map.tiles.length; x++) { for (int y = 0; y < map.tiles[x].length; y++) { map.tiles[x][y] = GameMapTileType.FLOOR; } } for (int x = 0; x < map.tiles.length; x++) { map.tiles[x][0] = GameMapTileType.WALL_BOTTOM; map.tiles[x][map.height - 1] = GameMapTileType.WALL_TOP; } for (int y = 0; y < map.tiles[0].length; y++) { map.tiles[0][y] = GameMapTileType.WALL_LEFT; map.tiles[map.width - 1][y] = GameMapTileType.WALL_RIGHT; } map.tiles[0][0] = GameMapTileType.WALL; map.tiles[0][height - 1] = GameMapTileType.WALL; map.tiles[width - 1][0] = GameMapTileType.WALL; map.tiles[width - 1][height - 1] = GameMapTileType.WALL; map.textureSheet = loadDefaultTextureSheet(); for (int i = 0; i < Teams.values().length; i++) { Teams team = Teams.values()[i]; map.addSpawnPosition(team, new Vector2D(width / 2, height / 2)); } return map; } private static byte[] loadDefaultTextureSheet() { File f = new File("map/DefaultTileMap.png"); try { return Files.readAllBytes(f.toPath()); } catch (IOException e) { e.printStackTrace(); return null; } } public static GameMap loadGameMapFromJSONString(String s) throws ParseException { JSONParser parser = new JSONParser(); Object obj = parser.parse(s); if (obj instanceof JSONObject) { JSONObject in = (JSONObject) obj; GameMap map = new GameMap(); //Verify Validity if (!in.get("type").equals("soTileMap")) return null; //TODO Implement Determination of the Deserializer depending on the version //Load Width/Height and Mapname map.mapName = in.get("mapName").toString(); map.width = (int) (long) in.get("width"); map.height = (int) (long) in.get("height"); //Load the Map Data byte[] mapData = Base64.getDecoder().decode((String) in.get("mapDataB64")); map.loadTilesFromByteArray(mapData); //Load the Spawnpositions int amtTeams = (int) (long) in.get("amtTeams"); if (amtTeams != Teams.values().length) { return null; } for (int i = 0; i < amtTeams; i++) { JSONObject o = (JSONObject) in.get("spawn_team_" + i); int len = (int) (long) o.get("length"); for (int j = 0; j < len; j++) { JSONObject oj = (JSONObject) o.get("" + j); map.spawnPositions[i].add(Vector2D.fromJSONObject(oj)); } } //Load the ItemLayer map.itemLayer = ItemLayer.fromJSONObject((JSONObject) in.get("itemLayer")); //Read the Image map.textureSheet = Base64.getDecoder().decode(in.get("tileImageB64").toString()); return map; } else { return null; } } public void saveMapToFile(File f) throws IOException { Files.write(f.toPath(), serializeMapToCompressedByteArray()); } public JSONObject serializeMapToJSONObject() { JSONObject obj = new JSONObject(); //Write Standard Header Info obj.put("type", "soTileMap"); obj.put("version", "1.0"); //Write misc Map Information obj.put("mapName", this.mapName); obj.put("width", this.width); obj.put("height", this.height); //Write the map Data (encoded in Base64 byte[] map = getMapData(); String mapData = Base64.getEncoder().encodeToString(map); obj.put("mapDataB64", mapData); //Write the ItemLayer obj.put("itemLayer", itemLayer.serializeToJSON()); //write the SpawnPositions obj.put("amtTeams", spawnPositions.length); for (int i = 0; i < spawnPositions.length; i++) { JSONObject tmpObj = new JSONObject(); tmpObj.put("length", spawnPositions[i].size()); for (int j = 0; j < spawnPositions[i].size(); j++) { Vector2D v = spawnPositions[i].get(j); tmpObj.put("" + j, v.toJSONObject()); } obj.put("spawn_team_" + i, tmpObj); } //Write the image File as Base64 obj.put("tileImageB64", Base64.getEncoder().encodeToString(textureSheet)); return obj; } public String serializeMapToJSONString() { return serializeMapToJSONObject().toJSONString(); } public byte[] serializeMapToCompressedByteArray() throws IOException { //Compress data ByteArrayOutputStream out = new ByteArrayOutputStream(); GZIPOutputStream gzipOut = new GZIPOutputStream(out); gzipOut.write(serializeMapToJSONString().getBytes()); gzipOut.flush(); gzipOut.finish(); return out.toByteArray(); } private byte[] getMapData() { ByteArrayOutputStream out = new ByteArrayOutputStream(); DataOutputStream output = new DataOutputStream(out); for (int x = 0; x < tiles.length; x++) { for (int y = 0; y < tiles[x].length; y++) { try { output.write(tiles[x][y].getTileID()); } catch (IOException e) { return null; } } } return out.toByteArray(); } private void setSize(int w, int h) { this.height = h; this.width = w; } public void setMapName(String mapName) { this.mapName = mapName; } private void initTileArray() { tiles = new GameMapTileType[width][height]; } public void addSpawnPosition(Teams team, Vector2D pos) { spawnPositions[team.getTeamID()].add(pos); } public void clearSpawnPositions() { for (int i = 0; i < spawnPositions.length; i++) { spawnPositions[i] = Collections.synchronizedList(new ArrayList<Vector2D>()); } } public Vector2D getSpawnPos(Teams team) { int teamID = team == null ? rnd.nextInt(spawnPositions.length) : team.getTeamID(); int vecPos = spawnPositions[teamID].size() == 1 ? 0 : rnd.nextInt(spawnPositions[teamID].size()); return allignPosition(spawnPositions[teamID].get(vecPos)); } private Vector2D allignPosition(Vector2D v) { return new Vector2D(v.getX() * TILE_WIDTH + TILE_WIDTH / 2, v.getY() * TILE_HEIGHT + TILE_HEIGHT / 2); } private void loadTilesFromByteArray(byte[] b) { initTileArray(); ByteArrayInputStream input = new ByteArrayInputStream(b); DataInputStream in = new DataInputStream(input); for (int x = 0; x < tiles.length; x++) { for (int y = 0; y < tiles[x].length; y++) { try { tiles[x][y] = GameMapTileType.getTypeFomeTileID(in.read()); } catch (IOException e) { e.printStackTrace(); } } } } public void debugMapLayout(PrintStream out) { out.println("Map name: " + mapName); for (int x = 0; x < width; x++) { out.print("X: " + x + " "); for (int y = 0; y < height; y++) { out.print(tiles[x][y].getTileID() + " "); } out.print("\n"); } out.println("Texture Size " + textureSheet.length + " bytes"); } public byte[] getTextureSheet() { return textureSheet; } public GameMapTileType[][] getTiles() { return tiles; } public int getHeight() { return height; } public int getWidth() { return width; } public int getHeightPixels() { return height * TILE_HEIGHT; } public int getWidthPixels() { return width * TILE_WIDTH; } }