Reading single Tile Texture in Game

Oct 26, 2011 at 12:32 PM

Greetings:
First I'd like to say that this is great tool, and it has helped me with the project i've been working on.
However, i have encounter a problem, when I'm using a *Physics Engine* with the fixtures and polygons in order to create the interactions and colisions.
And I would like to know if it's possible to read a texture which is using a selected tile, taking in count that the engine itself has a function for processing the texture enabling the creation of the element on the physics engine.

I appreciated your time, and i'll be waiting for your reply.

Coordinator
Oct 26, 2011 at 12:43 PM
Edited Oct 26, 2011 at 12:43 PM

What sort of problem have you encountered when using a physics engine with the tile engine?

As for getting the tilesheet texture, it is possible to do this indirectly via the TileSheet's ImageSource property. You should be able to use this as an asset reference via the content pipeline, like so:


// get first tilesheet in map
TileSheet tileSheet = map.TileSheets[0];

// load tilesheet texture from content pipeline
Texture2D tileSheetTexture = Content.Load<Texture2D>(tileSheet.ImageSource); 
Oct 27, 2011 at 1:40 AM

Thanks for replying so soon!

My issue show up when my character steps on a cutted tile, like a ramp. I need to know how to access every tile texture, since, in order the physics engine already allows me to create non-square elements.

I'm gonna start with your method, but i would like to know if you can read only one tile as it shows in the tile picker's editor. Just one, so i can process tile by tile every texture so i can build properly all the floor that the characters using the physics engine function to create polygons.

Something like this (just invented code) 

//Read tile texture
Texture2D polygonTexture = tile[0].texture;

//Create physic object to collision with the player
Polygon object = Engine.CreatePolygon(polygonTexture, polygonTexture.Width, polygonTexture.Height);

Thanks again.

Coordinator
Oct 27, 2011 at 7:40 AM

The tilesheet texture is shared by all tiles in a tilesheet. But you can cut out the tile as a subtexture using the tile's index number, size, margin from the top and left and spacing between tiles. You can get these properties from the TileSheet object.

However I'm not sure if what you're trying to achieve is sound. Does your Engine.CreatePolygon method scan the pixels within the texture to create the required shape?

Oct 27, 2011 at 1:13 PM

Thanks again for replying!
I hadn't figure out using subtextures. I'll try that way.
I'm using Farseer physics engine, the same has a function which allows you to convert a texture into a polygon (or fixture) reading all pixels and building it correctly with it's proper algorithms.
My previous code was a simplefied version of how i would build the respective code.

I will post any other issues I may find.

Thanks a lot for your help.

Oct 27, 2011 at 6:33 PM
Edited Oct 27, 2011 at 6:38 PM

Hi xdijam,

To answer your question, here's how you obtain a piece of a texture ("subtexture"), for the tile at the position [i,j], and store in the variable "data[]" (assuming tiles are 32*32 px in size, and that your tilesheet has 16 tiles per row).

Texture2D tileSheetTex = content.Load<Texture2D>(tileSheet.ImageSource);
//Create an array to hold the data from the texture
uint[] data = new uint[32 * 32];

int idx = worldLayer.Tiles[i, j].TileIndex;
tileSheetTex.GetData(0, new Microsoft.Xna.Framework.Rectangle(32 * (idx % 16), 32 * (idx / 16), 32, 32), data, 0, 32 * 32);

Then, to use this data[] in Farseer you would do something like this:

 

//Find the vertices that makes up the outline of the shape in the texture
Vertices verts = FarseerPhysics.Common.PolygonTools.CreatePolygon(data, 32, false);
//Since it may be a concave polygon, we need to partition it into several smaller convex polygons
List<Vertices> _list = BayazitDecomposer.ConvexPartition(verts);

// Create the fixture
Body tileBody = BodyFactory.CreateCompoundPolygon(_world, _list, 1f, tilePosition);

tileBody.IsStatic = true;
tileBody.Restitution = 0.3f;
tileBody.Friction = 0.8f;

 

There you go. This is how I made my collisions work intitially, but now I don't actually recommend this method very much, since sometimes it generates too many polygons for a simple tile shape. Currently, my code instead works with a switch-case loop for the tile index, generating the proper shape manually (A triangle for the slopes and a rectangle for the rest of the tile types).

Feb 14, 2012 at 1:24 PM

Hey pablocm, thanks for you snippet.

How did you managed to calculate the tilePosition from xTide map position? I can't seem to translate the xTide x,y position to farseer world, to position the body  correctly. Any ideas?

Thank you very much.