Getting Tile Info

Jul 8, 2011 at 3:08 PM

Hey, really liking tIDE and xTile. I've got a question though - how do i get info on the tiles inside of c#/XNA? I'd like to make a layer with a collision map and check for collisions in my Playersprite Update(). I've tried finding out via Intellisense and the provided XML, but no luck so far.

Jul 8, 2011 at 3:15 PM

OK searching the discussions sort of helped ... duh.

Coordinator
Jul 8, 2011 at 9:40 PM

Glad you figured it out! If you have further questions just let me know.

Jul 9, 2011 at 10:00 AM

Well you could help me clear up what the difference is between xTile's and XNA's Rectangle structures. It would also help if the xTile Rectangle would be called something like xRectangle so i don't have to provide the full namespace to access them when i use both.

Jul 9, 2011 at 11:24 AM
Edited Jul 9, 2011 at 11:46 AM

Here's my collision code for a top down oldschool Zelda like situation, in case someone might find it useful. I'm pretty much a beginner coder,

but i think the logic is sound. Of course you're welcome to point out an easier / faster way of doing this :)

I calculate the texture rectangle for the sprite centered at the center of a collision box, which saves some writing in figuring out the collision.

For the collision detection i just check each corner of the collision box to see if it hits a solid tile (index 0 in my collision map on layer 1),

and if so overwrite the new coordinates stored in the variable newPos with the original position. Using a collision box allows for the sprite to

be centered at the feet, this way the torso and head overlap any tiles above it.

 

By the way, where can i get the source code for the demo application? I haven't found it so far.

 

        Map map;
        Layer collision;

        public PlayerSprite(Texture2D texture, Point position, Microsoft.Xna.Framework.Rectangle collisionBox, Map map)
            : base(texture, position, collisionBox)
        {
            this.map = map;
            collision = map.Layers[1];
        }

        public void Update()
        {
            Point newPos = position;
                        
            KeyboardState keyState = Keyboard.GetState();

            if (keyState.IsKeyDown(Keys.W))
                newPos.Y-=2;
            if (!calculateCollision(newPos))
                position.Y = newPos.Y;
            else
                newPos.Y = position.Y;

            if (keyState.IsKeyDown(Keys.S))
                newPos.Y += 2;
            if (!calculateCollision(newPos))
                position.Y = newPos.Y;
            else
                newPos.Y = position.Y;

            if (keyState.IsKeyDown(Keys.A))
                newPos.X -= 2;
            if (!calculateCollision(newPos))
                position.X = newPos.X;
            else
                newPos.X = position.X;

            if (keyState.IsKeyDown(Keys.D))
                newPos.X += 2;
            if (!calculateCollision(newPos))
                position.X = newPos.X;
            else
                newPos.X = position.X;
        }

        private bool calculateCollision(Point newPos)
        {
            Tile tile;
            Location tileLocation;

            Debug.WriteLine("cx: " + collisionBox.X + " cy: " + collisionBox.Y + "\n");

            tileLocation = new Location((newPos.X - collisionBox.Width / 2) / 64,
                (newPos.Y - collisionBox.Height / 2) / 64);
            tile = collision.Tiles[tileLocation];
            if (tile.TileIndex == 0)
                return true;

            tileLocation = new Location((newPos.X + collisionBox.Width / 2) / 64, 
                (newPos.Y - collisionBox.Height / 2) / 64);
            tile = collision.Tiles[tileLocation];
            if (tile.TileIndex == 0)
                return true;

            tileLocation = new Location((newPos.X + collisionBox.Width / 2) / 64,
                (newPos.Y + collisionBox.Height / 2) / 64);
            tile = collision.Tiles[tileLocation];
            if (tile.TileIndex == 0)
                return true;

            tileLocation = new Location((newPos.X - collisionBox.Width / 2) / 64,
                (newPos.Y + collisionBox.Height / 2) / 64);
            tile = collision.Tiles[tileLocation];
            if (tile.TileIndex == 0)
                return true;

            return false;
        }
Coordinator
Jul 9, 2011 at 2:51 PM

Your collision detection code looks good to me. I personally like the idea of using a layer just for collision detection and other markers. You could also use custom tile properties at the layer or tilesheet level.

As for the demo code, you can access the source code from the Source Code tab above or by clicking this link: http://tide.codeplex.com/SourceControl/BrowseLatest. This will let you browse online within the code, which consists of a VS solution with a number of project folders. One of these folders, named Demo contains the demo code with three project files (PC, X360, WP7) sharing the code within.

Jul 9, 2011 at 3:53 PM

Thank you!

Mar 7, 2013 at 6:42 AM
Anyone have sample code of how to reference the tiles in the map for collision detection, I have yet to figure it out even with these examples. I have a 2 layers a "walls" layer and a "floor" layer. Just want to access the walls layer and detect if my player is colliding with any walls but how to access the tiles is the question?
Any helpful code with explanation would be greatly appreciated.
Thanks,
Coordinator
Mar 7, 2013 at 8:57 AM
There is a sample in this very thread if you look carefully enough. There are also plenty of answers throughout the forum.
Nov 11, 2014 at 1:31 AM
I am new to xtiled and I am not very confident with its functions yet. I have a "wall" layer and want to prevent the player from moving when he collides with that layer.
I have tried to use Loco's collision code but instead of preventing the player from walking through the tile, I get the error: "Indices out of bounds". Does someone know why I get this error?
I have searched for several examples but it did not stick well enough to write good code for this. Could somebody explain me how to check for collision of player and wall layer in a bit more detail so I get it well enough to implement my own code??? Thanks a lot in advance!
Coordinator
Nov 11, 2014 at 1:58 PM
Edited Nov 11, 2014 at 2:00 PM
The following code
tile = collision.Tiles[tileLocation];
if (tile.TileIndex == 0)
    return true;
will crash when the coordinates of tileLocation are not within the size of the Layer (called collision here). To fix this, you need to add some checks like so:
if (tileLocation.x >= 0
    && tileLocation.y >= 0
    && tileLocation.x < collision.Layerwidth
    && tileLocation.y < collision.layerHeight)
{
    tile = collision.Tiles[tileLocation];
    if (tile.TileIndex == 0)
        return true;
}