public TileCollisionLayer(ECollisionType[][] existingMap, int newW, int newH) { if (existingMap == null) { InitializeLayout(newW, newH, ECollisionType.Moveable); } else { mLayoutMap = new ECollisionType[newW][]; for (int x = 0; x < newW; x++) { mLayoutMap[x] = new ECollisionType[newH]; for (int y = 0; y < newH; y++) { if (x >= existingMap.Length || y >= existingMap[x].Length) { mLayoutMap[x][y] = ECollisionType.Moveable; } else { mLayoutMap[x][y] = existingMap[x][y]; } } } } }
public void SetCell(int x, int y, ECollisionType Type) { if (IsValidPoint(x, y) == false) { return; } mLayoutMap[x][y] = Type; }
private void InitializeLayout(int width, int height, ECollisionType type) { mLayoutMap = new ECollisionType[width][]; for (int x = 0; x < width; x++) { mLayoutMap[x] = new ECollisionType[height]; for (int y = 0; y < height; y++) { mLayoutMap[x][y] = type; } } }
public bool CheckCell(int x, int y, ECollisionType flag) { if (IsValidCell(x, y) == false) { return(false); } int i = (y * Width) + x; ECollisionType cell = Cells[i]; return((cell & flag) > 0); }
public void SetCell(int x, int y, ECollisionType cell) { if (mMapBlocks == null || IsValidCell(x, y) == false) { return; } int i = (y * Width) + x; mMapCells[i] = cell; }
public void ReplaceIndex(ECollisionType existingType, ECollisionType newType) { for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { if (GetCell(x, y) == existingType) { SetCell(x, y, newType); } } } }
public static ECollisionType ByteToFlag(byte gat) { ECollisionType flag = ECollisionType.NotWalkable; switch (gat) { case 0: flag = (ECollisionType.Walkable | ECollisionType.Shootable); break; // walkable ground case 1: flag = ECollisionType.NotWalkable; break; // non-walkable ground case 2: flag = (ECollisionType.Walkable | ECollisionType.Shootable); break; // ??? case 3: flag = (ECollisionType.Walkable | ECollisionType.Shootable | ECollisionType.Water); break; // walkable water case 4: flag = (ECollisionType.Walkable | ECollisionType.Shootable); break; // ??? case 5: flag = (ECollisionType.Shootable); break; // gap (snipable) case 6: flag = (ECollisionType.Walkable | ECollisionType.Shootable); break; // ??? default: ServerConsole.ErrorLine("Unknown tile flag {0}, default to NoWalkable", gat); break; } return(flag); }
private static void WriteMapcache(string pathNew, Dictionary <string, MapcacheMapData> dataList) { BinaryFormatter bin = new BinaryFormatter(); int iMap = 0; using (FileStream s = new FileStream(pathNew, FileMode.Create)) { using (BinaryWriter writer = new BinaryWriter(s)) { writer.Write(dataList.Count); foreach (KeyValuePair <string, MapcacheMapData> kvp in dataList) { MapcacheMapData mapData = kvp.Value; Console.WriteLine("\t[" + (++iMap).ToString("000") + "/" + dataList.Count + "] " + kvp.Key); mapData.MyCellData = new byte[mapData.Width * mapData.Height]; for (int x = 0; x < mapData.Width; x++) { for (int y = 0; y < mapData.Height; y++) { int i = (y * mapData.Width) + x; ECollisionType flag = Map.ByteToFlag(mapData.CellData[i]); mapData.MyCellData[i] = (byte)flag; } } writer.Write(kvp.Key); writer.Write(mapData.Width); writer.Write(mapData.Height); byte[] buf = ZlibDeflate.Compress(mapData.MyCellData, true); writer.Write(buf.Length); writer.Write(buf); buf = null; mapData.MyCellData = null; mapData.CellData = null; GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced); } } } }
public void Draw(SpriteBatch batch, IEngineCamera camera, Point2D min, Point2D max) { Rectangle destRect; Texture2D drawTex = Constants.TextureNotMoveable; Color drawColor = Constants.ColorNotMoveable; for (int x = min.X; x < max.X; x++) { for (int y = min.Y; y < max.Y; y++) { ECollisionType type = GetCell(x, y); if (type == ECollisionType.Moveable) { drawTex = Constants.TextureMoveable; drawColor = Constants.ColorMoveable; } else if (type == ECollisionType.Water) { drawTex = Constants.TextureWater; drawColor = Constants.ColorWater; } else if (type == ECollisionType.Underwater) { drawTex = Constants.TextureUnderwater; drawColor = Constants.ColorUnderwater; } else { // Default draw to not moveable drawTex = Constants.TextureNotMoveable; drawColor = Constants.ColorNotMoveable; } destRect = new Rectangle(x * camera.TileWidth, y * camera.TileHeight, camera.TileWidth, camera.TileHeight); batch.Draw(drawTex, destRect, drawColor); } } }
public TileCollisionLayer(ECollisionType[][] existingMap) { mLayoutMap = (ECollisionType[][])existingMap.Clone(); }
public void SetCell(Point2D p, ECollisionType cell) { SetCell(p.X, p.Y, cell); }
public void SetCell(Point point, ECollisionType Type) { SetCell(point.X, point.Y, Type); }
public void RemoveType(ECollisionType existingType) { ReplaceIndex(existingType, ECollisionType.NotMoveable); }
public TileCollisionLayer(int width, int height, ECollisionType type) { InitializeLayout(width, height, type); }
/*========================================== * is ranged attack from (x0,y0) to (x1,y1) possible? *------------------------------------------*/ public static bool SearchLongPath(ShootpathData spd, Map m, int x0, int y0, int x1, int y1, ECollisionType cell) { int dx, dy; int wx = 0, wy = 0; int weight; if (spd == null) { spd = new ShootpathData(); // use dummy output variable } dx = (x1 - x0); if (dx < 0) { x0 = x0.Swap(ref x1); y0 = y0.Swap(ref y1); dx = -dx; } dy = (y1 - y0); spd.rx = spd.ry = 0; spd.len = 1; spd.x[0] = x0; spd.y[0] = y0; if (m.CheckCell(x1, y1, cell)) { return(false); } if (dx > Math.Abs(dy)) { weight = dx; spd.ry = 1; } else { weight = Math.Abs(y1 - y0); spd.rx = 1; } while (x0 != x1 || y0 != y1) { if (m.CheckCell(x0, y0, cell)) { return(false); } wx += dx; wy += dy; if (wx >= weight) { wx -= weight; x0++; } if (wy >= weight) { wy -= weight; y0++; } else if (wy < 0) { wy += weight; y0--; } if (spd.len < MAX_WALKPATH) { spd.x[spd.len] = x0; spd.y[spd.len] = y0; spd.len++; } } return(true); }
/// <summary> /// path search (x0,y0).(x1,y1) /// <para> /// flag & 1 = easy path search only /// </para> /// </summary> /// <param name="wpd">path info will be written here</param> /// <param name="m">map to check the path on</param> /// <param name="pStart">start-point</param> /// <param name="pEnd">end-point</param> /// <param name="flag">&1 = easy path search only</param> /// <param name="cell">type of obstruction to check for</param> /// <returns></returns> public static bool SearchPath(out WalkpathData wpd, Map m, Point2D pStart, Point2D pEnd, int flag, ECollisionType cell) { return(SearchPath(out wpd, m, pStart.X, pStart.Y, pEnd.X, pEnd.Y, flag, cell)); }
public void SetCellData(ECollisionType[] cells) { mMapCells = cells; }
/// <summary> /// path search (x0,y0).(x1,y1) /// <para> /// flag & 1 = easy path search only /// </para> /// </summary> /// <param name="wpd">path info will be written here</param> /// <param name="m">map to check the path on</param> /// <param name="x0">start X</param> /// <param name="y0">start Y</param> /// <param name="x1">end X</param> /// <param name="y1">end Y</param> /// <param name="flag">&1 = easy path search only</param> /// <param name="cell">type of obstruction to check for</param> /// <returns></returns> public static bool SearchPath(out WalkpathData wpd, Map m, int x0, int y0, int x1, int y1, int flag, ECollisionType cell) { int[] heap = new int[MAX_HEAP + 1]; STmpPath[] tp = new STmpPath[MAX_WALKPATH * MAX_WALKPATH]; int i, j, len, x, y, dx, dy; int rp, xs, ys; wpd = new WalkpathData(); //Do not check starting cell as that would get you stuck. if (x0 < 0 || x0 >= m.Width || y0 < 0 || y0 >= m.Height /*|| m.CheckTile(x0,y0,cell) == false*/) { return(false); } if (x1 < 0 || x1 >= m.Width || y1 < 0 || y1 >= m.Height || m.CheckCell(x1, y1, cell) == false) { return(false); } // calculate (sgn(x1-x0), sgn(y1-y0)) dx = ((dx = x1 - x0) > 0) ? ((dx < 0) ? -1 : 1) : 0; dy = ((dy = y1 - y0) > 0) ? ((dy < 0) ? -1 : 1) : 0; // try finding direct path to target x = x0; y = y0; i = 0; while (i < wpd.path.Length) { wpd.path[i] = WalkChoises[-dy + 1][dx + 1]; i++; x += dx; y += dy; if (x == x1) { dx = 0; } if (y == y1) { dy = 0; } if (dx == 0 && dy == 0) { break; // success } if (m.CheckCell(x, y, cell) == false) { break; // obstacle = failure } } if (x == x1 && y == y1) //easy path successful. { wpd.path_len = (uint)i; wpd.path_pos = 0; return(true); } if ((flag & 1) == 1) { return(false); } i = CalcIndex(x0, y0); tp[i].x = (short)x0; tp[i].y = (short)y0; tp[i].dist = 0; tp[i].before = 0; tp[i].cost = (short)CalcCost(tp[i], x1, y1); tp[i].flag = 0; heap[0] = 0; PushHeapPath(heap, tp, CalcIndex(x0, y0)); xs = m.Width - 1; // ‚ ‚ç‚©‚¶‚ß‚PŒ¸ŽZ‚µ‚Ä‚¨‚ ys = m.Height - 1; while (true) { int e = 0, f = 0; int dist; int cost; int[] dc = new int[4]; if (heap[0] == 0) { return(false); } rp = PopHeapPath(heap, tp); x = tp[rp].x; y = tp[rp].y; dist = tp[rp].dist + 10; cost = tp[rp].cost; if (x == x1 && y == y1) { break; } // dc[0] : y++ // dc[1] : x-- // dc[2] : y-- // dc[3] : x++ if (y < ys && m.CheckCell(x, y + 1, cell)) { f |= 1; dc[0] = (y >= y1 ? 20 : 0); e += AddPath(heap, tp, x, y + 1, dist, rp, cost + dc[0]); // (x, y+1) } if (x > 0 && m.CheckCell(x - 1, y, cell)) { f |= 2; dc[1] = (x <= x1 ? 20 : 0); e += AddPath(heap, tp, x - 1, y, dist, rp, cost + dc[1]); // (x-1, y ) } if (y > 0 && m.CheckCell(x, y - 1, cell)) { f |= 4; dc[2] = (y <= y1 ? 20 : 0); e += AddPath(heap, tp, x, y - 1, dist, rp, cost + dc[2]); // (x , y-1) } if (x < xs && m.CheckCell(x + 1, y, cell)) { f |= 8; dc[3] = (x >= x1 ? 20 : 0); e += AddPath(heap, tp, x + 1, y, dist, rp, cost + dc[3]); // (x+1, y ) } if ((f & (2 + 1)) == (2 + 1) && m.CheckCell(x - 1, y + 1, cell)) { e += AddPath(heap, tp, x - 1, y + 1, dist + 4, rp, cost + dc[1] + dc[0] - 6); // (x-1, y+1) } if ((f & (2 + 4)) == (2 + 4) && m.CheckCell(x - 1, y - 1, cell)) { e += AddPath(heap, tp, x - 1, y - 1, dist + 4, rp, cost + dc[1] + dc[2] - 6); // (x-1, y-1) } if ((f & (8 + 4)) == (8 + 4) && m.CheckCell(x + 1, y - 1, cell)) { e += AddPath(heap, tp, x + 1, y - 1, dist + 4, rp, cost + dc[3] + dc[2] - 6); // (x+1, y-1) } if ((f & (8 + 1)) == (8 + 1) && m.CheckCell(x + 1, y + 1, cell)) { e += AddPath(heap, tp, x + 1, y + 1, dist + 4, rp, cost + dc[3] + dc[0] - 6); // (x+1, y+1) } tp[rp].flag = 1; if (e > 0 || heap[0] >= MAX_HEAP - 5) { return(false); } } if (!(x == x1 && y == y1)) // will never happen... { return(false); } for (len = 0, i = rp; len < 100 && i != CalcIndex(x0, y0); i = tp[i].before, len++) { } if (len == 100 || len >= wpd.path.Length) { return(false); } wpd.path_len = (uint)len; wpd.path_pos = 0; for (i = rp, j = len - 1; j >= 0; i = tp[i].before, j--) { dx = tp[i].x - tp[tp[i].before].x; dy = tp[i].y - tp[tp[i].before].y; Point2D p = new Point2D(dx, dy); wpd.path[j] = p.ToDirection(); } return(true); }
public bool CheckCell(Point2D p, ECollisionType flag) { return(CheckCell(p.X, p.Y, flag)); }
/// <summary> /// path search (x0,y0).(x1,y1) /// <para> /// flag & 1 = easy path search only /// </para> /// </summary> /// <param name="wpd">path info will be written here</param> /// <param name="m">map to check the path on</param> /// <param name="pStart">start-point</param> /// <param name="pEnd">end-point</param> /// <param name="flag">&1 = easy path search only</param> /// <param name="cell">type of obstruction to check for</param> /// <returns></returns> public static bool SearchPath(out WalkpathData wpd, Map m, Point2D pStart, Point2D pEnd, int flag, ECollisionType cell) { return SearchPath(out wpd, m, pStart.X, pStart.Y, pEnd.X, pEnd.Y, flag, cell); }
public bool CheckCell(int x, int y, ECollisionType flag) { if (IsValidCell(x, y) == false) { return false; } int i = (y * Width) + x; ECollisionType cell = Cells[i]; return (cell & flag) > 0; }
/*========================================== * is ranged attack from (x0,y0) to (x1,y1) possible? *------------------------------------------*/ public static bool SearchLongPath(ShootpathData spd, Map m, int x0, int y0, int x1, int y1, ECollisionType cell) { int dx, dy; int wx = 0, wy = 0; int weight; if (spd == null) spd = new ShootpathData(); // use dummy output variable dx = (x1 - x0); if (dx < 0) { x0 = x0.Swap(ref x1); y0 = y0.Swap(ref y1); dx = -dx; } dy = (y1 - y0); spd.rx = spd.ry = 0; spd.len = 1; spd.x[0] = x0; spd.y[0] = y0; if (m.CheckCell(x1, y1, cell)) return false; if (dx > Math.Abs(dy)) { weight = dx; spd.ry = 1; } else { weight = Math.Abs(y1 - y0); spd.rx = 1; } while (x0 != x1 || y0 != y1) { if (m.CheckCell(x0, y0, cell)) return false; wx += dx; wy += dy; if (wx >= weight) { wx -= weight; x0++; } if (wy >= weight) { wy -= weight; y0++; } else if (wy < 0) { wy += weight; y0--; } if (spd.len < MAX_WALKPATH) { spd.x[spd.len] = x0; spd.y[spd.len] = y0; spd.len++; } } return true; }
public bool CheckCell(Point2D p, ECollisionType flag) { return CheckCell(p.X, p.Y, flag); }
/// <summary> /// path search (x0,y0).(x1,y1) /// <para> /// flag & 1 = easy path search only /// </para> /// </summary> /// <param name="wpd">path info will be written here</param> /// <param name="m">map to check the path on</param> /// <param name="x0">start X</param> /// <param name="y0">start Y</param> /// <param name="x1">end X</param> /// <param name="y1">end Y</param> /// <param name="flag">&1 = easy path search only</param> /// <param name="cell">type of obstruction to check for</param> /// <returns></returns> public static bool SearchPath(out WalkpathData wpd, Map m, int x0, int y0, int x1, int y1, int flag, ECollisionType cell) { int[] heap = new int[MAX_HEAP + 1]; STmpPath[] tp = new STmpPath[MAX_WALKPATH * MAX_WALKPATH]; int i, j, len, x, y, dx, dy; int rp, xs, ys; wpd = new WalkpathData(); //Do not check starting cell as that would get you stuck. if (x0 < 0 || x0 >= m.Width || y0 < 0 || y0 >= m.Height /*|| m.CheckTile(x0,y0,cell) == false*/ ) return false; if (x1 < 0 || x1 >= m.Width || y1 < 0 || y1 >= m.Height || m.CheckCell(x1, y1, cell) == false) return false; // calculate (sgn(x1-x0), sgn(y1-y0)) dx = ((dx = x1 - x0) > 0) ? ((dx < 0) ? -1 : 1) : 0; dy = ((dy = y1 - y0) > 0) ? ((dy < 0) ? -1 : 1) : 0; // try finding direct path to target x = x0; y = y0; i = 0; while (i < wpd.path.Length) { wpd.path[i] = WalkChoises[-dy + 1][dx + 1]; i++; x += dx; y += dy; if (x == x1) dx = 0; if (y == y1) dy = 0; if (dx == 0 && dy == 0) break; // success if (m.CheckCell(x, y, cell) == false) break; // obstacle = failure } if (x == x1 && y == y1) { //easy path successful. wpd.path_len = (uint)i; wpd.path_pos = 0; return true; } if ((flag & 1) == 1) return false; i = CalcIndex(x0, y0); tp[i].x = (short)x0; tp[i].y = (short)y0; tp[i].dist = 0; tp[i].before = 0; tp[i].cost = (short)CalcCost(tp[i], x1, y1); tp[i].flag = 0; heap[0] = 0; PushHeapPath(heap, tp, CalcIndex(x0, y0)); xs = m.Width - 1; // ‚ ‚ç‚©‚¶‚ß‚PŒ¸ŽZ‚µ‚Ä‚¨‚ ys = m.Height - 1; while (true) { int e = 0, f = 0; int dist; int cost; int[] dc = new int[4]; if (heap[0] == 0) return false; rp = PopHeapPath(heap, tp); x = tp[rp].x; y = tp[rp].y; dist = tp[rp].dist + 10; cost = tp[rp].cost; if (x == x1 && y == y1) break; // dc[0] : y++ // dc[1] : x-- // dc[2] : y-- // dc[3] : x++ if (y < ys && m.CheckCell(x, y + 1, cell)) { f |= 1; dc[0] = (y >= y1 ? 20 : 0); e += AddPath(heap, tp, x, y + 1, dist, rp, cost + dc[0]); // (x, y+1) } if (x > 0 && m.CheckCell(x - 1, y, cell)) { f |= 2; dc[1] = (x <= x1 ? 20 : 0); e += AddPath(heap, tp, x - 1, y, dist, rp, cost + dc[1]); // (x-1, y ) } if (y > 0 && m.CheckCell(x, y - 1, cell)) { f |= 4; dc[2] = (y <= y1 ? 20 : 0); e += AddPath(heap, tp, x, y - 1, dist, rp, cost + dc[2]); // (x , y-1) } if (x < xs && m.CheckCell(x + 1, y, cell)) { f |= 8; dc[3] = (x >= x1 ? 20 : 0); e += AddPath(heap, tp, x + 1, y, dist, rp, cost + dc[3]); // (x+1, y ) } if ((f & (2 + 1)) == (2 + 1) && m.CheckCell(x - 1, y + 1, cell)) e += AddPath(heap, tp, x - 1, y + 1, dist + 4, rp, cost + dc[1] + dc[0] - 6); // (x-1, y+1) if ((f & (2 + 4)) == (2 + 4) && m.CheckCell(x - 1, y - 1, cell)) e += AddPath(heap, tp, x - 1, y - 1, dist + 4, rp, cost + dc[1] + dc[2] - 6); // (x-1, y-1) if ((f & (8 + 4)) == (8 + 4) && m.CheckCell(x + 1, y - 1, cell)) e += AddPath(heap, tp, x + 1, y - 1, dist + 4, rp, cost + dc[3] + dc[2] - 6); // (x+1, y-1) if ((f & (8 + 1)) == (8 + 1) && m.CheckCell(x + 1, y + 1, cell)) e += AddPath(heap, tp, x + 1, y + 1, dist + 4, rp, cost + dc[3] + dc[0] - 6); // (x+1, y+1) tp[rp].flag = 1; if (e > 0 || heap[0] >= MAX_HEAP - 5) return false; } if (!(x == x1 && y == y1)) // will never happen... return false; for (len = 0, i = rp; len < 100 && i != CalcIndex(x0, y0); i = tp[i].before, len++) { } if (len == 100 || len >= wpd.path.Length) return false; wpd.path_len = (uint)len; wpd.path_pos = 0; for (i = rp, j = len - 1; j >= 0; i = tp[i].before, j--) { dx = tp[i].x - tp[tp[i].before].x; dy = tp[i].y - tp[tp[i].before].y; Point2D p = new Point2D(dx, dy); wpd.path[j] = p.ToDirection(); } return true; }
public static void Initialize() { Maps = new Dictionary <int, Map>(); Stopwatch watch = Stopwatch.StartNew(); Dictionary <string, MapcacheMapData> mapDataList = ReadMapcache(Core.Conf.Maplist["MapcachePath"]); Debug.WriteLine("Mapcache binary data took: " + watch.ElapsedMilliseconds + "ms"); watch.Restart(); MapcacheMapData mapData; Map map; string mapname; ECollisionType[] cells; int mapCount = Core.Conf.Maplist.Settings.Count - 1; foreach (KeyValuePair <string, string> kvp in Core.Conf.Maplist.Settings) { if (kvp.Key == "MapcachePath") { continue; } mapname = kvp.Value; if (mapDataList.ContainsKey(mapname) == false) { // Map not found! ServerConsole.ErrorLine("Can't find mapcache data for map '{0}', removed from list.", mapname); continue; } mapData = mapDataList[mapname]; mapDataList.Remove(mapname); map = new Map(mapname, mapData.Width, mapData.Height); // Faster than .ConvertAll() or .Cast<>().. // but still needs 4-6sec.. // TODO: this should be faster than 150 maps per sec! cells = new ECollisionType[mapData.CellData.Length]; for (int i = 0; i < cells.Length; i++) { cells[i] = (ECollisionType)mapData.CellData[i]; } map.SetCellData(cells); Maps.Add(map.ID, map); cells = null; map = null; //ServerConsole.DebugLine("Loading Maps [{0:000}/{1}]: {2}\r", Maps.Count, mapCount, mapname); } mapData = null; mapDataList = null; map = null; Debug.WriteLine("Mapcache managed data took: " + watch.ElapsedMilliseconds + "ms"); watch.Stop(); watch = null; }