Game Development Community

Simple Tile Collisions question

by Henry Shilling · in Torque X 2D · 09/10/2009 (9:11 pm) · 5 replies

I am building a tile layer in code. I have all my tiles etc it all works great. However how do I set the collisions material on a tile? There is a T2DTileObject.CollisionsEnabled but I do not see where to set the coords of a collision rectangle.

There is also something called CollisionPolyBasis, a Vector2.

#1
09/10/2009 (9:36 pm)
Typically, you set the tile's collision polygon in the 2D Level Builder. I can't recally the process in code, but... You can try setting the collision polygon in the 2D Tilemap editor and then look at the .txcene file to find out which properties/values are set and then accomplish the same thing in code - since the XML values map directly to class and property names.

John K.
www.envygames.com
#2
09/10/2009 (9:44 pm)
That's funny I did just that then saw your response. Basically the CollisonPolyBasis is an array of Vector2's that describe the collison rectangle, just as you would set it in the editor. so I basically added this is my code:

_rock.Material = TorqueObjectDatabase.Instance.FindObject<GarageGames.Torque.Materials.RenderMaterial>("cave_blankMaterial");
            _rock.CollisionsEnabled = true;
            _rock.CollisionPolyBasis = new Vector2[4];
            _rock.CollisionPolyBasis[0] = new Vector2(-1, -1);
            _rock.CollisionPolyBasis[1] = new Vector2(1, -1);
            _rock.CollisionPolyBasis[2] = new Vector2(1,1);
            _rock.CollisionPolyBasis[3] = new Vector2(-1, 1);

#3
09/11/2009 (1:54 am)
Excellent! This should do the trick. Most of my early Torque X learning was based on dissecting the level files, before moving on to dissecting the engine code.

John K.
www.envygames.com
#4
09/11/2009 (6:55 am)
This is kinda weird to me but here is what I found out. Each tile in order to have collision is it's own autonomous tile object.
if you try this:

class TileTest
    {
        public TileTest()
        {
            T2DTileLayer _tileMap = new T2DTileLayer();
            _tileMap.Position = new Vector2(0, 0);
            _tileMap.Name = "MyTilemap";
            _tileMap.MapSize = new Vector2(5, 1);
            _tileMap.Size = new Vector2(100, 20);
            _tileMap.TileSize = new Vector2(20, 20);
            _tileMap.Layer = 10;
            _tileMap.CollisionsEnabled = true;

            T2DTileType _logo = new T2DTileType();
            _logo.Material = TorqueObjectDatabase.Instance.FindObject<GarageGames.Torque.Materials.RenderMaterial>("GGLogoMaterial");

            _logo.CollisionPolyBasis = new Vector2[4];
            _logo.CollisionPolyBasis[0] = new Vector2(-1f, -1f);
            _logo.CollisionPolyBasis[1] = new Vector2(1f, -1f);
            _logo.CollisionPolyBasis[2] = new Vector2(1f, 1f);
            _logo.CollisionPolyBasis[3] = new Vector2(-1f, 1f);
            _logo.Name = "LogoTile";
            _logo.CollisionsEnabled = true;

            T2DTileObject _tile = new T2DTileObject;
            _tile = new T2DTileObject();
            _tile.TileType = _logo;


            for (int i = 0; i < 5; i++)
            {
                _tileMap.SetTileByGridCoords(i, 0, _tile);
            }
            _tileMap.RenderCollisionBounds = true;
            TorqueObjectDatabase.Instance.Register(_tileMap);
        }
    }


Each tile is actually pointing to 1 tile. Only the last tile is the real tile with collision, the others are like just inkstamps. I found this by tracing and noticing that the X,Y values were changing to the last X,Y set by SetTileByGridCoords. By making each tile a new til you can get around this.

class TileTest
    {
        public TileTest()
        {
            T2DTileLayer _tileMap = new T2DTileLayer();
            _tileMap.Position = new Vector2(0, 0);
            _tileMap.Name = "MyTilemap";
            _tileMap.MapSize = new Vector2(5, 1);
            _tileMap.Size = new Vector2(100, 20);
            _tileMap.TileSize = new Vector2(20, 20);
            _tileMap.Layer = 10;
            _tileMap.CollisionsEnabled = true;

            T2DTileType _logo = new T2DTileType();
            _logo.Material = TorqueObjectDatabase.Instance.FindObject<GarageGames.Torque.Materials.RenderMaterial>("GGLogoMaterial");

            _logo.CollisionPolyBasis = new Vector2[4];
            _logo.CollisionPolyBasis[0] = new Vector2(-1f, -1f);
            _logo.CollisionPolyBasis[1] = new Vector2(1f, -1f);
            _logo.CollisionPolyBasis[2] = new Vector2(1f, 1f);
            _logo.CollisionPolyBasis[3] = new Vector2(-1f, 1f);
            _logo.Name = "LogoTile";
            _logo.CollisionsEnabled = true;
            _logo.Name = "theName";

            T2DTileObject[] _tile = new T2DTileObject[5];
            for (int i = 0; i < 5; i++)
            {
                _tile[i] = new T2DTileObject();
                _tile[i].TileType = _logo;
            }

            for (int i = 0; i < 5; i++)
            {
                _tileMap.SetTileByGridCoords(i, 0, _tile[i]);
            }
            _tileMap.RenderCollisionBounds = true;
            TorqueObjectDatabase.Instance.Register(_tileMap);
        }
    }

freaking weird to me. Its passing the actual tile we create. When we return from SetTileByGridCoords our tile _tile, has been changed to reflect what SetTileByGridCoords has done with it. I thought that when we passed an object to a function it created a new copy of that object. I guess that's a C# thing.

Overall it ended up not being so simple...
#5
09/11/2009 (12:37 pm)
It kind of makes sense, since a tilemap is all about efficiently re-using the same tiles (as opposed to simply organizing sprites into a grid). So each different tile type should have its own collision definition. If each rendered tile should have a different collision shape and material, then they should each have a different tile type. In the example above, each tile is set to the same tile type.

John K.
www.envygames.com