root/src/BRAINSFramework/World.cs

User picture

Author: conkerjo

Revision: 30 («Previous)


File Size: 32.3 KB

(November 01, 2009 14:48 UTC) Over 2 years ago

Added Zune HD support and simple sample

 

Showing without highlighting since it looks like a big file and may slow your browser - show with highlighting

Show/hide line numbers

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Globalization;
using Brains.Framework.QuadTree;
using Brains.Framework.Map;
using Brains.Framework.Utility;
using Brains.Framework.Behaviors.PathFinding;
using Brains.Framework.Grouping;
using Brains.Spatial;

namespace Brains.Framework
{
    /// <summary>
    /// Class represents a game World for the AI Engine.
    /// Contains Grids and Actors
    /// </summary>
    public class World
    {
        //
        //privates
        //
        private List<Agent> _agentsToRemove = new List<Agent>();
        private Texture2D _mapTexture;
        private WorldMap _map;
        internal SpatialTable _spatialtable;
        //
        //Public properties
        //
        /// <summary>
        /// Parent Engine
        /// </summary>
        public AIEngine Engine { get; set; }
        
        /// <summary>
        /// Gets or sets the list of Actors in the world
        /// </summary>
        public List<Agent> Actors = new List<Agent>();

        public Dictionary<int,Group> Groups { get; set; }

        /// <summary>
        /// Gets the world map
        /// </summary>
        public WorldMap Map { get { return _map; } }

        public World()
        {
            Groups = new Dictionary<int, Group>();
            
        }
        //
        //Public Methods
        //
        /// <summary>
        /// This method calls Update on all Actors. This can be overriden.
        /// </summary>
        /// <param name="gameTime">The GameTime elapsed since the last update</param>
        public virtual void Update(GameTime gameTime)
        {
            foreach (var item in Actors)
            {
                item.UpdatePerception(gameTime);
            }
            foreach (var item in Actors)
            {
                item.Update(gameTime);
            }
            if (_agentsToRemove.Count > 0)
            {
                for (int i = 0; i < _agentsToRemove.Count; i++)
                {
                    Actors.Remove(_agentsToRemove[i]);
                }
                _agentsToRemove.Clear();
            }
        }

        /// <summary>
        /// Initializes a new world map with the provides parameters
        /// </summary>
        /// <param name="width">The width of the map in pixels</param>
        /// <param name="height">The height of the map in pixels</param>
        /// <param name="cellsize">The size of a cells width or height</param>
        public void SetupMap(int width, int height, int cellsize)
        {
            SetupMap(width, height, cellsize, width / cellsize, height / cellsize,typeof(Grid));
        }
        protected static sbyte[,] direction = new sbyte[4, 2]
            { 
                { 0,-1} , 
                { 1, 0}, 
                { 0, 1}, 
                {-1, 0}
            };

        /// <summary>
        /// This method will create a game Map of the defined size and automatically cluster the map into grids
        /// </summary>
        /// <param name="width">The full width in pixels of the map</param>
        /// <param name="height">The full height in pixels of the map</param>
        /// <param name="cellsize">The width or height of a gridcell</param>
        /// <param name="maxclusterwidth">Maximum number of columns in any grid of the cluster</param>
        /// <param name="maxclusterheight"></param>
        internal void SetupMap(int width, int height, int cellsize, int maxclusterwidth,int maxclusterheight,Type gridType)
        {
            _map = new WorldMap(width,height);
            int totalCols = width / cellsize;
            int totalRows= height / cellsize;
            int clusterRows = totalCols / maxclusterwidth;
            int clusterCols = totalRows/ maxclusterheight;
            _map.ClusterGrid.Setup(clusterRows, clusterCols);
            _spatialtable = new SpatialTable();
            _spatialtable.Setup(width, height, cellsize);

            Vector2 position = new Vector2();
            for (int y = 0; y < clusterRows; y++)
            {
                for (int x = 0; x < clusterCols; x++)
                {

                    Grid grid = (Grid)gridType.Assembly.CreateInstance(gridType.FullName);
                    grid.Setup(position, maxclusterwidth * cellsize, maxclusterheight * cellsize, cellsize);
                    //Grid grid = (Grid)gridType.Assembly.CreateInstance(
                    //    gridType.FullName,
                    //    true,
                    //    System.Reflection.BindingFlags.CreateInstance,
                    //    null,
                    //    new object[] { 
                    //        position,
                    //        maxclusterwidth * cellsize, 
                    //        maxclusterheight* cellsize,  
                    //        cellsize },
                    //    CultureInfo.CurrentCulture,
                    //    null);

                    grid.Initialize();
                    position.X += maxclusterwidth * cellsize;
                    Map.AddGrid(grid);
                }
                position.Y += maxclusterheight * cellsize;
                position.X = 0;
            }
            
        }
       
