Objektide parsimine

Hetkel oleme loonud staatilise (töötab nagu taust, st pole collisione) kaardi. Nüüd peame õppima, kuidas parsida objekte, et luua seinad, liikuvad objektid jne.

Objektide loomiseks teeme Tiled'is uue kihi Layer -> New -> Object Layer ja nimetame seda fence'ks.

Tile kihtide ja objektide kihtide erinevus on selles, et tile kiht on mõeldud kaardi joonistamiseks ja objektide kiht on mõeldud näiteks collisionite loomiseks.

Object layer

Valime fence kihi ja siis meil on valida kolme kujundi, punkti ning terve Tile'i vahel.

  • Rectangle Object (enim kasutatud)

  • Point Object

  • Ellipse Object

  • Polygon Object

  • Tile Object

Object types

Rectangle Object

Ristküliku objekti jaoks vajutame Insert Rectangle või R klaviatuuril.

Kui hoida SHIFT, siis on lihtsam joonistada ruutu. Kui hoida CTRL, siis on lihtsam joonistada üle ruudustiku.

Rectangle object

Parsime kõik objektid kaardilt.

TiledMapLoader.java

/**
 * Parse all objects from all layers of the TiledMap.
 */
public TiledMapLoader parseAllObjects() {
    // iterating all layers
    for (MapLayer mapLayer : map.getLayers()) {
        // iterating all objects in current the layer
        for (MapObject mapObject : mapLayer.getObjects()) {
            // check if current MapObject is instance of RectangleMapObject and cast MapObject to RectangleMapObject
            if (mapObject instanceof RectangleMapObject rectangleMapObject) {
                // get rectangle from RectangleMapObject
                Rectangle rectangle = rectangleMapObject.getRectangle();
                // ...
            }
        }
    }
    return this;
}

Või parsime ainult konkreetse kihi objektid.

TiledMapLoader.java

/**
 * Parse objects from specific layer of the TiledMap.
 *
 * @param layer name of the layer to parse
 */
public TiledMapLoader parseObjectByLayer(String layer) {
    // finding objects from layer by name and iterating
    for (MapObject mapObject : map.getLayers().get(layer).getObjects()) {
        // check if current MapObject is instance of RectangleMapObject and cast MapObject to RectangleMapObject
        if (mapObject instanceof RectangleMapObject rectangleMapObject) {
            // get rectangle from RectangleMapObject
            Rectangle rectangle = rectangleMapObject.getRectangle();
            // ...
        }
    }
    return this;
}

Ja kasutame ekraani klassis.

GameScreen.java

@Override
public void show() {
    camera = new OrthographicCamera();
    mapRenderer = new TiledMapLoader("tiled/map.tmx")
            .parseObjectByLayer("fence")
            // .parseAllObjects()
            .setupMap();
    worldWidth = (int) mapRenderer.getMap().getProperties().get("width") * Constants.PPM;
    worldHeight = (int) mapRenderer.getMap().getProperties().get("height") * Constants.PPM;
}

Point Object

Punkti objekti jaoks vajutame Insert Point või I klaviatuuril.

Point object

Punktide jaoks pole konkreetset klassi ja kasutatakse RectangleMapObject null pikkusega ja kõrgusega (width=0,height=0), sest punktil pole suurust.

Punktide kasutamine saab olla kasulik mängija alguspunktide loomisel. Saab panna mitu punkti ja juhuslikult mängija spawnida.

Ellipse Object

Ovaalsete objektide jaoks vajutame Insert Ellipse või C klaviatuuril.

Ellipse object

TiledMapLoader.java

/**
 * Parse all objects from all layers of the TiledMap.
 */
public TiledMapLoader parseAllObjects() {
    // iterating all layers
    for (MapLayer mapLayer : map.getLayers()) {
        // iterating all objects in current the layer
        for (MapObject mapObject : mapLayer.getObjects()) {
            // check if current MapObject is instance of EllipseMapObject and cast MapObject to EllipseMapObject
            if (mapObject instanceof EllipseMapObject ellipseMapObject) {
                // get ellipse from EllipseMapObject
                Ellipse ellipse = ellipseMapObject.getEllipse();
                // ...
            }
        }
    }
    return this;
}

Polygon Object

Hulknurksete objektide jaoks vajutame Insert Polygon või P klaviatuuril.

Polygon object

TiledMapLoader.java

/**
 * Parse all objects from all layers of the TiledMap.
 */
public TiledMapLoader parseAllObjects() {
    // iterating all layers
    for (MapLayer mapLayer : map.getLayers()) {
        // iterating all objects in current the layer
        for (MapObject mapObject : mapLayer.getObjects()) {
            // check if current MapObject is instance of PolygonMapObject and cast MapObject to PolygonMapObject
            if (mapObject instanceof PolygonMapObject polygonMapObject) {
                // get polygon from PolygonMapObject
                Polygon polygon = polygonMapObject.getPolygon();
                // ...
            }
        }
    }
    return this;
}

Tile Object

Tile objektide jaoks vajutame Insert Tile või T klaviatuuril, valime Tileset aknast soovitud tile'i ja paneme seda kaardi peale.

Tile object
/**
 * Parse all objects from all layers of the TiledMap.
 */
