MapEditor 导出为 JSON - 对象已加密?
MapEditor export as JSON - Object encrypted?
我已经使用 MapEditor 来选择使用我制作的特定 TileMap 来创建地图。我的问题是:
当通过 JSON 导出创建的地图时,通常大多数地图都显示为它们的图块 ID,如下面的代码片段所示。
{
"data":[1, 2, 1, 2, 3, 1, 3, 1, 2, 2, 3, 3, 4, 4, 4, 1], <------ TIle Id's
"height":4,
"name":"ground",
"opacity":1,
"properties":
{
"tileLayerProp":"1"
},
"type":"tilelayer",
"visible":true,
"width":4,
"x":0,
"y":0
}
然而,当我在我看到的相同字段中检查自己导出的 JSON 地图时,
{
"compression":"zlib",
"data":"eJzt1UFqwzAQQFFvus1Juizdldz\/ViULgQmWItmyJMtv4JGQBirNT9NlmXO+L2qEaXHP30K9u\/RWuq9SYR4rqenZ5+xdlOzrzHlsyJ2Wbe4yWz1KmoS5W4\/UmcLPfiKPsYm10CM9qTPlnDW231SPkiaP5T49UufKbbG1308tcpqs33eHHkfPFttvbouSHmc3GWGOnK9k53uabL1vth7PwjPG1GyRa7bvq9Biz\/TY\/8w9jrR4Te8Wo\/fY871TY2ZtcWQ\/Rz\/rtUaPcVq8z\/peV2wRdvp6\/Fs9XwqejzJndWjdY\/37QpOrTOwuM\/So3ST2v77WtGjQu0etJqFF7F5HptXfQ48WqZ3tbZJqUaNJyw6j9PjU5Cvyek6LVJP312LvuWOPvedocc9ZW\/T4rF2NHuNo3UKPsVrooccV9GqhR\/\/96zFui1F6tDhj7z2P2KPXeXvveOYepXfovd879gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4v4BxPaYbQ==",
"encoding":"base64",
"height":100,
"name":"solids",
"opacity":1,
"type":"tilelayer",
"visible":true,
"width":100,
"x":0,
"y":0
},
这两个都是真实样本,第一个来自他们的文档,第二个来自我的原始导出。如您所见,他们的 'data' 字段与我的不同,因为他们的字段是 JSON 数组,因此我相信这个函数,
public static void load(String path) throws Exception
{
JSONParser parser = new JSONParser();
Object obj = parser.parse(new FileReader(path));
JSONObject jObj = (JSONObject) obj;
JSONArray layers = (JSONArray) jObj.get("layers");
int amount = layers.size();
for (int i = 0; i < amount; i++)
{
JSONObject layer = (JSONObject) layers.get(i);
String type = (String) layer.get("name");
if (type.equals("solids"))
{
WIDTH = (int) ((long)layer.get("width"));
HEIGHT = (int) ((long)layer.get("height"));
solids = parse((JSONArray) layer.get("data"));
}
一直给我带来麻烦。是不是因为在我的地图的 'data' 字段中,我相信那是一个 JSON 字符串和一个编码的字符串。
经过重新搜索,我似乎需要对 'data' 进行解码,最终它会以某种方式变成您在第一段代码中看到的 'data' 字段。
关于我如何执行此操作或只是禁用所有编码的任何提示?
编辑:根据要求我的解析函数
private static Image[][] parse(JSONArray array)
{
Image[][] layer = new Image[WIDTH][HEIGHT];
int index;
for (int x = 0; x < WIDTH; ++x)
{
for (int y = 0; y < HEIGHT; ++y)
{
index = (int)((long)array.get((y * WIDTH) + x)); //must cast because JSON returns long
layer[x][y] = getSpriteImage(index);
}
}
return layer;
}
编辑 2:我编辑的加载函数
public static void load(String path) throws Exception
{
JSONParser parser = new JSONParser();
Object obj = parser.parse(new FileReader(path));
JSONObject jObj = (JSONObject) obj;
JSONArray layers = (JSONArray) jObj.get("layers");
int amount = layers.size();
for (int i = 0; i < amount; i++)
{
JSONObject layer = (JSONObject) layers.get(i);
String type = (String) layer.get("name");
if (type.equals("solids"))
{
Decoder decoder = Base64.getDecoder();
byte[] decodedBytes = decoder.decode((byte[]) layer.get("data"));
Inflater decompresser = new Inflater();
solids = parse((JSONArray)decompresser.inflate(decodedBytes));
编辑 3:我的 getSpriteImage 函数
private static Image getSpriteImage(int index)
{
if (index == 0 )
{
return null;
}
index -= 1;
SpriteSheet sheet = Resources.getSprite("tileset");
int verti = sheet.getVerticalCount();
int horiz = sheet.getHorizontalCount();
int y = (index / verti);
int x = (index % horiz);
return sheet.getSubImage(x, y);
}
编辑 5:地图的外观
[44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, etcccccccccccccccccccccccccccccccccccccccccccccccc]
编辑 6:世界和 GameState 的渲染方法
world-最终值Tile.SIZE = 5;
public static void render(float xRend, float yRend)
{
int offset = 2;
int xStart = (int)(xRend / Tile.SIZE) - offset;
int yStart = (int)(yRend / Tile.SIZE) - offset;
int xEnd = (Window.WIDTH / Tile.SIZE) + xStart + (offset * 2);
int yEnd = (Window.HEIGHT / Tile.SIZE) + yStart + (offset * 2);
for (int x = xStart; x < xEnd; ++x)
{
for (int y = yStart; y < yEnd; ++y)
{
if (solidTileBound(x, y))
{
solids[x][y].draw(x * Tile.SIZE, y * Tile.SIZE, Tile.SIZE, Tile.SIZE);
}
}
}
}
和游戏状态:
@Override
public void render(GameContainer gc, StateBasedGame stateGame, Graphics gfx) throws SlickException
{
gfx.drawString(("Game State"), 50, 50);
//gfx.translate(-1500, -1500);
World.render(500, 500);
//gfx.resetTransform();
}
编辑 7:
[LOG] Loading C:\Users\William.William-PC\Desktop\testMap.json
Sun Dec 06 18:51:33 EST 2015 ERROR:Error loading World
org.newdawn.slick.SlickException: Error loading World
at main.java.TestGame.init(TestGame.java:39)
at org.newdawn.slick.AppGameContainer.setup(AppGameContainer.java:390)
at org.newdawn.slick.AppGameContainer.start(AppGameContainer.java:314)
at main.java.Main.main(Main.java:40)
Caused by: java.lang.RuntimeException: Resource not found: tileset.png
at org.newdawn.slick.util.ResourceLoader.getResourceAsStream(ResourceLoader.java:69)
at org.newdawn.slick.opengl.InternalTextureLoader.getTexture(InternalTextureLoader.java:169)
at org.newdawn.slick.Image.<init>(Image.java:196)
at org.newdawn.slick.SpriteSheet.<init>(SpriteSheet.java:129)
at org.newdawn.slick.SpriteSheet.<init>(SpriteSheet.java:115)
at org.newdawn.slick.SpriteSheet.<init>(SpriteSheet.java:102)
at main.java.Resources.addTileSet(Resources.java:55)
at main.java.JSONLoader.load(JSONLoader.java:33)
at main.java.TestGame.init(TestGame.java:31)
... 3 more
我仔细查看了它,但我不确定我应该把它放在哪里 tileset.png 或者为什么世界不会为此加载。您是否创建了自己的 .json 世界导出来测试它?
非常接近。不幸的是 Inflater
比这更复杂:
而不是
Decoder decoder = Base64.getDecoder();
byte[] decodedBytes = decoder.decode((byte[]) layer.get("data"));
Inflater decompresser = new Inflater();
solids = parse((JSONArray)decompresser.inflate(decodedBytes));
试试这个:
Object o = layer.get("data");
if ( o instanceof JSONArray )
solids = parseJSONArray( (JSONArray) o );
else if ( o instanceof String
&& "base64".equals( layer.get( "encoding" ) )
&& "zlib".equals( layer.get( "compression" ) )
)
{
// base64 decode
Decoder decoder = Base64.getDecoder();
byte[] decodedBytes = decoder.decode((String) o);
// zlib decompress
Inflater decompresser = new Inflater();
decompresser.setInput(decodedBytes);
byte[] decompressedBytes = new byte[WIDTH * HEIGHT * 4];
int resultLength = decompresser.inflate(decompressedBytes);
decompresser.end();
// convert `byte[N*4]` to `int[N]`
int[] result = new int[WIDTH * HEIGHT];
ByteBuffer bb = ByteBuffer.wrap(decompressedBytes);
bb.order(ByteOrder.LITTLE_ENDIAN);
bb.asIntBuffer().get(result);
solids = parseIntArray( result );
}
else
throw new RuntimeException( "Unimplemented data type: "
+ o.getClass().getName() );
将原来的 parse
函数重命名为 parseJSONArray
(例如),
然后将其复制到一个新函数 parseByteArray
,如下所示:
private static Image[][] parseIntArray( int[] array )
{
Image[][] layer = new Image[WIDTH][HEIGHT];
for (int x = 0; x < WIDTH; ++x)
for (int y = 0; y < HEIGHT; ++y)
layer[x][y] = getSpriteImage( array[ y * WIDTH + x ] );
return layer;
}
我已经使用 MapEditor 来选择使用我制作的特定 TileMap 来创建地图。我的问题是:
当通过 JSON 导出创建的地图时,通常大多数地图都显示为它们的图块 ID,如下面的代码片段所示。
{
"data":[1, 2, 1, 2, 3, 1, 3, 1, 2, 2, 3, 3, 4, 4, 4, 1], <------ TIle Id's
"height":4,
"name":"ground",
"opacity":1,
"properties":
{
"tileLayerProp":"1"
},
"type":"tilelayer",
"visible":true,
"width":4,
"x":0,
"y":0
}
然而,当我在我看到的相同字段中检查自己导出的 JSON 地图时,
{
"compression":"zlib",
"data":"eJzt1UFqwzAQQFFvus1Juizdldz\/ViULgQmWItmyJMtv4JGQBirNT9NlmXO+L2qEaXHP30K9u\/RWuq9SYR4rqenZ5+xdlOzrzHlsyJ2Wbe4yWz1KmoS5W4\/UmcLPfiKPsYm10CM9qTPlnDW231SPkiaP5T49UufKbbG1308tcpqs33eHHkfPFttvbouSHmc3GWGOnK9k53uabL1vth7PwjPG1GyRa7bvq9Biz\/TY\/8w9jrR4Te8Wo\/fY871TY2ZtcWQ\/Rz\/rtUaPcVq8z\/peV2wRdvp6\/Fs9XwqejzJndWjdY\/37QpOrTOwuM\/So3ST2v77WtGjQu0etJqFF7F5HptXfQ48WqZ3tbZJqUaNJyw6j9PjU5Cvyek6LVJP312LvuWOPvedocc9ZW\/T4rF2NHuNo3UKPsVrooccV9GqhR\/\/96zFui1F6tDhj7z2P2KPXeXvveOYepXfovd879gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4v4BxPaYbQ==",
"encoding":"base64",
"height":100,
"name":"solids",
"opacity":1,
"type":"tilelayer",
"visible":true,
"width":100,
"x":0,
"y":0
},
这两个都是真实样本,第一个来自他们的文档,第二个来自我的原始导出。如您所见,他们的 'data' 字段与我的不同,因为他们的字段是 JSON 数组,因此我相信这个函数,
public static void load(String path) throws Exception
{
JSONParser parser = new JSONParser();
Object obj = parser.parse(new FileReader(path));
JSONObject jObj = (JSONObject) obj;
JSONArray layers = (JSONArray) jObj.get("layers");
int amount = layers.size();
for (int i = 0; i < amount; i++)
{
JSONObject layer = (JSONObject) layers.get(i);
String type = (String) layer.get("name");
if (type.equals("solids"))
{
WIDTH = (int) ((long)layer.get("width"));
HEIGHT = (int) ((long)layer.get("height"));
solids = parse((JSONArray) layer.get("data"));
}
一直给我带来麻烦。是不是因为在我的地图的 'data' 字段中,我相信那是一个 JSON 字符串和一个编码的字符串。
经过重新搜索,我似乎需要对 'data' 进行解码,最终它会以某种方式变成您在第一段代码中看到的 'data' 字段。
关于我如何执行此操作或只是禁用所有编码的任何提示?
编辑:根据要求我的解析函数
private static Image[][] parse(JSONArray array)
{
Image[][] layer = new Image[WIDTH][HEIGHT];
int index;
for (int x = 0; x < WIDTH; ++x)
{
for (int y = 0; y < HEIGHT; ++y)
{
index = (int)((long)array.get((y * WIDTH) + x)); //must cast because JSON returns long
layer[x][y] = getSpriteImage(index);
}
}
return layer;
}
编辑 2:我编辑的加载函数
public static void load(String path) throws Exception
{
JSONParser parser = new JSONParser();
Object obj = parser.parse(new FileReader(path));
JSONObject jObj = (JSONObject) obj;
JSONArray layers = (JSONArray) jObj.get("layers");
int amount = layers.size();
for (int i = 0; i < amount; i++)
{
JSONObject layer = (JSONObject) layers.get(i);
String type = (String) layer.get("name");
if (type.equals("solids"))
{
Decoder decoder = Base64.getDecoder();
byte[] decodedBytes = decoder.decode((byte[]) layer.get("data"));
Inflater decompresser = new Inflater();
solids = parse((JSONArray)decompresser.inflate(decodedBytes));
编辑 3:我的 getSpriteImage 函数
private static Image getSpriteImage(int index)
{
if (index == 0 )
{
return null;
}
index -= 1;
SpriteSheet sheet = Resources.getSprite("tileset");
int verti = sheet.getVerticalCount();
int horiz = sheet.getHorizontalCount();
int y = (index / verti);
int x = (index % horiz);
return sheet.getSubImage(x, y);
}
编辑 5:地图的外观
[44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, etcccccccccccccccccccccccccccccccccccccccccccccccc]
编辑 6:世界和 GameState 的渲染方法
world-最终值Tile.SIZE = 5;
public static void render(float xRend, float yRend)
{
int offset = 2;
int xStart = (int)(xRend / Tile.SIZE) - offset;
int yStart = (int)(yRend / Tile.SIZE) - offset;
int xEnd = (Window.WIDTH / Tile.SIZE) + xStart + (offset * 2);
int yEnd = (Window.HEIGHT / Tile.SIZE) + yStart + (offset * 2);
for (int x = xStart; x < xEnd; ++x)
{
for (int y = yStart; y < yEnd; ++y)
{
if (solidTileBound(x, y))
{
solids[x][y].draw(x * Tile.SIZE, y * Tile.SIZE, Tile.SIZE, Tile.SIZE);
}
}
}
}
和游戏状态:
@Override
public void render(GameContainer gc, StateBasedGame stateGame, Graphics gfx) throws SlickException
{
gfx.drawString(("Game State"), 50, 50);
//gfx.translate(-1500, -1500);
World.render(500, 500);
//gfx.resetTransform();
}
编辑 7:
[LOG] Loading C:\Users\William.William-PC\Desktop\testMap.json
Sun Dec 06 18:51:33 EST 2015 ERROR:Error loading World
org.newdawn.slick.SlickException: Error loading World
at main.java.TestGame.init(TestGame.java:39)
at org.newdawn.slick.AppGameContainer.setup(AppGameContainer.java:390)
at org.newdawn.slick.AppGameContainer.start(AppGameContainer.java:314)
at main.java.Main.main(Main.java:40)
Caused by: java.lang.RuntimeException: Resource not found: tileset.png
at org.newdawn.slick.util.ResourceLoader.getResourceAsStream(ResourceLoader.java:69)
at org.newdawn.slick.opengl.InternalTextureLoader.getTexture(InternalTextureLoader.java:169)
at org.newdawn.slick.Image.<init>(Image.java:196)
at org.newdawn.slick.SpriteSheet.<init>(SpriteSheet.java:129)
at org.newdawn.slick.SpriteSheet.<init>(SpriteSheet.java:115)
at org.newdawn.slick.SpriteSheet.<init>(SpriteSheet.java:102)
at main.java.Resources.addTileSet(Resources.java:55)
at main.java.JSONLoader.load(JSONLoader.java:33)
at main.java.TestGame.init(TestGame.java:31)
... 3 more
我仔细查看了它,但我不确定我应该把它放在哪里 tileset.png 或者为什么世界不会为此加载。您是否创建了自己的 .json 世界导出来测试它?
非常接近。不幸的是 Inflater
比这更复杂:
而不是
Decoder decoder = Base64.getDecoder();
byte[] decodedBytes = decoder.decode((byte[]) layer.get("data"));
Inflater decompresser = new Inflater();
solids = parse((JSONArray)decompresser.inflate(decodedBytes));
试试这个:
Object o = layer.get("data");
if ( o instanceof JSONArray )
solids = parseJSONArray( (JSONArray) o );
else if ( o instanceof String
&& "base64".equals( layer.get( "encoding" ) )
&& "zlib".equals( layer.get( "compression" ) )
)
{
// base64 decode
Decoder decoder = Base64.getDecoder();
byte[] decodedBytes = decoder.decode((String) o);
// zlib decompress
Inflater decompresser = new Inflater();
decompresser.setInput(decodedBytes);
byte[] decompressedBytes = new byte[WIDTH * HEIGHT * 4];
int resultLength = decompresser.inflate(decompressedBytes);
decompresser.end();
// convert `byte[N*4]` to `int[N]`
int[] result = new int[WIDTH * HEIGHT];
ByteBuffer bb = ByteBuffer.wrap(decompressedBytes);
bb.order(ByteOrder.LITTLE_ENDIAN);
bb.asIntBuffer().get(result);
solids = parseIntArray( result );
}
else
throw new RuntimeException( "Unimplemented data type: "
+ o.getClass().getName() );
将原来的 parse
函数重命名为 parseJSONArray
(例如),
然后将其复制到一个新函数 parseByteArray
,如下所示:
private static Image[][] parseIntArray( int[] array )
{
Image[][] layer = new Image[WIDTH][HEIGHT];
for (int x = 0; x < WIDTH; ++x)
for (int y = 0; y < HEIGHT; ++y)
layer[x][y] = getSpriteImage( array[ y * WIDTH + x ] );
return layer;
}