        public void AnotateMap()
        {
            List<QuadTreePositionItem<GridCell>> list = new List<QuadTreePositionItem<GridCell>>();
            Map.GridCellTree.GetAllItems(ref list);
            //Grid grid = Map.Cluster[index];
            //Annotate clearance.
            int rows = Map.ClusterGrid.Rows;
            int cols= Map.ClusterGrid.Cols;
            Cluster cluster = Map.ClusterGrid;
            for (int xx = cluster.TotalCols - 1; xx >= 0; xx--)
            {
                for (int yy = cluster.TotalRows - 1; yy >= 0; yy--)
                {
                    //int x = xx / Map.Cluster[0].Cols;
                    //int y = yy/ Map.Cluster[0].Rows;
                    //int index = y * Map.Cols + x;
                    //Grid grid = Map.Cluster[index];

                    int index = yy * cluster.TotalCols + xx;
                    GridCell cell = Map.AllCells[index];// grid.GetCell(xx - (x * grid.Cols), yy - (y * grid.Rows));
                    if (cell.Type == 0) //If the cell is not traversable, bail out.
                        continue;
                    
                    //Get adjacent tiles
                    GridCell c1, c2, c3;
                    int y = (index - (index % cluster.TotalCols)) / cluster.TotalCols;
                    int x = index % cluster.TotalCols;
                    int newindex = (y + 1) * cluster.TotalCols + (x + 1);
                    c1 = null;
                    c2 = null;
                    c3 = null;
                    if(Map.AllCells.Count > newindex)
                        c1 = Map.AllCells[newindex];// grid.GetCell(cell.X + 1, cell.Y + 1);

                    newindex = (y) * cluster.TotalCols + (x + 1);
                    if (Map.AllCells.Count > newindex)
                        c2 = Map.AllCells[newindex]; //grid.GetCell(cell.X + 1, cell.Y);
                    newindex = (y + 1) * cluster.TotalCols + (x);
                    if (Map.AllCells.Count > newindex)
                        c3 = Map.AllCells[newindex]; //grid.GetCell(cell.X, cell.Y + 1);
                    
                    //If all tiles are valid
                    if (c1 != null && c2 != null && c3 != null)
                    {

                        int min = c1.Labels[AIConsts.CLEARANCEVALUE];
                        min = c2.Labels[AIConsts.CLEARANCEVALUE] < min ? c2.Labels[AIConsts.CLEARANCEVALUE] : min;
                        min = c3.Labels[AIConsts.CLEARANCEVALUE] < min ? c3.Labels[AIConsts.CLEARANCEVALUE] : min;
                        cell.Labels[AIConsts.CLEARANCEVALUE] = min + 1; // NB: +1 for minimum tile clearance

                    }
                    else
                    {
                        for (int i = 1; i < 3; i++)
                        {
                            int v = i & cell.Type;
                            if (v == cell.Type)
                                cell.Labels[AIConsts.CLEARANCEVALUE] = 1;
                            else
                                cell.Labels[AIConsts.CLEARANCEVALUE] = 0;
                        }
                        //Otherwise it must be up against a non traversable tile.

                    }



                }
            }
                        
            if (cluster.Grids.Count > 1)
            {
                int index = 0;
                for (int y = 0; y < rows; y++)
                {
                    for (int x = 0; x < cols; x++)
                    {
                        SetHorizontalEntrancesOnGrid(x, y);
                        SetVerticalEntrancesOnGrid(x, y);
                        ////Check right edge
                        //if (cluster.Grids.Count > index + 1)
                        //{
                        //    for (int row = 0; row < cluster.Grids[index].Rows; row++)
                        //    {
                        //        GridCell leftcell = cluster.Grids[index].GetCell(
                        //                        cluster.Grids[index].Cols - 1,
                        //                        row);
                        //        GridCell rightcell = cluster.Grids[index + 1].GetCell(
                        //                        0,
                        //                        row);

                        //        if (leftcell.Type != AIConsts.BLOCKED_TILE &&
                        //            rightcell.Type != AIConsts.BLOCKED_TILE)
                        //        {
                        //            //leftcell.Labels[AIConsts.ISVALIDCLUSTEREDGE] = 1;
                        //            //rightcell.Labels[AIConsts.ISVALIDCLUSTEREDGE] = 1;
                        //        }
                        //    }
                        //}

                        ////check left edge

                        //if (index > 1)
                        //{
                        //    for (int row = 0; row < cluster.Grids[index].Rows; row++)
                        //    {
                        //        GridCell leftcell = cluster.Grids[index - 1].GetCell(
                        //                            cluster.Grids[index - 1].Cols - 1,
                        //                            row);
                        //        GridCell rightcell = cluster.Grids[index].GetCell(
                        //                        0,
                        //                        row);

                        //        if (leftcell.Type != AIConsts.BLOCKED_TILE &&
                        //            rightcell.Type != AIConsts.BLOCKED_TILE)
                        //        {
                        //            //leftcell.Labels[AIConsts.ISVALIDCLUSTEREDGE] = 1;
                        //            //rightcell.Labels[AIConsts.ISVALIDCLUSTEREDGE] = 1;
                        //        }
                        //    }
                        //}

                        ////check bottom edge

                        //if (index + cols < cluster.Grids.Count)
                        //{
                        //    for (int col = 0; col < cluster.Grids[index].Cols; col++)
                        //    {
                        //        GridCell topcell = cluster.Grids[index].GetCell(
                        //                        col,
                        //                        cluster.Grids[index].Rows - 1);
                        //        GridCell bottomcell = cluster.Grids[index + cols].GetCell(
                        //                        col,
                        //                        0);

                        //        if (topcell.Type != AIConsts.BLOCKED_TILE &&
                        //            bottomcell.Type != AIConsts.BLOCKED_TILE)
                        //        {
                        //          //  bottomcell.Labels[AIConsts.ISVALIDCLUSTEREDGE] = 1;
                        //          //  topcell.Labels[AIConsts.ISVALIDCLUSTEREDGE] = 1;
                        //        }
                        //    }
                        //}
                        ////Check Top
                        //if (index - cols > 0)
                        //{
                        //    for (int col = 0; col < cluster.Grids[index].Cols; col++)
                        //    {
                        //        GridCell topcell = cluster.Grids[index - cols].GetCell(
                        //                        col,
                        //                        cluster.Grids[index - cols].Rows - 1);
                        //        GridCell bottomcell = cluster.Grids[index].GetCell(
                        //                        col,
                        //                        0);

                        //        if (topcell.Type != AIConsts.BLOCKED_TILE &&
                        //            bottomcell.Type != AIConsts.BLOCKED_TILE)
                        //        {
                        //            //bottomcell.Labels[AIConsts.ISVALIDCLUSTEREDGE] = 1;
                        //            //topcell.Labels[AIConsts.ISVALIDCLUSTEREDGE] = 1;
                        //        }
                        //    }
                        //}
                        index++;
                    }
                }
            }


            //Precalculate paths for each grid transition
            int gridIndex = 0;
            foreach (var item in Map.ClusterGrid.Grids)
            {
                
                int y = (gridIndex - (gridIndex % Map.ClusterGrid.Cols)) / Map.ClusterGrid.Cols;
                int x = gridIndex % Map.ClusterGrid.Cols;
                //North To East
                if (y > 0 && x < Map.ClusterGrid.Cols - 1)
                {
                    PredeterminePaths(item,x, y - 1, x + 1, y);
                }
                //East To South
                if (x < Map.ClusterGrid.Cols - 1 && y<Map.ClusterGrid.Rows-1)
                {
                    PredeterminePaths(item, x + 1, y, x, y + 1);
                }
                //South To West
                if (y < Map.ClusterGrid.Rows - 1 && x > 0)
                {
                    PredeterminePaths(item, x, y + 1, x - 1, y);
                }
                //West To Nort
                if (x>0 && y>0)
                {
                    PredeterminePaths(item, x - 1, y, x, y - 1);
                }

                //West To East
                if (x > 0 && x < Map.ClusterGrid.Cols-1)
                {
                    PredeterminePaths(item, x - 1, y, x + 1, y);
                }

                //North To South
                if (y > 0 && y < Map.ClusterGrid.Rows- 1)
                {
                    PredeterminePaths(item, x, y - 1, x, y + 1);
                }
                gridIndex++;
            }


            //Cluster cl = Map.ClusterGrid;
            //int index1 = 0;


            //foreach (var item in Map.ClusterGrid.Grids)
            //{
            //    int y = (index1 - (index1 % cl.Cols)) / cl.Cols;
            //    int x = index1 % cl.Cols;

            //    //Top To Right
            //    if (y > 0 && x < cl.Cols - 1)
            //    {
            //        int indexF = (y-1) * cl.Cols + x ;
            //        int indexT = y * cl.Cols + (x+1);
            //        GridCell from;
            //        GridCell to;

            //        from = GetFreeCellAt(item, Direction.up);
            //        to = GetFreeCellAt(item, Direction.rigth);
            //        if(from!=null&& to!=null)
            //            CalculatePath(from, to,indexF,indexT);
            //    }
            //    //Right To Bottom
            //    if (y < cl.Rows - 1 && x < cl.Cols - 1)
            //    {
            //        int indexF = y * cl.Cols + (x + 1);
            //        int indexT = (y + 1) * cl.Cols + x;
            //        GridCell from;
            //        GridCell to;

            //        from = GetFreeCellAt(item, Direction.rigth);
            //        to = GetFreeCellAt(item, Direction.down);
            //        if (from != null && to != null)
            //            CalculatePath(from, to, indexF, indexT);
            //    }
            //    //Bottom To Left
            //    if (y < cl.Rows - 1 && x > 0)
            //    {
            //        int indexF = (y + 1) * cl.Cols + x;
            //        int indexT = y * cl.Cols + (x - 1);
            //        GridCell from;
            //        GridCell to;

            //        from = GetFreeCellAt(item, Direction.down);
            //        to = GetFreeCellAt(item, Direction.left);
            //        if (from != null && to != null)
            //            CalculatePath(from, to, indexF, indexT);
            //    }
            //    //Left To Top
            //    if (y > 0 && x > 0)
            //    {
            //        int indexF = y * cl.Cols + (x-1);
            //        int indexT = (y-1) * cl.Cols + x;
            //        GridCell from;
            //        GridCell to;

            //        from = GetFreeCellAt(item, Direction.left);
            //        to = GetFreeCellAt(item, Direction.up);
            //        if (from != null && to != null)
            //            CalculatePath(from, to, indexF, indexT);
            //    }
            //    //Top to bottom
            //    if (y > 0 && y < cl.Rows - 1)
            //    {
            //        int indexF = (y - 1) * cl.Cols + x;
            //        int indexT = (y + 1) * cl.Cols + x;
            //        GridCell from;
            //        GridCell to;

            //        from = GetFreeCellAt(item, Direction.up);
            //        to = GetFreeCellAt(item, Direction.down);
            //        if (from != null && to != null)
            //            CalculatePath(from, to, indexF, indexT);
            //    }
            //    //Left To Right
            //    if (x > 0 && x < cl.Cols - 1)
            //    {
            //        int indexF = y * cl.Cols + (x - 1);
            //        int indexT = y * cl.Cols + (x + 1);
            //        GridCell from;
            //        GridCell to;

            //        from = GetFreeCellAt(item, Direction.left);
            //        to = GetFreeCellAt(item, Direction.rigth);
            //        if (from != null && to != null)
            //            CalculatePath(from, to,indexF,indexT);
            //    }

            //    index1++;
            //}
        }

