Ejemplo n.º 1
0
        // join tiles that are side by side into larger rectangles to allow for smoother wall collisions
        // these tiles are not meant for foot collisions -> losing some of the collision types (only persisting platform vs. impassable)
        // where impassable will be a lump of all non-platform, non-hideable, non-passable tiles
        //
        // NOTE: this ONLY returns tiles that have merged up to larger tiles, anything that stayed as a single tile will still need to check collisions
        protected IList<ITile> joinTiles(IList<ITile> tiles)
        {
            IList<ITile> result = new List<ITile>();

            if (tiles.Count > 0)
            {
                int singleWidth = 0;
                int singleHeight = 0;

                // the tile layout size will be more like 5 x 4 - using 10 so there is a buffer
                ITile[,] tileLayout = new Tile[10, 10];

                // creating a dummy tile
                ITile dummyTile = new Tile(game);

                // initialize tileLayout to dummy values;
                for (int i = 0; i < 10; i++)
                {
                    for (int j = 0; j < 10; j++)
                    {
                        tileLayout[i, j] = dummyTile;
                    }
                }

                // the top-most y position of our tiles being sorted - -1 indicates no tiles yet
                int currY = -1;

                // start y index at -1 so the first y gets set properly
                int yIndex = -1;
                int xIndex = 0;

                // put the tiles into their appropriate row based on y value (smaller y is the top of the screen)
                foreach (ITile t in tiles)
                {
                    // set the width of a single tile
                    singleWidth = t.getPosition().Width;
                    singleHeight = t.getPosition().Height;

                    // new row, so insert the tile (deal with shifting the layout later)
                    if (currY < 0 || currY < t.getPosition().Top)
                    {
                        xIndex = 0;
                        yIndex += 1;

                        tileLayout[yIndex, xIndex] = t;
                        currY = t.getPosition().Top;
                    }
                    // otherwise that tile belongs to this row, so it is the next tile in the row
                    else
                    {
                        xIndex += 1;

                        tileLayout[yIndex, xIndex] = t;
                    }
                }

                // adjust the tile layout to fix things being always pushed to the left i.e...
                // (0,0) (x,x)  ----> (0,0)(x,x)(x,x)
                // (1,1) (1,2)  ----> (x,x)(1,1)(1,2)
                for (int j = 0; j < 10; j++)
                {
                    int xMin = -1;
                    // get the min x in the current column
                    for (int i = 0; i < 10; i++)
                    {
                        if (xMin == -1 || (tileLayout[i, j].getPosition().X != -1 && xMin > tileLayout[i, j].getPosition().X))
                        {
                            xMin = tileLayout[i, j].getPosition().X;
                        }
                    }

                    // we only care about shifts when there was a valid minimum
                    if (xMin != -1)
                    {
                        // perform any shifts to the layout
                        for (int i = 0; i < 10; i++)
                        {
                            // this row needs to shift to the right
                            if (xMin < tileLayout[i, j].getPosition().X)
                            {
                                for (int k = 9; k > j; k--)
                                {
                                    tileLayout[i, k] = tileLayout[i, k - 1];
                                }

                                // set the start column of the row that just shifted to the dummy tile
                                tileLayout[i, j] = dummyTile;
                            }
                        }
                    }
                }

                ITile combined = new Tile(game);

                // do not merge platforms with any other tile-type -> these rectangles are not for foot collisions
                // combine tiles into taller tiles when they are touching each other
                for (int j = 0; j < 10; j++)
                {
                    // for each row until the end of the rows is hit
                    for (int i = 0; i < 10; i++)
                    {
                        // if the current tile is a valid tile
                        if (tileLayout[i, j].getPosition().X != -1)
                        {
                            // start a new tile
                            if (i == 0 || combined.getPosition().Bottom != tileLayout[i, j].getPosition().Top
                                       || !compatibleTypes(tileLayout[i, j].getCollisionBehaviour(), combined.getCollisionBehaviour()))
                            {
                                // add the merged tile to the result list
                                if (combined.getPosition().X != -1 && combined.getPosition().Height > singleHeight)
                                {
                                    result.Add(combined);
                                }

                                // build the next tile
                                combined = new Tile(game);
                                combined.setPosition(tileLayout[i, j].getPosition());
                                combined.changeType(tileLayout[i, j].getCollisionBehaviour());
                            }
                            else
                            {
                                //extend the rectangle's height
                                Rectangle r = combined.getPosition();
                                r.Height += tileLayout[i, j].getPosition().Height;

                                combined.setPosition(r);
                            }

                        }
                    }
                }

                // add the last combined tile to the result if there were any
                if (combined.getPosition().X != -1 && combined.getPosition().Height > singleHeight)
                {
                    result.Add(combined);
                }

                // clear out the merged tile
                combined = new Tile(game);
                // combine columns into rectangles when they are beside each other
                for (int i = 0; i < 10; i++)
                {
                    // for each row until the end of the rows is hit
                    for (int j = 0; j < 10; j++)
                    {
                        // if the current tile is a valid tile
                        if (tileLayout[i, j].getPosition().X != -1)
                        {
                            // start a new tile
                            if (j == 0 || combined.getPosition().Right != tileLayout[i, j].getPosition().Left
                                       || !compatibleTypes(tileLayout[i, j].getCollisionBehaviour(), combined.getCollisionBehaviour()))
                            {
                                // add the merged tile to the result list
                                if (combined.getPosition().X != -1 && combined.getPosition().Width > singleWidth)
                                {
                                    result.Add(combined);
                                }

                                // build the next tile
                                combined = new Tile(game);
                                combined.setPosition(tileLayout[i, j].getPosition());
                                combined.changeType(tileLayout[i, j].getCollisionBehaviour());
                            }
                            else
                            {
                                //extend the rectangle's height
                                Rectangle r = combined.getPosition();
                                r.Width += tileLayout[i, j].getPosition().Width;

                                combined.setPosition(r);
                            }

                        }
                    }
                }

                // add the last merged tile to the result set
                if (combined.getPosition().X != -1 && combined.getPosition().Width > singleWidth)
                {
                    result.Add(combined);
                }

                /*
                System.Console.WriteLine("------------merged-----------");
                foreach (ITile t in result)
                {
                    System.Console.WriteLine("(" + t.getPosition().X + ", "
                                                 + t.getPosition().Y + ", "
                                                 + t.getPosition().Width + ", "
                                                 + t.getPosition().Height + ") -> "
                                                 + t.getCollisionBehaviour().ToString());
                }
                */

            }

            return result;
        }