public TiledMapLoader parseAllObjects() {
    for (MapLayer mapLayer : map.getLayers()) { // iterating all layers
        for (MapObject mapObject : mapLayer.getObjects()) { // iterating all objects in current the layer
            if (mapObject instanceof TiledMapTileMapObject tiledMapTileMapObject) { // check if current MapObject is instance of TiledMapTileMapObject and cast MapObject to TiledMapTileMapObject
                float x = tiledMapTileMapObject.getX();
                float y = tiledMapTileMapObject.getY();
                TextureRegion textureRegion = tiledMapTileMapObject.getTextureRegion();
                // use variables to draw SpriteBatch
            }
        }
    }
    return this;
}

Kasutame siin TextureRegion, et saada sama tekstuur, mis oli kasutatud objekti loomisel.

*Tile objektid saab ka kasutada, et joonistada ilma ruudustiku joondust järgimatta.

Objektide sidumine

Objekte saab ka omavahel siduda. Näiteks saab luua vaenlase objekti ja panna punkti kuhu ta peaks minema.

Esiteks, paneme objektid kaardile.

Add objects

Siis lisame objektile uus omadus path ja paneme Object tüüp.

Add property
Object

Valime nupu Select Object on Map ja vajutame teise objekti peale.

Select Object on Map

Ja pärast saab seda objekti kätte kasutades

object.getProperties().get("path");

Kõik kujunditüübid koos

Mõnikord peab kasutama mitut tüüpi korraga.

TiledMapLoader.java

/**
 * Parse all objects from all layers of the TiledMap.
 */
public TiledMapLoader parseAllObjects() {
    for (MapLayer mapLayer : map.getLayers()) { // iterating all layers
        for (MapObject mapObject : mapLayer.getObjects()) { // iterating all objects in current the layer
            if (mapObject instanceof RectangleMapObject rectangleMapObject) { // check if current MapObject is instance of RectangleMapObject and cast MapObject to RectangleMapObject
                Rectangle rectangle = rectangleMapObject.getRectangle(); // get rectangle from RectangleMapObject
                // ...
            } else if (mapObject instanceof EllipseMapObject ellipseMapObject) { // check if current MapObject is instance of EllipseMapObject and cast MapObject to EllipseMapObject
                Ellipse ellipse = ellipseMapObject.getEllipse(); // get ellipse from EllipseMapObject
                // ...
            } else if (mapObject instanceof PolygonMapObject polygonMapObject) { // check if current MapObject is instance of PolygonMapObject and cast MapObject to PolygonMapObject
                Polygon polygon = polygonMapObject.getPolygon(); // get polygon from PolygonMapObject
                // ...
            } else if (mapObject instanceof TiledMapTileMapObject tiledMapTileMapObject) { // check if current MapObject is instance of TiledMapTileMapObject and cast MapObject to TiledMapTileMapObject
                float x = tiledMapTileMapObject.getX();
                float y = tiledMapTileMapObject.getY();
                TextureRegion textureRegion = tiledMapTileMapObject.getTextureRegion();
                // use variables to draw SpriteBatch
            }
        }
    }
    return this;
}

On ka teine variant, kuidas seda saab kirjutada, kasutades switch. Minu lõplik variant:

TiledMapLoader.java

/**
 * Parse objects from specific layer of the TiledMap.
 *
 * @param layer name of the layer to parse
 */
public TiledMapLoader parseObjectByLayer(String layer) {
    for (MapObject mapObject : map.getLayers().get(layer).getObjects()) { // finding objects from layer by name and iterating
        handleMapObject(mapObject);
    }
    return this;
}

/**
 * Parse all objects from all layers of the TiledMap.
 */
public TiledMapLoader parseAllObjects() {
    for (MapLayer mapLayer : map.getLayers()) { // iterating all layers
        for (MapObject mapObject : mapLayer.getObjects()) { // iterating all objects in current the layer
            handleMapObject(mapObject);
        }
    }
    return this;
}

/**
 * Handle object according to its type
 *
 * @param mapObject map object to handle
 */
public void handleMapObject(MapObject mapObject) {
    switch (mapObject) {
        case RectangleMapObject object -> { // If object is instance of RectangleMapObject
            Rectangle rectangle = object.getRectangle(); // get rectangle from RectangleMapObject
            // ...
        }
        case EllipseMapObject object -> { // If object is instance of EllipseMapObject
            Ellipse ellipse = object.getEllipse(); // get ellipse from EllipseMapObject
            // ...
        }
        case PolygonMapObject object -> { // If object is instance of PolygonMapObject
            Polygon polygon = object.getPolygon(); // get polygon from PolygonMapObject
            // ...
        }
        case TiledMapTileMapObject object -> { // If object is instance of TiledMapTileMapObject
            float x = object.getX();
            float y = object.getY();
            TextureRegion textureRegion = object.getTextureRegion();
            // use variables to draw SpriteBatch
        }
        default -> System.out.println("Some other type");
    }
}

GameScreen.java

@Override
public void show() {
    camera = new OrthographicCamera();
    mapRenderer = new TiledMapLoader("tiled/map.tmx")
        .parseObjectByLayer("fence")
        // .parseAllObjects()
        .setupMap();
    worldWidth = (int) mapRenderer.getMap().getProperties().get("width") * Constants.PPM;
    worldHeight = (int) mapRenderer.getMap().getProperties().get("height") * Constants.PPM;
}

- Kui on soovi, saab detailselt uurida materjale objektide loomisest: https://doc.mapeditor.org/en/stable/manual/objects/
- Edasi tutvuge teemaga `Collision <https://gamedevdoc.pages.taltech.ee/collision/collision.html>`__