        private void PredeterminePaths(Grid grid,int x1,int y1,int x2,int y2)
        {

            int indexF = Map.ClusterGrid.GetGridIndex(x1, y1);
            int indexT = Map.ClusterGrid.GetGridIndex(x2, y2);

            Grid gridA = Map.ClusterGrid.GetGrid(x1, y1);
            GridCell cellA= GetValidCellFromEntrance(gridA,grid);

            Grid gridB= Map.ClusterGrid.GetGrid(x2, y2);
            GridCell cellB = GetValidCellFromEntrance(gridB, grid);

            if (cellB != null && cellA != null)
            {
                CalculatePath(
                    grid.GetCell(cellA.X,cellA.Y),
                    grid.GetCell(cellB.X, cellB.Y), 
                    indexF, 
                    indexT);
            }
        }

        private GridCell GetValidCellFromEntrance(Grid fromGrid,Grid toGrid)
        {
            foreach (var entrance in Map.ClusterGrid.Entrances)
            {
                if (entrance.CellA.Parent == fromGrid && entrance.CellB.Parent==toGrid)
                    return entrance.CellB;
                if (entrance.CellB.Parent == fromGrid && entrance.CellA.Parent == toGrid)
                    return entrance.CellA;
            }
            return null;
        }

        private void SetVerticalEntrancesOnGrid(int x, int y)
        {
            bool checkEast = false;
            bool checkWest = false;

            Grid thisGrid = Map.ClusterGrid.GetGrid(x, y);

            if (x > 0)
                checkWest= true;

            if (x < Map.ClusterGrid.Cols- 1)
                checkEast = true;

            if (checkEast)
            {
                Grid eastGrid = Map.ClusterGrid.GetGrid(x+1, y);
                SetVertEntranceBetweenGrids(thisGrid, eastGrid);
            }
            if (checkWest)
            {
                Grid westGrid= Map.ClusterGrid.GetGrid(x-1, y);
                SetVertEntranceBetweenGrids(thisGrid, westGrid);
            }
        }

