Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: 'Tiled' Tile-map Loader  (Read 201607 times)

0 Members and 4 Guests are viewing this topic.

fallahn

  • Hero Member
  • *****
  • Posts: 507
  • Buns.
    • View Profile
    • Trederia
Re: 'Tiled' Tile-map Loader
« Reply #30 on: June 14, 2013, 10:27:18 pm »
Ok so it looks like I made the silly mistake of naming a variable 'or', and there are some missing includes presumably because of VC's precompiled headers or somesuch. If I get time this weekend I'll take a look - I've been planning an update with a quadtree anyway. For now you can try renaming the variable and including cstring (I think, you'll have to look up memcpy)

EDIT: after taking a look this morning I've managed to get this working properly with MinGW / Code::Blocks. To fix it manually simply rename the variable

or

to something else like

orientation

and add

#include <cstring>

in MapLoaderPrivate.cpp. I've also updated the download file so if in doubt just re-downloaded it from my blog post.
« Last Edit: June 15, 2013, 10:44:30 am by fallahn »

NathanielSheller

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: 'Tiled' Tile-map Loader
« Reply #31 on: June 24, 2013, 03:32:14 pm »
Thank you ever so much :D, and sorry for the late reply, been a little busy.

fallahn

  • Hero Member
  • *****
  • Posts: 507
  • Buns.
    • View Profile
    • Trederia
Re: 'Tiled' Tile-map Loader
« Reply #32 on: June 26, 2013, 11:53:03 am »
No problem, hope it helps. I've updated it with quadtree partitioning for map objects



Which you can read about here  8)

fallahn

  • Hero Member
  • *****
  • Posts: 507
  • Buns.
    • View Profile
    • Trederia
Re: 'Tiled' Tile-map Loader
« Reply #33 on: July 03, 2013, 04:36:43 pm »
I've updated this again so now it draws maps using vertex arrays, and is nice and speedy! :D

mathme

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: 'Tiled' Tile-map Loader
« Reply #34 on: July 16, 2013, 04:21:41 pm »
I'm using window.mapPixelToCoords(sf::Mouse::getPosition(window)) to map world coordinates to map coordinates. Is this the best route to take?
« Last Edit: July 16, 2013, 04:49:14 pm by mathme »

fallahn

  • Hero Member
  • *****
  • Posts: 507
  • Buns.
    • View Profile
    • Trederia
Re: 'Tiled' Tile-map Loader
« Reply #35 on: July 16, 2013, 05:57:43 pm »
Yup, assuming you're passing the same window to the Draw function (ie you're not drawing to a render texture then drawing that texture to the window or something). Take a look at the isometric demo in the archive for an example.

mathme

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: 'Tiled' Tile-map Loader
« Reply #36 on: July 16, 2013, 11:36:48 pm »
Okay great thanks.

I'm not very familiar to Tiled so sorry if these questions have obvious answers.

My goal is to be able to manipulate the loaded in Tiled Map. Be able to add new things (flowers, monsters) and destroy these things as well.

Is there a way to go about this? From what I can see I can delete Objects, but Objects don't have any images associated with them.

Let me know if you have any ideas on this, thanks!

fallahn

  • Hero Member
  • *****
  • Posts: 507
  • Buns.
    • View Profile
    • Trederia
