我正在使用 libGDX 和 Tiled 来制作RPG。我已经有很多工作了:标题屏幕,测试屏幕,我的地图已加载。我可以阅读我放在地图上和某些瓷砖上的属性。我也可以在地图上移动一切,但我现在要弄清楚的是:
如何从对象图层渲染地图对象并处理碰撞?
我想在我的碰撞层使用Tiled的Object层。 IE:在我不希望角色能够通过的某些瓷砖/区域周围放置形状。
这是我到目前为止所做的:
package rawct.awakening;
import java.lang.reflect.Method;
import java.util.Iterator;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.maps.MapObject;
import com.badlogic.gdx.maps.MapObjects;
import com.badlogic.gdx.maps.tiled.TiledMap;
import com.badlogic.gdx.maps.tiled.TiledMapTile;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer.Cell;
import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer;
import com.badlogic.gdx.maps.tiled.TiledMapTileSet;
import com.badlogic.gdx.maps.tiled.TmxMapLoader;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ObjectMap;
public class GameMap extends TiledMap {
private String TAG = "GameMap";
private TmxMapLoader loader = new TmxMapLoader();
private OrthogonalTiledMapRenderer mRender;
private TiledMap gamemap;
private TiledMapTileLayer mapTiles;
private ObjectMap<TiledMapTile, Boolean> Blocked;
private ObjectMap<TiledMapTile, Boolean> Event;
private MapObjects mObjects = new MapObjects();
private MapObject mObj;
public void draw(OrthographicCamera cam){
mRender.setView(cam);
mRender.render();
// Should render my map object?
mRender.renderObject(mObj);
}
public GameMap(String Map){
Blocked = new ObjectMap<TiledMapTile, Boolean>();
Event = new ObjectMap<TiledMapTile, Boolean>();
gamemap = loader.load("maps/"+Map+".tmx");
mRender = new OrthogonalTiledMapRenderer(gamemap);
loadMap(gamemap);
}
private Cell getCellAt(float x, float y){
return mapTiles.getCell((int)x, (int)y);
}
private TiledMapTile getTileAt(float x, float y){
Cell cell = getCellAt(x, y);
return cell != null ? cell.getTile() : null;
}
public boolean isTileBlocked(float x, float y){
try {
return Blocked.get(getTileAt(x, y));
} catch (Exception e) {
Gdx.app.log(TAG, e.toString());
return false;
}
}
private void loadMap(TiledMap map) {
String sI = null;
Blocked.clear();
Event.clear();
try{
mapTiles = (TiledMapTileLayer)map.getLayers().get(0);
mObjects = map.getLayers().get("Testing").getObjects();
} catch (Exception e) {
Gdx.app.log(TAG, e.toString());
}
Gdx.app.log(TAG, "Objects:"+mObjects.getCount());
for(Iterator<MapObject> mObjs = mObjects.iterator(); mObjs.hasNext();){
// I have set just about everything possible(I only have one object at the moment so mObj only gets set once.
mObj = mObjs.next();
Gdx.app.log(TAG, "Obj:"+mObj.getName());
mObj.setColor(Color.GREEN);
mObj.setOpacity(1f);
mObj.setVisible(true);
// try {
// Method Test = getClass().getDeclaredMethod((String) mObj.getProperties().get("Func"));
// Test.invoke(this);
// } catch (Exception e) {
// Gdx.app.log(TAG, e.toString());
// }
}
Array<String> sTilesets = new Array<String>();
TiledMapTile tile;
try {
for(Iterator<TiledMapTileSet> tilesets = map.getTileSets().iterator(); tilesets.hasNext();){
sI = tilesets.next().getName();
sTilesets.add(sI);
}
int tCount = sTilesets.size;
for(int i = 0; i < tCount; i++){
for(Iterator<TiledMapTile> tiles = map.getTileSets().getTileSet(sTilesets.get(i)).iterator(); tiles.hasNext();){
tile = tiles.next();
if(tile.getProperties().containsKey("blocked")){
//Gdx.app.log(TAG, "Tile:" + tile.getId() + " blocked!");
}
if(tile.getProperties().containsKey("name")){
//Gdx.app.log(TAG, "Name:" + tile.getProperties().get("name"));
}
boolean blocked = Boolean.parseBoolean(tile.getProperties().get("blocked", "false", String.class));
boolean event = Boolean.parseBoolean(tile.getProperties().get("event", "false", String.class));
Blocked.put(tile, blocked);
Event.put(tile, event);
}
}
Gdx.app.log(TAG, "Map Loaded!");
} catch (Exception e) {
Gdx.app.log(TAG, "Error:" + e.toString());
}
}
public TiledMap getMap(){
return gamemap;
}
}
答案 0 :(得分:6)
反正。我给出的答案和基于它的教程都使用Box2d来处理碰撞检测。如果你不是在制作你的游戏,那么全心全意建议走这条路线:如果你使用它,Box2d会为你处理很多,但它确实意味着重新思考你现有的很多代码。一切与运动有关,基本上。如果这就是你选择做的事情,好的LibGDX wiki可以帮助你开始(这是与相关文章的直接链接)。
如果你不想去那个兔子洞,那么上面的链接仍然建议一个解决方案。在我认为你出错的地方是试图直接绘制MapObject
s。试试这个:
MapObjects objects = map.getLayers().get("Obstacles").getObjects();
for(MapObject object : objects) {
if (object instanceof RectangleMapObject) {
Rectangle rect = ((RectangleMapObject) object).getRectangle();
// do something with rect...
}
else if (object instanceof PolygonMapObject) {
Polygon polygon = ((PolygonMapObject) object).getPolygon();
// do something with polygon...
}
else if (object instanceof PolylineMapObject) {
Polyline chain = ((PolylineMapObject) object).getPolyline();
// do something with chain...
}
else if (object instanceof CircleMapObject) {
Circle circle = ((CircleMapObject) object).getCircle();
// do something with circle...
}
}
从那里你处理生成的形状(Rectangle
或你有什么),而不是MapObject
。它们具有用于碰撞检测的方法,例如overlaps()
,contains()
等。如果你只处理一种形状,那么它可以让你在非Box2d游戏中变得更轻松。例如,仅使用if
的{{1}}语句,然后删除其他三个语句。
答案 1 :(得分:-1)
我想你需要为阻塞的瓷砖进行一种“映射”。因此,您无法始终检查瓷砖是否被阻挡。这需要很长时间来获得瓷砖。
这样做有不同的方法,但我用这个。
我写了自己的“地图”。此Map在我当前的TiledMap维度上保存一个Array。当我加载一个Map时,我确实在该mapArray中设置了一个值,所以我知道,如果我可以移动那个Tile。这看起来有点令人满意,并且需要花一些时间在更大的地图上,但确实有效。
private void setBlocked() {
for (int i = 0; i < this.map.getLayers().getCount(); i++) {
TiledMapTileLayer layer = (TiledMapTileLayer) this.map.getLayers()
.get(i);
for (int y = 0; y < layer.getHeight(); y++) {
for (int x = 0; x < layer.getWidth(); x++) {
if (layer.getCell(x, y) != null
&& layer.getCell(x, y).getTile().getProperties()
.containsKey("blocked")) {
this.mapArray[x][y] = Config.CANTMOVEONPOSITION;
}
}
}
}
}
要调试i渲染方块并以“mapState”的颜色填充它们,请执行以下操作:
if (this.map != null) {
for (int i = 0; i < this.map.width; i++) {
for (int j = 0; j < this.map.height; j++) {
switch (this.map.mapArray[i][j]) {
case Config.CHARSTATE:
// green
debugger.setColor(0, 1f, 0, Config.DEBUG_ALPHA);
break;
case Config.CANTMOVEONPOSITION:
// black
debugger.setColor(1f, 1f, 1f, Config.DEBUG_ALPHA + 0.1f);
break;
case Config.MONSTERSTATE:
// red
debugger.setColor(1f, 0, 0, Config.DEBUG_ALPHA);
break;
case Config.MOVETONEXTMAP:
// yellow
debugger.setColor(1f, 1f, 0, Config.DEBUG_ALPHA);
break;
default:
debugger.setColor(0, 0, 0, 0);
break;
}
debugger.rect(i * Config.TILE_SIZE, j * Config.TILE_SIZE,
Config.TILE_SIZE, Config.TILE_SIZE);
}
}
debugger.end();
}
这不是优化的!因此,如果你有一张大地图并且只显示一个小框架,它仍会绘制每个方格。在这种情况下,height and width
是高度和宽度的tilecount。
我希望这可以回答你的问题,或者你可以找到你的帮助。
问候