        private void SetVertEntranceBetweenGrids(Grid gridA, Grid gridB)
        {
            int yIndexa = 0;
            int yIndexb = gridA.Cols- 1;
            if (gridB.Position.X > gridA.Position.X)
            {
                yIndexa = yIndexb;
                yIndexb = 0;
            }
            //Start near the middle
            int startRow = gridA.Rows/ 2;
            //Currently supports 1 transition per set of grids
            bool continueChecking = true;
            //Loop to end ignoring the corner cell
            for (int i = startRow; i < gridA.Rows - 1; i++)
            {

                GridCell _edgeCell = gridA.GetCell(yIndexa,i);
                GridCell _adjacentCell = gridB.GetCell(yIndexb,i);
                if (_edgeCell.Labels[AIConsts.BLOCKED_TILE] == 0 &&
                    _adjacentCell.Labels[AIConsts.BLOCKED_TILE] == 0)
                {
                    Map.ClusterGrid.AddEntrance(_edgeCell, _adjacentCell);
                    continueChecking = false;
                    break;
                }
            }
            if (continueChecking)
            {
                //Loop to beginning column ignoring the corner cell
                for (int i = startRow; i > 0; i--)
                {
                    GridCell _edgeCell = gridA.GetCell(yIndexa, i);
                    GridCell _adjacentCell = gridB.GetCell(yIndexb, i);
                    if (_edgeCell.Labels[AIConsts.BLOCKED_TILE] == 0 && _adjacentCell.Labels[AIConsts.BLOCKED_TILE] == 0)
                    {
                        Map.ClusterGrid.AddEntrance(_edgeCell, _adjacentCell);
                        continueChecking = false;
                        break;
                    }
                }
            }

        }
        