Re: 'Tiled' Tile-map Loader
« Reply #37 on: July 17, 2013, 11:00:14 am »
You can insert tiles on object layers and add all the associated properties which objects have using the tile tool (shortcut T iirc) in Tiled. These will be drawn by the map loader no problem. Currently there is a bug, however, when moving objects about where the associated debug graphic and AABB for the quad tree are not updated which I plan to fix in the near future. Personally speaking (I'm sure there are other and probably better ways to do this) I only use the map objects as static geometry for things such as solid objects or transition triggers. I usually create dynamic objects such as collectables, players or enemies as separate entities which can interact with each other and are drawn over the top of the map. It depends on what kind of game you are making, of course, but having the dynamic entities separate can also help with things like z-ordering when sprites need to move behind and in front of other objects. All dynamic objects can be made to interact with the loaded map by querying the quad tree (see the included example in the archive). If you want to place something like collectables in the map with Tiled you can do so with placeholder objects on their own layer, then when loading the map check that layer and use each object's position to spawn your collectable entity (or any other entity for that matter).

mathme

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: 'Tiled' Tile-map Loader
« Reply #38 on: July 22, 2013, 04:12:14 am »
I've decided to go with the last method you posted. I'm creating objects as placeholders for items. However, it would be nice to have a function to add an Object to the map. I know there is an addTile function, but it'd be much nicer to have the addObject function. Any chance that this would be a possibility in a future update?

fallahn

  • Hero Member
  • *****
  • Posts: 507
  • Buns.
    • View Profile
    • Trederia
Re: 'Tiled' Tile-map Loader
« Reply #39 on: July 22, 2013, 11:05:49 am »
I'm not entirely sure what you mean by an addObject function. Tiled objects contain a position and a shape as well as, optionally, user data and a tile from one of the tile sets. The map loader uses a MapObject class which just reflects these properties as well as adding a few utility functions for things like collision testing or drawing debug output. If you want to create a new MapObject programmatically you can by using the MapObject class just like any other C++ class, then use layer.objects.push_back(myObj) as all the objects are stored in a vector belonging to the object layer (see the MapLayer class). If you want extended functionality you'll need to create your own entities which you can compose from sf::Sprite or an animated sprite class, along with a reference to a MapObject, for example:

class MyEnt
{
public:
    MyEnt(tmx::MapObject& mo) : m_mapObj(mo){};
    void Update(float dt){//do ent logic here};
    //so we can draw with rt.draw(myEnt.GetSprite());
    const sf::Sprite& GetSprite(void) const{return m_sprite;};
private:
    sf::Sprite m_sprite;
    tmx::MapObject& m_mapObj;
};
 

Then your entity will have direct access to the map object to which it is bound, including its collision testing and debug drawing abilities. I've recently updated the MapObject class with a Move() function, as someone else has also requested it, but it's not generally the approach I take so I can't vouch for its effectiveness.

mflash

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: 'Tiled' Tile-map Loader
« Reply #40 on: September 07, 2013, 07:15:44 pm »
Matt, first of all thanks for your code. It works really well!

I've just found a little bug when you compute the number of rows and columns in MapLoader::m_ProcessTiles:

const bool MapLoader::m_ProcessTiles(const pugi::xml_node& tilesetNode)
{
        sf::Uint16 tileWidth, tileHeight, spacing, margin;
        ...
        //slice into tiles
        int columns = sourceImage->getSize().x / tileWidth;
        int rows = sourceImage->getSize().y / tileHeight;
 

This won't take into account the spacing and margin of the tileset, if any. I've discovered by accident, trying to load a map with the blocks1.png tileset (attached below). That tileset requires a margin and spacing of 2 pixels.

The fix is easy:

const bool MapLoader::m_ProcessTiles(const pugi::xml_node& tilesetNode)
{
        sf::Uint16 tileWidth, tileHeight, spacing, margin;
        ...
        //slice into tiles
        int columns = (sourceImage->getSize().x-margin) / (tileWidth+spacing);
        int rows = (sourceImage->getSize().y-margin) / (tileHeight+spacing);
 

Hope it helps  :)

Cheers!
« Last Edit: September 08, 2013, 01:03:47 am by mflash »

fallahn

  • Hero Member
  • *****
  • Posts: 507
  • Buns.
    • View Profile
    • Trederia
Re: 'Tiled' Tile-map Loader
« Reply #41 on: September 08, 2013, 09:15:42 am »
Oh! Thanks, I shall add your fix as soon as I can :D

mflash

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: 'Tiled' Tile-map Loader
« Reply #42 on: September 13, 2013, 02:08:10 pm »
Glad to be of help  :)

I have another quick question for you: I'm trying to check for collisions between a sprite and a collision layer of tiles, but your MapTile struct doesn't store the GID of a tile. Hence I added a gid field to the struct as follows:

struct MapTile
{
        //returns the base centre point of sprite / tile
        const sf::Vector2f GetBase(void) const
        {
                return sf::Vector2f(sprite.getPosition().x + (sprite.getLocalBounds().width / 2.f),
                sprite.getPosition().y + sprite.getLocalBounds().height);
        }
        sf::Sprite sprite;
        sf::Vector2i gridCoord;
        sf::Uint16 gid; // need gid to check contents
        sf::RenderStates renderStates; //used to perform any rendering with custom shaders or blend mode
};
 

What do you reckon? Is that a sensible approach?

Cheers!

fallahn

  • Hero Member
  • *****
  • Posts: 507
  • Buns.
    • View Profile
    • Trederia
Re: 'Tiled' Tile-map Loader
« Reply #43 on: September 13, 2013, 05:34:28 pm »
Honestly? I couldn't say without knowing more about what you're trying to do. I've tried to make the loader as generic as possible but there is bound to be some need for customisation for any project. If it works for you, then it's good I guess :) I've personally always handled collisions by drawing data on an object layer then using the quadtree to query objects near the sprite but, like I say, I don't really know what fits your particular project :)

Jove

  • Full Member
  • ***
  • Posts: 114
    • View Profile
    • http://www.jestofevekites.com/
Re: 'Tiled' Tile-map Loader
« Reply #44 on: September 13, 2013, 08:20:26 pm »
RE your quadtree implementation... Would it not be more effecient to add a 'remove' function rather than recreating the tree each frame? That way, any object that has moved is removed from the tree and re-added in the new position.

For myself I made a simple spacial partitioning system with a fixed-size grid that implemented the remove/add technique, it's only created once.

BTW, that car game would look awesome with a rotating view! :)
{much better code}

 

anything