public int Waypoint; // Current waypoint in the path #endregion Fields #region Constructors public Entity( int index ) { Index = index; Transform = new InstanceTransformRef(); Type = EntityType.Civilian; HalfSize = 1f; AABB = new AABB(); NextPosition = Vector3.Zero; NextAngle = 0f; ListNode = null; Direction = Vector3.Zero; StateTime = 0; StateDuration = 0; Behavior = null; Collision = 0; Path = new List<Vector2>( 60 ); Waypoint = -1; MoveSpeed = 1f; Beacon = null; BeaconVersion = 0; }
private bool DetermineIfPathCellIsWalkable( AABB aabb, Building[] buildings ) { for ( int i = 0; i < buildings.Length; ++i ) { if ( TestBuildingVsAABB( buildings[i], aabb ) ) return false; } return true; }
private bool TestBuildingVsAABB( Building building, AABB aabb ) { Vector2 min = Vector2.Clamp( building.AABB.Min, Min, Max ); Vector2 max = Vector2.Clamp( building.AABB.Max, Min, Max ); float cellWidth = ( Max.X - Min.X ) / Cols; int colMin = (int)( ( min.X - Min.X ) / cellWidth ); int colMax = (int)( ( max.X - Min.X ) / cellWidth ); float cellHeight = ( Max.Y - Min.Y ) / Rows; int rowMin = (int)( ( min.Y - Min.Y ) / cellHeight ); int rowMax = (int)( ( max.Y - Min.Y ) / cellHeight ); // make sure the maxs don't go out of bounds if ( colMax == Cols ) colMax = colMin; if ( rowMax == Rows ) rowMax = rowMin; // test polygon's aabb against aabb (effectively aabb version of SAT) if ( aabb.Max.X < min.X || aabb.Min.X > max.X ) return false; if ( aabb.Max.Y < min.Y || aabb.Min.Y > max.Y ) return false; tempAABBVerts[0] = aabb.Min; tempAABBVerts[1] = new Vector2( aabb.Min.X, aabb.Max.Y ); tempAABBVerts[2] = aabb.Max; tempAABBVerts[3] = new Vector2( aabb.Max.X, aabb.Min.Y ); // SAT using building's axes for ( int i = 0; i < building.Boundary.Length; ++i ) { float lower = float.MaxValue; float upper = float.MinValue; for ( int j = 0; j < tempAABBVerts.Length; ++j ) { Vector2 disp = building.Boundary[i] - tempAABBVerts[j]; float proj = Vector2.Dot( disp, building.Normals[i] ); if ( proj < lower ) lower = proj; if ( proj > upper ) upper = proj; } if ( upper < 0 || lower > building.SATProjections[i] ) return false; } return true; }
CellState[] states; // true if open, false if closed #endregion Fields #region Constructors public PathGrid( Vector2 min, Vector2 max, int rows, int cols, WalkablePredicate walkablePredicate ) { smoothStep = .25f * ( max.X - min.X ) / cols; Min = min; Max = max; Rows = rows; Cols = cols; openList = new List<int>( 100 ); int cellCount = Rows * Cols; cells = new PathCell[cellCount]; costs = new PathCellCost[cellCount]; states = new CellState[cellCount]; float xStep = ( Max.X - Min.X ) / Cols; float yStep = ( Max.Y - Min.Y ) / Rows; AABB aabb = new AABB(); aabb.Min.Y = Min.Y; aabb.Max.Y = Min.Y + yStep; for ( int r = 0; r < Rows; ++r ) { aabb.Min.X = Min.X; aabb.Max.X = Min.X + xStep; for ( int c = 0; c < Cols; ++c ) { int index = r * Cols + c; bool walkable = walkablePredicate != null ? walkablePredicate( aabb, Building.Buildings ) : true; cells[index] = new PathCell( walkable, index, Vector2.Lerp( aabb.Min, aabb.Max, .5f ) ); aabb.Min.X += xStep; aabb.Max.X += xStep; } aabb.Min.Y += yStep; aabb.Max.Y += yStep; } // do the a* stuffs here for ( int r = 0; r < Rows; ++r ) { for ( int c = 0; c < Cols; ++c ) { int index = r * Cols + c; if ( cells[index].Walkable ) { for ( int r2 = 0; r2 < Rows; ++r2 ) { for ( int c2 = 0; c2 < Cols; ++c2 ) { //FindPath( r, c, r2, c2 ); } } } } } debugGrid = new DebugGrid( Min, Max, Rows, Cols, Color.LightGray, ZombieCraft.Instance.GraphicsDevice ); }