        private void SetHorizontalEntrancesOnGrid(int x, int y)
        {
            bool checkNorth = false;
            bool checkSouth = false;

            Grid thisGrid = Map.ClusterGrid.GetGrid(x,y);
            
            if (y > 0)
                checkNorth = true;
            
            if (y < Map.ClusterGrid.Rows-1)
                checkSouth= true;

            if (checkNorth)
            {
                Grid northGrid = Map.ClusterGrid.GetGrid(x, y - 1);
                SetHorizEntranceBetweenGrids(thisGrid, northGrid);
            }
            if (checkSouth)
            {
                Grid southGrid = Map.ClusterGrid.GetGrid(x, y + 1);
                SetHorizEntranceBetweenGrids(thisGrid, southGrid);
            }
            

        }

        private void SetHorizEntranceBetweenGrids(Grid gridA, Grid gridB)
        {
            int yIndexa = 0;
            int yIndexb = gridA.Rows - 1;
            if (gridB.Position.Y > gridA.Position.Y)
            {
                yIndexa = yIndexb;
                yIndexb = 0;
            }
            //Start near the middle
            int startCol = gridA.Cols / 2;
            //Currently supports 1 transition per set of grids
            bool continueChecking = true;
            //Loop to end ignoring the corner cell
            for (int i = startCol; i < gridA.Cols - 1; i++)
            {
                
                GridCell _edgeCell = gridA.GetCell(i, yIndexa);
                GridCell _adjacentCell = gridB.GetCell(i, yIndexb);
                if (_edgeCell.Labels[AIConsts.BLOCKED_TILE] == 0 && 
                    _adjacentCell.Labels[AIConsts.BLOCKED_TILE] == 0)
                {
                    Map.ClusterGrid.AddEntrance(_edgeCell, _adjacentCell);
                    continueChecking = false;
                    break;
                }
            }
            if (continueChecking)
            {
                //Loop to beginning column ignoring the corner cell
                for (int i = startCol; i > 0; i--)
                {
                    GridCell _edgeCell = gridA.GetCell(i, yIndexa);
                    GridCell _adjacentCell = gridB.GetCell(i, yIndexb);
                    if (_edgeCell.Labels[AIConsts.BLOCKED_TILE] == 0 && _adjacentCell.Labels[AIConsts.BLOCKED_TILE] == 0)
                    {
                        Map.ClusterGrid.AddEntrance(_edgeCell, _adjacentCell);
                        continueChecking = false;
                        break;
                    }
                }
            }


        }

