Releases: jmecn/TMXLoader
v0.6.0
- The “visual” object is separate from TiledMap, Layers, Tiles and MapObject. You can’t use tile.getVisual(), instead use mapRenderer.getSpriteFactory().newTileSprite(Tile).
- Add a demo to show how it works.
- Tons of changes.
Full Changelog: v0.5.0...v0.6.0
v0.5.0
- support parallax scroll factor
- support z-standard compressed data
- Rewrite a desktop application to show how to use the latest features.
Full Changelog: v0.4.0...v0.5.0
v0.4.0
Full Changelog: v0.3.1...v0.4.0
v0.3.1
Full Changelog: v0.3.0...v0.3.1
v0.3.0
- Support ImageLayer
- Support GroupLayer
- Support Tile as Object
- Support Tinting Color
- Fixed Object transform in Isometric map
- Add Test Grid mesh
Full Changelog: v0.2...v0.3.0
TMXLoader v0.2
Changelog
- Use Bucket.GUI instead of Bucket.Transparent, change whole scene from XOZ plane to XOY plane now.
- Removed RPGCameraState, use only TiledMapAppState now.
- Fixed issue #1 and #2: Removed BatchNode, use simple Node instead.
- Fixed issue #3: Now tiles with flip mask can display correctly.
- Add new feature for animated tiles.
TODO
- Fixed issue #4
- Add interface to let control tiles and objects in the scene.
How to use:
package net.jmecn.tmx;
import com.jme3.app.SimpleApplication;
import com.jme3.tmx.TiledMapAppState;
import com.jme3.tmx.TmxLoader;
import com.jme3.tmx.core.TiledMap;
/**
* Test loading tmx assets with TmxLoader.
* @author yanmaoyuan
*
*/
public class TmxLoaderExample extends SimpleApplication {
@Override
public void simpleInitApp() {
// register it
assetManager.registerLoader(TmxLoader.class, "tmx", "tsx");
// load tmx with it
TiledMap map = (TiledMap) assetManager.loadAsset("Models/Examples/Desert/desert.tmx");
assert map != null;
// render it with TiledMapAppState
stateManager.attach(new TiledMapAppState());
TiledMapAppState tiledMap = stateManager.getState(TiledMapAppState.class);
tiledMap.setMap(map);
}
public static void main(String[] args) {
TmxLoaderExample app = new TmxLoaderExample();
app.start();
}
}
TMXLoader v0.1 alpha
Introduction
TMXLoader is used for loading .tmx assets created by Tiled Map Editor. It's a plugin for jMonkeyEngine 3.1.
How to use
- First of all, register it to assetManager.
- Then load a tmx asset with assetManager, you will get a TileMap object.
- Render it or do anything you want to it.
Example:
package net.jmecn.tmx;
import com.jme3.app.SimpleApplication;
import com.jme3.math.Vector3f;
import com.jme3.tmx.RPGCamAppState;
import com.jme3.tmx.TiledMapAppState;
import com.jme3.tmx.TmxLoader;
import com.jme3.tmx.core.TiledMap;
/**
* An example to let you know how to use TMXLoader
*
* @author yanmaoyuan
*
*/
public class TiledMapExample extends SimpleApplication {
@Override
public void simpleInitApp() {
// register it to assetManager.
assetManager.registerLoader(TmxLoader.class, "tmx", "tsx");
// load an asset with it.
TiledMap map = (TiledMap) assetManager.loadAsset("Models/Examples/Orthogonal/01.tmx");
// render it
TiledMapAppState tiledAppState = new TiledMapAppState(map);
stateManager.attach(tiledAppState);
// setup an parallel cam for it
int viewColumns = 24;
RPGCamAppState rpcamAppState = new RPGCamAppState(viewColumns);
rpcamAppState.setTileWidth(map.getTileWidth());
stateManager.attach(rpcamAppState);
// may be you want to look at the center of this map?
Vector3f loc = tiledAppState.getLocation(map.getWidth()/2, map.getHeight()/2);
cam.setLocation(loc);
}
public static void main(String[] args) {
TiledMapExample app = new TiledMapExample();
app.start();
}
}
The MapRenderer
If you don't want to make an renderer your self, I have created some MapRenderers for easy use.
- com.jme3.tmx.render.MapRenderer;
- com.jme3.tmx.render.HexagonalRenderer;
- com.jme3.tmx.render.IsometricRenderer;
- com.jme3.tmx.render.OrthogonalRenderer;
- com.jme3.tmx.render.StaggeredRenderer;
As there are 3 kind of layers in a TiledMap:
- TileLayer
- ObjectGroup
- ImageLayer
The MapRenderers provides 3 methods to make spatials for each layer.
public Spatial render(TileLayer layer);
public Spatial render(ObjectLayer layer);
public Spatial render(ImageLayer layer);
Here it an example I wrote earlier.
public void render(TiledMap map) {
this.map = map;
switch (map.getOrientation()) {
case ORTHOGONAL:
mapRender = new OrthogonalRenderer(map);
break;
case ISOMETRIC:
mapRender = new IsometricRenderer(map);
break;
case HEXAGONAL:
mapRender = new HexagonalRenderer(map);
break;
case STAGGERED:
mapRender = new StaggeredRenderer(map);
break;
}
mapRender.updateVisual();
// background color
if (map.getBackgroundColor() != null) {
viewPort.setBackgroundColor(map.getBackgroundColor());
} else {
viewPort.setBackgroundColor(ColorRGBA.Black);
}
Node node = new Node("Tiled Map");
int len = map.getLayerCount();
int layerCnt = 0;
for (int i = 0; i < len; i++) {
Layer layer = map.getLayer(i);
// skip invisible layer
if (!layer.isVisible()) {
continue;
}
Spatial visual = null;
if (layer instanceof TileLayer) {
visual = mapRender.render((TileLayer) layer);
}
if (layer instanceof ObjectLayer) {
visual = mapRender.render((ObjectLayer) layer);
}
if (layer instanceof ImageLayer) {
visual = mapRender.render((ImageLayer) layer);
}
if (visual != null) {
node.attachChild(visual);
// this is a little magic to make let top layer block off the
// bottom layer
visual.setLocalTranslation(0, layerCnt++, 0);
}
}
// make the whole map thinner
if (layerCnt > 0) {
node.setLocalScale(1, 1f / layerCnt, 1);
}
rootNode.attachChild(node);
}
The com.jme3.tmx.TiledMapAppState will help you to do all the mess.
The camera
I don't really draw 2d image in a 3d game engine, instead I create spatials and apply Material to tiles and objects. They are large quad align to XOZ plane.
In Tiled Qt they use XOY axis, X positive to right and Y positive to down
O------- X
|
|
|
Y
Once in jme3 I choose XOY plane, which means I have to modify the Y for every tile and every object. Now I choose XOZ plane, it's much easier to do the math. The Point(x,y) in Tiled now converted to Vector3f(x, 0, y).
O------- X
|
|
|
Z
Which means you need to set a parallel and make it look at XOZ plane just like this.
/**
* Set view columns. It changes the number of tiles you can see in a row.
*
* @param columns
*/
public void setViewColumn(float columns) {
this.viewColumns = columns;
if (cam == null) {
return;
}
cam.setParallelProjection(true);
cam.lookAtDirection(new Vector3f(0, -1, 0), new Vector3f(0, 0, -1));
float frustumSize = viewColumns * tileWidth * 0.5f;
float aspect = (float) cam.getHeight() / cam.getWidth();
cam.setFrustum(-1000, 1000, -frustumSize, frustumSize, aspect
* frustumSize, -aspect * frustumSize);
}
If you don't want to do it yourself, I create com.jme3.tmx.RPGCamAppState for my debug use. It may help you.
Using RPGCamAppState will disable the FlyCamAppState.
TODO
- add interface to control player and monster
- add support for animated tiles
- handle layer offsets
- handle fliped tile
- fix a lot of bugs:
- NPE when call render() before TiledMapAppState initialized.
- object in hexangonal and isometric map located on wrong position.
- .......