Monday, September 27, 2010

How did I work out tile destruction.

Well here's an explanation - not a tutorial, of how it's done.

Basically as you know the Tile system is held in an array, in the level.cs file up the top it's called

public Tile[,] tiles;


Now the Tile[,] is the actual array of the graph Tile[x,y], X being the left and right, Y being up and down.

Now the grid is setup like so.

x0y0 x1y0 x2y0
x0y1 x1y1 x2y1
x0y2 x1y2 x2y2

See how it increments, now this is what you call a multi dimensional array, EACH of those coordinates hold a TILE value, so, the texture, what it is, the width/height.

All I did was add to the Player.cs file down where it handles player collisions under the


                    if (collision != TileCollision.Passable)
                    {
                        // Determine collision depth (with direction) and magnitude.
                        Rectangle tileBounds = Level.GetBounds(x, y);
                        Vector2 depth = RectangleExtensions.GetIntersectionDepth(bounds, tileBounds);
                        if (depth != Vector2.Zero)
                        {
                            float absDepthX = Math.Abs(depth.X);
                            float absDepthY = Math.Abs(depth.Y);                                


I added:



                                // RIGHT
                                if (collision == TileCollision.Impassable &&
                                keyboardState.IsKeyDown(Keys.Z) &&
                                keyboardState.IsKeyDown(Keys.Right) &&
                                    previousRight <= tileBounds.Right)
                                {
                                    Level.tiles[x, y].Collision = TileCollision.Passable;
                                    Level.tiles[x, y].Texture = null;
                                }



If all goes well this should allow you to 'destroy' walls.

What we did was:

If the collision is a non passable object, scroll down-
If the collision is impassible, we have his Z and RIGHT, and the previousRight tile is less than that tiles bounds (if we hit the left side)-
We want to make the collision of the tile we hit passable, do that like this-
Level.tiles[x,y].Collision = TileCollision.Passable;


Hold up, what about the texture?

Well if you want NO texture what you want to do is:
Level.tiles[x, y].Texture = null;


null = no value so we cleared the texture, and basically swapped the 'air' tile with it.

Down the very bottom you will want to add:


            // Save the new bounds bottom.
            previousBottom = bounds.Bottom;
            previousLeft = bounds.Left;
            previousRight = bounds.Right;


So it knows what we hit last.

There is an error with hitting the left direction!
I have no idea why it does this but I boosted the hitting UP 1 tile with this code:



                                    Level.tiles[x, y--].Collision = TileCollision.Passable;
                                    Level.tiles[x, y].Texture = null;


Notice the y--, i'm telling it the collision is there, And for some reason it clears the first tile and the top, that's why I was mining left and falling down; here's an example:

OOO
OOP
OOO

P = player tile, I go to hit the left direction, what should happen is:


OOO
OXP
OOO

X = the tile I hit, but instead it does this:

OOO
OXP
OXO

and then the player falls down but with that other bit of code it does this:

OXO
OXP
OOO

It will allow the user to not fall down but mine to tiles.

I have no idea so far why this does what it does, the right mining is the same but reversed on mining and it works flawlessly.

Ok It was kinda a tutorial, haha :).


EDIT:
I figured out the collision of the left direction while digging code is as follows:

                                // LEFT
                                if (collision == TileCollision.Impassable &&
                                keyboardState.IsKeyDown(Keys.Z) &&
                                keyboardState.IsKeyDown(Keys.Left) &&
                                    previousLeft <= tileBounds.Left)
                                {

                                    x--;
                                    y--;
                                    Level.tiles[x, y].Texture = null;
                                    Level.tiles[x, y].Collision = TileCollision.Passable;

                                }
It appears that this is slightly retarded, you have to minus and make the left side passable, If I had:


                                    Level.tiles[x--, y--].Texture = null;
                                    Level.tiles[x--, y--].Collision = TileCollision.Passable;


It removes one under it for some retarded reason, probably due to collision below interfering with the object or something, either way it works! Go me!


EDIT 2:
Apparently you have to add this code to the RIGHT one so it stops skitzing out, I manage to fix it by changeing the tile size but then I have problems digging down:


                                // RIGHT
                                if (collision == TileCollision.Impassable &&
                                keyboardState.IsKeyDown(Keys.Z) &&
                                keyboardState.IsKeyDown(Keys.Right) &&
                                    previousRight >= tileBounds.Right &&
                                    GlobalVaribles.HitCooldown == 0)
                                {
                                    x++;
                                    y--;
                                    Level.tiles[x, y].Texture = null;
                                    Level.tiles[x, y].Collision = TileCollision.Passable;
                                }


So there you have it, I guess you just full around with those values as it's too unsafe to mess around with the tile[x,y] values. Something to do with the global array I bet.


No comments:

Post a Comment