        private void CalculatePath(GridCell from, GridCell to,int gridfrom,int gridto)
        {
            PathFinding.PathFinder _f = new Brains.Framework.PathFinding.PathFinder();
            _f.Grid = from.Parent;
            _f.StartNode = from;
            _f.EndNode = to;
            _f.Reset();

            while (_f.State == Brains.Framework.PathFinding.PathFinderState.Working)
            {
                _f.Iterate();
            }
            if (_f.State == Brains.Framework.PathFinding.PathFinderState.Finished)
            {
                // copying nodes
                PreStoredPath _path = new PreStoredPath();
                _path.Nodes = new List<StoredPathNode>();
                
                int counter = 0;
                //for (int index = pathFinder.closeList.Count - 1; index >= 0; index--)
                for (int index = 0; index <= _f.closeList.Count - 1; index++)
                {
                    StoredPathNode newNode = new StoredPathNode();
                    Grid grid = from.Parent;
                    GridCell _node = grid.GetCell(_f.closeList[index].X,
                                            _f.closeList[index].Y);
                    newNode.nodePosition.X = grid.GetCell(_f.closeList[index].X,
                                            _f.closeList[index].Y).Position.X;
                    newNode.nodePosition.Y = grid.GetCell(_f.closeList[index].X,
                                            _f.closeList[index].Y).Position.Y;
                    newNode.X = _f.closeList[index].X;
                    newNode.Y = _f.closeList[index].Y;


                    _path.FromGrid =gridfrom;
                    _path.ToGrid = gridto;
                    //pathNodes[counter] = newNode;
                    _path.Nodes.Add(newNode);
                    counter++;
                }


                from.Parent.PredeterminedPaths.Add(_path);
            }
            if (_f.State == Brains.Framework.PathFinding.PathFinderState.Failed)
            {
                Console.WriteLine("");
            }

        }
        
