2013-04-28 3 views
1

Я использую libGDX и Плиточный для создания РПГ. У меня уже много работы: экран заголовка, экран тестирования, на котором моя карта загружена. Я могу прочитать свойства, которые я положил на карту и на определенные плитки. Я также могу перемещаться по карте и всему, но сейчас я пытаюсь выяснить:libGDX: Как обрабатывать столкновений для спрайтов с слоя слоя 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; 
    } 
} 

ответ

-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 - это ширина по ширине и ширине.
Надеюсь, это ответит на ваш вопрос, или вы можете найти свой путь с этой помощью.
С уважением

+0

Я боюсь, что ваш ответ не имеет ничего общего с q, который был связан с отображением объектов карты из слоя объекта. Выполнение этого на уровне плитки предполагает, что слой плитки и ячейка там приводят к несколько ужасному синтаксическому анализу плитки карты и последующему дублирующему массиву в вашем решении. Использование объектов карты, как описано в q и первом ответе, бесконечно более мощно, поскольку объекты карты могут быть легко превращены в объекты b2d и не ограничены размером одной ячейки. – RichieHH

6

I answered a similar question на GameDev в последнее время, будучи в тупике той же проблемой на некоторое время. Тщательный Гуглинг в конечном итоге привел меня к a tutorial по этому вопросу. И я имею в виду тщательно. Кажется, это единственное решение этой проблемы во всем Интернете. Weird.

В любом случае. Ответ, который я дал, и руководство было основано на использовании 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 для PolygonMapObject, например, и отпустите остальные три.

Смежные вопросы