1

libGDXTiledを使用して RPG を作成しています。タイトル画面、テスト画面、マップが読み込まれているなど、すでに多くの作業が行われています。マップと特定のタイルに配置したプロパティを読み取ることができます。マップやすべてを移動することもできますが、今把握しようとしているのは次のとおりです。

オブジェクト レイヤーからマップ オブジェクトをレンダリングし、衝突を処理するにはどうすればよいですか?

コリジョン レイヤーに Tiled のオブジェクト レイヤーを使用したいと考えています。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;
    }
}
4

2 に答える 2

6

私は最近、GameDev で同様の質問に答えましたが、しばらく同じ問題に悩まされていました。徹底したグーグル検索により、最終的にこのテーマに関するチュートリアルにたどり着きました。そして、私は徹底的に意味します。これは、インターネット全体でこの問題を解決する唯一の方法のようです。変。

ともかく。私が与えた答えとそれに基づいたチュートリアルでは、どちらも Box2d を使用して衝突検出を処理しています。ゲームの作成にあまり慣れていない場合は、この方法を使用することを心からお勧めします。Box2d を使用すると、かなりの処理が行われますが、既存のコードの多くを再考する必要があります。基本的に、動きに関係するすべて。それを選択した場合は、古き良きLibGDX wikiから始めることができます (関連記事への直接リンクです)。

そのうさぎの穴に行きたくない場合でも、上記のリンクは解決策を提案しています. あなたが間違っていると思うところは、MapObjects を直接描画しようとしているところです。これを試して:

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、s ではなく、生成された形状 (またはあなたが持っているもの) を処理しますMapObjectoverlaps()などの衝突検出に役立つメソッドがありますcontains()。1 種類のシェイプのみを扱う場合は、Box2d 以外のゲームでの作業が楽になります。たとえば、ifステートメント forのみを使用し、他の 3 つを削除します。PolygonMapObject

于 2014-02-18T13:40:33.293 に答える
-1



ブロックされたタイルには一種の「マッピング」が必要だと思います。そのため、タイルがブロックされているかどうかを常に確認することはできません。これは、タイルを取得するのに時間がかかります。
やり方はいろいろありますが、私はこれを使いました。
私は自分の「地図」を書きました。このマップは、現在の TiledMap の次元で配列を保持します。マップをロードするとき、その mapArray 内に値を設定するので、そのタイルに移動できるかどうかがわかります。これは少し恐ろしく見え、大きなマップでは時間がかかりますが、うまくいきます。

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;
                }
            }
        }
    }
}

デバッグするには、正方形をレンダリングし、次のように「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場合、高さと幅のタイル数です。
これがあなたの質問に答えるか、その助けを借りて道を見つけることができることを願っています.
よろしく

于 2013-04-28T13:37:05.983 に答える