        /// <summary>
        /// Adds the specified Actor to the Actors collection
        /// </summary>
        /// <param name="actor">The Actor to add</param>
        public void AddActor(Agent actor)
        {
            actor.ParentWorld = this;
            Actors.Add(actor);
            _spatialtable.RegisterObject(actor);
        }
        /// <summary>
        /// Loads Map data from a texture
        /// </summary>
        /// <param name="texture">The texture to use</param>
        /// <param name="cellSize">The size of a cells width or height</param>
        /// <param name="grid">The type of grid to create</param>
        public void LoadMapDataFromTexture(Texture2D texture, int cellSize,Type grid)
        {
            LoadMapDataFromTexture(texture, 1, 1, cellSize, grid);
        }
        /// <summary>
        /// Loads Map data from a texture
        /// </summary>
        /// <param name="texture">The texture to use</param>
        /// <param name="cellSize">The size of a cells width or height</param>
        public void LoadMapDataFromTexture(Texture2D texture, int cellSize)
        {
            LoadMapDataFromTexture(texture, 1, 1, cellSize, typeof(Grid));
        }
        /// <summary>
        /// Loads Map data from a texture
        /// </summary>
        /// <param name="texture">The texture to use</param>
        /// <param name="cellSize">The size of a cells width or height</param>
        /// <param name="cols">The number of cols to split the map into</param>
        /// <param name="rows">The number of rows to split the map into</param>
        /// <param name="gridType">The type of grid to create</param>
        public void LoadMapDataFromTexture(Texture2D texture, int clusterColumnSplit, int clusterRowSplit, int cellSize, Type gridType)
        {
            _mapTexture = texture;

            Vector2 position = new Vector2();
            int clusterCols = texture.Width / clusterColumnSplit;
            int clusterRows = texture.Height / clusterRowSplit;

            SetupMap(
                texture.Width * cellSize,
                texture.Height * cellSize,
                cellSize,
                clusterCols,
                clusterRows,
                gridType);

            int index = 0;
            for (int y = 0; y < clusterRowSplit; y++)
            {
                for (int x = 0; x < clusterColumnSplit; x++)
                {
                    Grid item = Map.ClusterGrid.Grids[index];
                    index++;

                    int count = item.Rows * item.Cols;
                    Color[] colorData = new Color[count];
                    texture.GetData<Color>(
                        0,
                        new Rectangle(x * clusterCols, y * clusterRows, clusterCols, clusterRows),
                        colorData,
                        0,
                        count);
                    item.ColorData = colorData;
                    int _index = 0;
                    for (int yy = 0; yy < item.Rows; yy++)
                    {
                        for (int xx = 0; xx < item.Cols; xx++)
                        {
                           
                            GridCell cell = item.GetCell(xx, yy);
                            cell.Labels[AIConsts.COLORR] = colorData[_index].R;
                            cell.Labels[AIConsts.COLORG] = colorData[_index].G;
                            cell.Labels[AIConsts.COLORB] = colorData[_index].B;
                            cell.Labels[AIConsts.COLORA] = colorData[_index].A;

                            if (colorData[_index] == Color.Black)
                            {
                                cell.Type = 0;
                            }
                            //HACK FOR WATER
                            if (colorData[_index] == new Color(0,17,255))
                            {
                                cell.Type = 2;
                            }
                            _index++;
                        }
                    }
                }
            }

            AnotateMap();
        }

        /// <summary>
        /// Adds an Actor to the Actors collection at the specified position and size
        /// </summary>
        /// <param name="position">The position to start the Actor at</param>
        /// <param name="radius">The radius of the Actor</param>
        /// <returns></returns>
        public Agent AddActor(Vector2 position, float radius)
        {
            Agent _actor = new Agent(position, radius);
            AddActor(_actor);
            return _actor;
        }
        
        /// <summary>
        /// Removes an Agent from the world
        /// </summary>
        /// <param name="agent"></param>
        public void RemoveAgent(Agent agent)
        {
            _agentsToRemove.Add(agent);
        }

        public void AddGroup(Group group)
        {
            Groups.Add(group.GroupID, group);
        }

        public Group GetGroup(int id)
        {
            return Groups[id];
        }
    }
}