1. Mis on Tiled¶
Tiled on 2D/3D kaardiredaktor, mis aitab luua mängumaailma. Põhifunktsiooniks on mängukaartide loomine kasutades Tileset. Tiled'i plussiks on selle paindlikkus ja intuitiivsus.
Tileset on mingi pakk tekstuurides, mida saab kasutada kaartide joonistamiseks
Kui tekkivad probleemid, siis saab avada originaalkoodi ja otsida mis läks valesti.
2. Tiled'i seadistamine¶
2.1. Uue kaardi loomine¶
Vajuta
New Map
'i peale;Map
sätted pole vaja muuta;Map Size
sätted võivad olla erinevad, sõltuvad projektist, aga siin hakkame kasutama 60x34 (1920x1088 pikselit) (vajadusel saab muuta pärast loomist);Tile size
säte sõltub projektist, tavaliselt kasutatakse 16x16, 32x32, 64x64, 128x128 jne, kuid selles juhendis hakkame kasutama 32x32;Vajutame
Ok
.

2.2. Lisa uus Tileset¶
Alguses on kaart tühi. Esialgul loome uue Tileset'i, vajutades New Tileset
nuppu.
Tileset ei pea olema üks, saab lisada mitu korraga, kui on vajadus.

Seejärel otsime Tileset'i (või loome käsitsi uue). Selleks, et leida sobiv Tileset, saab kasutada erinevaid ressursse. Näiteks, saab kasutada craftpix. Ise olen valinud seda. Samuti tuleb meeles pidada, et tuleb otsida Tileset suurusega 32x32, või kui teie projektis on teine suurus, siis vastav suurus.


Uus tileset avab end küll uues aknas. Aga sellega ei pea midagi tegema ja saab lihtsalt tagasi projekti aknasse minna. Tileset on automaatselt laaditud meie esialgse projektiakna Tileset aknasse paremal ääres.
2.3. Kaardi loomine¶

Valime Tileset aknast tile'i ja hakkame kanval joonistama.
Lõpuks vajutame CTRL + S
või COMMAND + S
, et salvestada oma kaardi.
Väga soovitan natuke katsetada ja proovida kogu Tiled'i funktsionaalsus üleval ribal.
3. Koodiosa¶
Esialgul, loome uue klassi TiledMapLoader
.
Teeme seda selleks, et meie projektis oleks struktuur ja kui on soov seda taaskasutada, et oleks lihtsam.
TiledMapLoader.java
public class TiledMapLoader {
private TiledMap map;
/**
* @param path path to the map, starting from /assets folder
*/
public TiledMapLoader(String path) {
this.map = new TmxMapLoader().load(path);
}
/**
* @return OrthogonalTiledMapRenderer of the TiledMap
*/
public OrthogonalTiledMapRenderer setupMap() {
return new OrthogonalTiledMapRenderer(map);
}
}
Kutsume enda kaardiklassi välja endale sobivas Screen
liidest implementivas klassis.
GameScreen.java
private OrthogonalTiledMapRenderer mapRenderer;
@Override
public void show() {
mapRenderer = new TiledMapLoader("tiled/map.tmx").setupMap();
}
@Override
public void render(float delta) {
Gdx.gl.glClearColor(1f, 1f, 1f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
mapRenderer.render();
}
See töötab praegu, aga näeb jube välja.
Kaart on kusagil vasakul ja seda on näha ainult osaliselt.
Selleks loome kaamera ja lingime seda koos mapRenderer
'iga.
Mainiks ka seda, et kasutame OrthographicCamera
, sest meil on 2D mäng ja kasutades seda tüüpi kaamerat me saame näha meie maailma ilma perspektiivita
GameScreen.java
private OrthographicCamera camera;
private float worldWidth;
private float worldHeight;
@Override
public void show() {
camera = new OrthographicCamera();
mapRenderer = new TiledMapLoader("tiled/map.tmx").setupMap();
worldWidth = (int) mapRenderer.getMap().getProperties().get("width") * Constants.PPM;
worldHeight = (int) mapRenderer.getMap().getProperties().get("height") * Constants.PPM;
}
@Override
public void render(float delta) {
Gdx.gl.glClearColor(1f, 1f, 1f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
mapRenderer.setView(camera);
mapRenderer.render();
}
@Override
public void resize(int width, int height) {
camera.setToOrtho(false, worldWidth, worldHeight); // Set camera to an orthographic projection and set viewport
}
Loome uue klassi Constants
ja lisame PPM
.
Constants.java
public class Constants {
public static final float PPM = 32.0f;
}
PPM (pixels per meter)
defineerib mängumaailma meetrite ja ekraanipikslite omavaheline seos (1 meeter mängumaailmas on võrdne 32 piksliga).

4. Kuidas objekte parsida¶
Hetkel oleme loonud staatilise(töötab nagu taust, sh 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 selleks, et luua näiteks collisione.

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

4.1. Rectangle Object¶
Ristküliku objektide jaoks vajutame Insert Rectangle
või R
klaviatuuril, et valida.
*Kui hoida SHIFT
, siis on lihtsam joonistada ruudu. Kui hoida CTRL
, siis on lihtsam joonistada üle ruudustiku.

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;
}
4.2. Point Object¶
Punkti objektide jaoks vajutame Insert Point
või I
klaviatuuril, et valida.

Punktide jaoks pole konkreetse 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.
4.3. Ellipse Object¶
Ovaalsete objektide jaoks vajutame Insert Ellipse
või C
klaviatuuril.

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;
}
4.4. Polygon Object¶
Hulknurkseid objektide jaoks vajutame Insert Polygon
või P
klaviatuuril, et valida.

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;
}
4.5. Tile Object¶
Tile objektide jaoks vajutame Insert Tile
või T
klaviatuuril, et valida. Valime Tileset aknast tile ja paneme seda kaardi peale.

/**
* 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 mis tekstuur oli kasutatud objekti loomisel.
*Tile objektid saab ka kasutada, et joonistada ilma ruudustiku joondust järgimatta.
4.6. Lisainfo
Kui on soovi, saab detailselt uurida materjale objektide loomisest.
https://doc.mapeditor.org/en/stable/manual/objects/
Objektide sidumine
Objekte saab ka omavahel siduda. Näiteks saab luua vaenlase objekti ja panna punkti kuhu ta peaks minema.
Esiteks, paneme objektid kaardile.

Siis lisa objektile uus omadus path
ja pane Object
tüüp


Ja vali nuppu Select Object on Map
ja vajuta teise objekti peale.

Ja pärast võib saada see objekt kasutades
object.getProperties().get("path");
6. Kõik kujunditüüpid koos¶
Mõnikord peab kasutama mitu tüüpe 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;
}