Getting Object from Tiled map

I’m trying to get information from objects in a Tiled map but I can’t find how. TCastleTiledMapData exposes only the tiles data through TCastleTiledapData.TileRenderData () (which isn’t documented, by the way) but the editor renders the objects, so it contains the data and is accessible. But how?

In general, the answer depends on the exact information you need.

function TUnitsOnMap.IsWater(const TilePosition: TVector2Integer): Boolean;
var
  Tileset: TCastleTiledMapData.TTileset;
  Frame: Integer;
  HorizontalFlip, VerticalFlip, DiagonalFlip: Boolean;
begin
  Result := Map.Data.TileRenderData(TilePosition,
    Map.Data.Layers[0],
    Tileset, Frame, HorizontalFlip, VerticalFlip, DiagonalFlip) and
    { Water is on 1, 5, 9 tiles (counting from 0) in data/maps/tileset-terrain.png . }
    ((Frame mod 4) = 1);
end;

Let me know which exactly information you’re looking for, I can help there more:)

I know I can get information from tile layers, but I need information from object layers (points, rectangles, polygons, ellipses, etc.). For example: I’m using points to mark the player and enemy spawn places and polygons to define the paths. But I can’t find how I can retrieve this information. I need to check their name and type (to know what it defines) and retrieve the information (coordinates, vectors…) to use it in the game.

I’ve dug in CGE sources and found the way by myself. But I think this should be added to the Tiled section. Also not all types are documented (i.e. TCastleTiledMapData.TTiledObject isn’t).

The code I’m using is similar to this one:

const
(* Name of the objects layer. *)
  ObjectsLayer = 'Objects';
(* Name of the object that marks the player's initial position. *)
  PlayerInitialPosition = 'Player';



(* Get the initial position of the player from the map's objects layer. *)
  procedure GetInitialPosition (aMap: TCastleTiledMap): TVector3;
  var
    lObjectsLayer: TCastleTiledMapData.TObjectGroupLayer = Nil;
    lNdx, lMapHeight: Integer;
    lFound: Boolean = False;
  begin
  { Get map height in pixels. }
    lMapHeight := aMap.Data.Height * aMap.Data.TileHeight;
  { Find objects layer. }
    for lNdx := 0 to aMap.Data.Layers.Count - 1 do
      if aMap.Data.Layers[lNdx].Name = ObjectsLayer then
        lObjectsLayer := aMap.Data.Layers[lNdx] as TCastleTiledMapData.TObjectGroupLayer;
    Assert (Assigned (lObjectsLayer), Concat ('No "', ObjectsLayer, '" layer.'));
  { Find initial position. }
    Result := TVector3.Zero;
    for lNdx := 0 to lObjectsLayer.Objects.Count - 1 do
      if lObjectsLayer.Objects.Items[lNdx].Name = PlayerInitialPosition then
      begin
        Result.X := lObjectsLayer.Objects.Items[lNdx].X;
      { Y is inverted (Tiled grows down, CGE grows up). }
        Result.Y := lMapHeight - lObjectsLayer.Objects.Items[lNdx].Y;
        lFound := True
      end;
    Assert (lFound, 'No initial position in map!')
  end;

Of course you can add this snippet to the manual documentation as it is or modified.

I’ve also written a small platformer game example. I wrote it in Spanish, but I can translate to English and send to you to add it as a game demo if you want. It includes tile colisions (I’ve wrote the collision algorithms by myself because I didn’t found if CGE is able to deal with it).

Sorry for a delay in reply – and I see you found the data, cool.

Indeed, not all there is documented, and I’m not yet 100% sure do we have the optimal API there. But we should improve at some point :slight_smile:

Note that we have a big platformer demo as part of the engine:) It uses physics colliders to solve collisions.

Of course you’re still welcome to share your version! I encourage to post in the Show Your Projects category. I love to see how everyone is using our engine, this is always giving me inspiration.

1 Like