public void RemoveFromWorld() { _placedInWorld = false; int colWidth = mWidth * 2; int colLength = mLength * 2; for (int iX = 0; iX < colWidth; ++iX) { for (int iY = 0; iY < colLength; ++iY) { IntVec2 worldTile = GetWorldCollisionTile(iX, iY, mPosition, mItemRot); CCollisionTile tile = mWorld.mMap.mGlobalCollisionTiles[worldTile.X, worldTile.Y]; tile.mOccupied = 0; tile.mSolid = false; } } for (int iX = 0; iX < mWidth; ++iX) { for (int iY = 0; iY < mLength; ++iY) { Vector2 worldPoint = RotationAxisTable[mItemRot].Transform(new Vector2(iX, iY)); int worldX = (int)worldPoint.x + mX; int worldY = (int)worldPoint.y + mY; CTile worldTile = mWorld.mMap.mTiles[worldX, worldY]; worldTile.mItem = -1; } } mWorld.RebuildInfluenceMap(); }
public virtual void PlaceInWorld() { mBluerprint = false; _placedInWorld = true; mBounds = CalculateBounds(mPosition, mItemRot, mWidth, mLength); int colWidth = mWidth * 2; int colLength = mLength * 2; for (int iX = 0; iX < colWidth; ++iX) { for (int iY = 0; iY < colLength; ++iY) { IntVec2 worldTile = GetWorldCollisionTile(iX, iY, mPosition, mItemRot); CCollisionTile tile = mWorld.mMap.mGlobalCollisionTiles[worldTile.X, worldTile.Y]; tile.mOccupied = -1; tile.mSolid = mAsset.mTiles[iX, iY].mSolid; } } for (int iX = 0; iX < mWidth; ++iX) { for (int iY = 0; iY < mLength; ++iY) { Vector2 worldPoint = RotationAxisTable[mItemRot].Transform(new Vector2(iX, iY)); int worldX = (int)worldPoint.x + mX; int worldY = (int)worldPoint.y + mY; CTile worldTile = mWorld.mMap.mTiles[worldX, worldY]; worldTile.mItem = mID; } } mWorld.RebuildInfluenceMap(); }
public void ModifyLocalCollisionMap(bool Active) { for (int iX = 0; iX < mAsset.mWidth * 2; ++iX) { for (int iY = 0; iY < mAsset.mLength * 2; ++iY) { IntVec2 worldTile = CItem.GetWorldCollisionTile(iX, iY, mPosition, mRotation); CCollisionTile tile = mWorld.mMap.mLocalCollisionTiles[mPlayerID][worldTile.X, worldTile.Y]; if (Active) { tile.mOccupied = mID; tile.mSolid = mAsset.mTiles[iX, iY].mSolid; } else { tile.mOccupied = 0; tile.mSolid = false; } } } Rect mr = new Rect(mBounds.min.x * 2.0f, mBounds.min.z * 2.0f, mBounds.size.x * 2.0f, mBounds.size.z * 2.0f); mWorld.mMap.CollisionModified(mPlayerID, mr); }
public void Generate(CMap Map, int PlayerId) { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); mRects.Clear(); mEdges.Clear(); mPortals.Clear(); Array.Clear(mRectLookup, 0, mRectLookup.Length); for (int i = 0; i < Map.mWidth * 2 + 1; ++i) { mXAxisEdges[i].Clear(); mYAxisEdges[i].Clear(); } for (int iX = 0; iX < 7; ++iX) { for (int iY = 0; iY < 7; ++iY) { mBuckets[iX, iY].Clear(); } } CCollisionTile[,] tileMap = Map.mLocalCollisionTiles[PlayerId]; double setupTime = sw.Elapsed.TotalMilliseconds; // Touch all cells and expand rects for (int iY = 0; iY < Map.mWidth * 2; ++iY) { for (int iX = 0; iX < Map.mWidth * 2; ++iX) { CCollisionTile tile = tileMap[iX, iY]; if (mRectLookup[iX, iY] == null && tile.mOccupied >= 0) { bool expandX = true; bool expandY = true; int sizeX = 1; int sizeY = 1; //int type = tile.mOccupied + 10000 * (tile.mSolid ? 1 : 0); int type = (tile.mOccupied + 10000) * (tile.mSolid ? 1 : 0); while (expandX || expandY) { // Check expansion in X if (expandX) { expandX = _CanExpandX(mRectLookup, tileMap, iX + sizeX - 1, iY, sizeY, type); } // Check expansion in Y if (expandY) { expandY = _CanExpandY(mRectLookup, tileMap, iX, iY + sizeY - 1, sizeX, type); } // Check corner expansion if we do both if (expandX && expandY) { // If we fail here, then prefer expand X. if (mRectLookup[iX + sizeX, iY + sizeY] != null || //tileMap[iX + sizeX, iY + sizeY].mOccupied + 10000 * (tileMap[iX + sizeX, iY + sizeY].mSolid ? 1 : 0) != type || (tileMap[iX + sizeX, iY + sizeY].mOccupied + 10000) * (tileMap[iX + sizeX, iY + sizeY].mSolid ? 1 : 0) != type || tileMap[iX + sizeX, iY + sizeY].mWallXSolid || tileMap[iX + sizeX, iY + sizeY].mWallZSolid) { expandY = false; } } if ((iX + sizeX) % 32 == 0) { expandX = false; } if ((iY + sizeY) % 32 == 0) { expandY = false; } if (expandX) { ++sizeX; } if (expandY) { ++sizeY; } } // Add nav rect. CNavRect r = new CNavRect(); r.mIndex = mRects.Count; r.mRect = new Rect(iX, iY, sizeX, sizeY); r.mFlags = type; r.mRoomId = -1; mRects.Add(r); mBuckets[iX / 32, iY / 32].Add(r); // Clear expanded area for (int jX = iX; jX < iX + sizeX; ++jX) { for (int jY = iY; jY < iY + sizeY; ++jY) { mRectLookup[jX, jY] = r; } } } } } double expansionTime = sw.Elapsed.TotalMilliseconds; // Go through each rect and determine accesible edges. for (int i = 0; i < mRects.Count; ++i) { Rect r = mRects[i].mRect; //----------------------------------------------------------------------------- // Bottom X //----------------------------------------------------------------------------- int start = (int)r.xMin; int run = 0; int y = (int)r.y; int x = (int)r.x; for (int j = start; j < (int)r.xMax; ++j) { if (tileMap[j, y].mWallXSolid) { if (run != 0) { // Add run to this point CNavRectEdge e = new CNavRectEdge(new Vector2(start, y), new Vector2(start + run, y), mRects[i]); mEdges.Add(e); mXAxisEdges[y].Add(e); run = 0; } start = j + 1; } else { if (run != 0 && tileMap[j, y - 1].mWallZSolid) { // Add run to this point and start with 1 already in run CNavRectEdge e = new CNavRectEdge(new Vector2(start, y), new Vector2(start + run, y), mRects[i]); mEdges.Add(e); mXAxisEdges[y].Add(e); start = j; run = 0; } ++run; } } // Add final non-blocked edge. if (run != 0) { CNavRectEdge e = new CNavRectEdge(new Vector2(start, y), new Vector2(start + run, y), mRects[i]); mEdges.Add(e); mXAxisEdges[y].Add(e); } //----------------------------------------------------------------------------- // Top X //----------------------------------------------------------------------------- start = (int)r.xMin; run = 0; y = (int)r.yMax; x = (int)r.x; for (int j = start; j < (int)r.xMax; ++j) { if (tileMap[j, y].mWallXSolid) { if (run != 0) { // Add run to this point CNavRectEdge e = new CNavRectEdge(new Vector2(start, y), new Vector2(start + run, y), mRects[i]); mEdges.Add(e); mXAxisEdges[y].Add(e); run = 0; } start = j + 1; } else { if (run != 0 && tileMap[j, y].mWallZSolid) { // Add run to this point and start with 1 already in run CNavRectEdge e = new CNavRectEdge(new Vector2(start, y), new Vector2(start + run, y), mRects[i]); mEdges.Add(e); mXAxisEdges[y].Add(e); start = j; run = 0; } ++run; } } // Add final non-blocked edge. if (run != 0) { CNavRectEdge e = new CNavRectEdge(new Vector2(start, y), new Vector2(start + run, y), mRects[i]); mEdges.Add(e); mXAxisEdges[y].Add(e); } //----------------------------------------------------------------------------- // Left Y //----------------------------------------------------------------------------- start = (int)r.yMin; run = 0; y = (int)r.y; x = (int)r.x; for (int j = start; j < (int)r.yMax; ++j) { if (tileMap[x, j].mWallZSolid) { if (run != 0) { // Add run to this point CNavRectEdge e = new CNavRectEdge(new Vector2(x, start), new Vector2(x, start + run), mRects[i]); mEdges.Add(e); mYAxisEdges[x].Add(e); run = 0; } start = j + 1; } else { if (run != 0 && tileMap[x - 1, j].mWallXSolid) { // Add run to this point and start with 1 already in run CNavRectEdge e = new CNavRectEdge(new Vector2(x, start), new Vector2(x, start + run), mRects[i]); mEdges.Add(e); mYAxisEdges[x].Add(e); start = j; run = 0; } ++run; } } // Add final non-blocked edge. if (run != 0) { CNavRectEdge e = new CNavRectEdge(new Vector2(x, start), new Vector2(x, start + run), mRects[i]); mEdges.Add(e); mYAxisEdges[x].Add(e); } //----------------------------------------------------------------------------- // Right Y //----------------------------------------------------------------------------- start = (int)r.yMin; run = 0; y = (int)r.y; x = (int)r.xMax; for (int j = start; j < (int)r.yMax; ++j) { if (tileMap[x, j].mWallZSolid) { if (run != 0) { // Add run to this point CNavRectEdge e = new CNavRectEdge(new Vector2(x, start), new Vector2(x, start + run), mRects[i]); mEdges.Add(e); mYAxisEdges[x].Add(e); run = 0; } start = j + 1; } else { if (run != 0 && tileMap[x, j].mWallXSolid) { // Add run to this point and start with 1 already in run CNavRectEdge e = new CNavRectEdge(new Vector2(x, start), new Vector2(x, start + run), mRects[i]); mEdges.Add(e); mYAxisEdges[x].Add(e); start = j; run = 0; } ++run; } } // Add final non-blocked edge. if (run != 0) { CNavRectEdge e = new CNavRectEdge(new Vector2(x, start), new Vector2(x, start + run), mRects[i]); mEdges.Add(e); mYAxisEdges[x].Add(e); } } double edgesTime = sw.Elapsed.TotalMilliseconds; // Generate portals. for (int k = 0; k < Map.mWidth * 2 + 1; ++k) { List <CNavRectEdge> edges = mXAxisEdges[k]; for (int i = 0; i < edges.Count; ++i) { for (int j = i + 1; j < edges.Count; ++j) { float min = Mathf.Max(edges[i].mA.x, edges[j].mA.x); float max = Mathf.Min(edges[i].mB.x, edges[j].mB.x); if (min < max) { CNavRectPortal p = new CNavRectPortal(new Vector2(min, edges[i].mA.y), new Vector2(max, edges[i].mA.y), edges[i].mRect, edges[j].mRect); mPortals.Add(p); edges[i].mRect.mPortals.Add(p); edges[j].mRect.mPortals.Add(p); } } } edges = mYAxisEdges[k]; for (int i = 0; i < edges.Count; ++i) { for (int j = i + 1; j < edges.Count; ++j) { float min = Mathf.Max(edges[i].mA.y, edges[j].mA.y); float max = Mathf.Min(edges[i].mB.y, edges[j].mB.y); if (min < max) { CNavRectPortal p = new CNavRectPortal(new Vector2(edges[i].mA.x, min), new Vector2(edges[i].mA.x, max), edges[i].mRect, edges[j].mRect); mPortals.Add(p); edges[i].mRect.mPortals.Add(p); edges[j].mRect.mPortals.Add(p); } } } } double portalsTime = sw.Elapsed.TotalMilliseconds; // Generate room IDs. int roomCounter = 1; List <CNavRect> rectStack = new List <CNavRect>(); int rectScan = 0; while (rectScan < mRects.Count) { if (mRects[rectScan].mRoomId == -1) { if (mRects[rectScan].mFlags >= 10000) { mRects[rectScan].mRoomId = 0; } else { rectStack.Add(mRects[rectScan]); mRects[rectScan].mRoomId = roomCounter; while (rectStack.Count > 0) { CNavRect rect = rectStack[0]; rectStack.RemoveAt(0); for (int i = 0; i < rect.mPortals.Count; ++i) { CNavRectPortal p = rect.mPortals[i]; if (p.mRectA.mFlags < 10000 && p.mRectA.mRoomId == -1) { rectStack.Add(p.mRectA); p.mRectA.mRoomId = roomCounter; } if (p.mRectB.mFlags < 10000 && p.mRectB.mRoomId == -1) { rectStack.Add(p.mRectB); p.mRectB.mRoomId = roomCounter; } } } } ++roomCounter; } ++rectScan; } double roomTime = sw.Elapsed.TotalMilliseconds; sw.Stop(); Debug.Log("NavRect: " + sw.Elapsed.TotalMilliseconds.ToString("0.000") + "ms Setup: " + setupTime.ToString("0.000") + "ms Rects(" + mRects.Count + "): " + (expansionTime - setupTime).ToString("0.000") + "ms Edges(" + mEdges.Count + "): " + (edgesTime - expansionTime).ToString("0.000") + "ms Portals(" + mPortals.Count + "): " + (portalsTime - edgesTime).ToString("0.000") + "ms Rooms: " + (roomTime - portalsTime).ToString("0.000") + "ms"); }