Пример #1
0
 protected override void OnKeyDown(KeyEventArgs e)
 {
     if (e.KeyData == Keys.Subtract || e.KeyData == Keys.OemMinus) {
         mapCoordinate.z--;
         UpdateMap();
     } else if (e.KeyData == Keys.Add || e.KeyData == Keys.Oemplus) {
         mapCoordinate.z++;
         UpdateMap();
     } else if (e.KeyData == Keys.Space) {
         mapCoordinate = new Coordinate(beginCoordinate);
         sourceWidth = beginWidth;
         UpdateMap();
     } else if (e.KeyData == Keys.Right) {
         FakePlayerData = nextConnectionPoint;
     } else {
         base.OnKeyDown(e);
     }
 }
Пример #2
0
 public void NextStep()
 {
     if (nextConnectionPoint.X >= 0) {
         FakePlayerData = nextConnectionPoint;
     }
 }
Пример #3
0
        public void UpdateMap(bool periodicUpdate = false)
        {
            lock (mapBoxLock) {
                int PlayerX = 0, PlayerY = 0, PlayerZ = 0;
                bool recomputeRoute = true;

                if (targetCoordinate != null) {
                    MemoryReader.UpdateBattleList();
                    PlayerX = MemoryReader.X;
                    PlayerY = MemoryReader.Y;
                    PlayerZ = MemoryReader.Z;

                    Point3D playerCoordinate = new Point3D(PlayerX, PlayerY, PlayerZ);
                    if (previousCoordinate != playerCoordinate) {
                        previousCoordinate = playerCoordinate;
                        mapCoordinate = new Coordinate(PlayerX, PlayerY, PlayerZ);
                    } else {
                        if (FakePlayerData.X >= 0) {
                            PlayerX = FakePlayerData.X;
                            PlayerY = FakePlayerData.Y;
                            PlayerZ = FakePlayerData.Z;

                            mapCoordinate = new Coordinate(PlayerX, PlayerY, PlayerZ);

                            FakePlayerData = new Point3D(-1, -1, -1);
                        } else {
                            if (periodicUpdate) return;
                            recomputeRoute = false;
                        }
                    }
                }
                if (beginCoordinate == null) {
                    beginCoordinate = new Coordinate(mapCoordinate);
                    beginWidth = sourceWidth;
                }
                if (beginCoordinate.x == Coordinate.MaxWidth / 2 && beginCoordinate.y == Coordinate.MaxHeight / 2 && beginCoordinate.z == 7) {
                    Image oldImage = this.Image;
                    this.Image = StyleManager.GetImage("nomapavailable.png");
                    if (oldImage != StyleManager.GetImage("nomapavailable.png") && oldImage != null) {
                        oldImage.Dispose();
                    }
                    this.SizeMode = PictureBoxSizeMode.Zoom;
                    return;
                }
                if (mapCoordinate.z < 0) {
                    mapCoordinate.z = 0;
                } else if (mapCoordinate.z >= StorageManager.mapFilesCount) {
                    mapCoordinate.z = StorageManager.mapFilesCount - 1;
                }
                if (mapCoordinate.x - sourceWidth / 2 < 0) {
                    mapCoordinate.x = sourceWidth / 2;
                }
                if (mapCoordinate.x + sourceWidth / 2 > Coordinate.MaxWidth) {
                    mapCoordinate.x = Coordinate.MaxWidth - sourceWidth / 2;
                }
                if (mapCoordinate.y - sourceWidth / 2 < 0) {
                    mapCoordinate.y = sourceWidth / 2;
                }
                if (mapCoordinate.y + sourceWidth / 2 > Coordinate.MaxHeight) {
                    mapCoordinate.y = Coordinate.MaxHeight - sourceWidth / 2;
                }

                Image image;
                if (mapCoordinate.z == zCoordinate) {
                    image = map != null ? map.GetImage() : mapImage;
                } else {
                    Map m = StorageManager.getMap(mapCoordinate.z);
                    if (otherMap != null && m != otherMap) {
                        otherMap.Dispose();
                    }
                    otherMap = m;
                    image = m.GetImage();
                }

                lock (image) {
                    sourceWidth = Math.Min(Math.Max(sourceWidth, minWidth), maxWidth);
                    Rectangle sourceRectangle = new Rectangle(mapCoordinate.x - sourceWidth / 2, mapCoordinate.y - sourceWidth / 2, sourceWidth, sourceWidth);
                    Bitmap bitmap = new Bitmap(this.Width, this.Height);
                    using (Graphics gr = Graphics.FromImage(bitmap)) {
                        gr.DrawImage(image, new Rectangle(0, 0, bitmap.Width, bitmap.Height), sourceRectangle, GraphicsUnit.Pixel);

                        if (targetCoordinate != null && recomputeRoute) {
                            Coordinate beginCoordinate = new Coordinate(PlayerX, PlayerY, PlayerZ);

                            Node beginNode = Pathfinder.GetNode(beginCoordinate.x, beginCoordinate.y, beginCoordinate.z);
                            Node endNode = Pathfinder.GetNode(targetCoordinate.x, targetCoordinate.y, targetCoordinate.z);

                            List<Rectangle3D> collisionBounds = null;
                            DijkstraNode highresult = Dijkstra.FindRoute(beginNode, endNode, new Point3D(targetCoordinate), previousResult);
                            previousResult = highresult;
                            SpecialConnection connection = null;

                            nextConnectionPoint = new Point3D(-1, -1, -1);
                            nextImportantTarget = null;
                            nextTarget = "Head to the destination.";
                            if (highresult != null) {
                                collisionBounds = new List<Rectangle3D>();
                                while (highresult != null) {
                                    highresult.rect.Inflate(5, 5);
                                    collisionBounds.Add(new Rectangle3D(highresult.rect, highresult.node.z));
                                    /*if (highresult.node.z == beginCoordinate.z) {
                                        Point tl = new Point(convertx(highresult.rect.X), converty(highresult.rect.Y));
                                        Point tr = new Point(convertx(highresult.rect.X + highresult.rect.Width), converty(highresult.rect.Y + highresult.rect.Height));
                                        gr.DrawRectangle(Pens.Yellow, new Rectangle(tl.X, tl.Y, (tr.X - tl.X), (tr.Y - tl.Y)));
                                    }*/
                                    if (highresult.connection.connection != null) {
                                        connection = highresult.connection.connection;
                                        if (connection.name.Equals("stairs", StringComparison.InvariantCultureIgnoreCase)) {
                                            nextTarget = connection.destination.z > connection.source.z ? "Go down the stairs." : "Go up the stairs.";
                                        } else if (connection.name.Equals("levitate", StringComparison.InvariantCultureIgnoreCase)) {
                                            nextTarget = connection.destination.z > connection.source.z ? "Levitate down." : "Levitate up.";
                                        } else {
                                            nextImportantTarget = String.Format("Take the {0}.", connection.name);
                                            nextTarget = null;
                                        }
                                        nextConnectionPoint = new Point3D(connection.destination.x, connection.destination.y, connection.destination.z);
                                    }
                                    highresult = highresult.previous;
                                }
                                if (collisionBounds.Count == 0) collisionBounds = null;
                            }

                            Map m = StorageManager.getMap(beginCoordinate.z);
                            DijkstraPoint result = Dijkstra.FindRoute(image as Bitmap, new Point3D(beginCoordinate), new Point3D(targetCoordinate), collisionBounds, null, connection);
                            if (result != null) {
                                playerPath = new TibiaPath();
                                playerPath.path = result;
                                playerPath.begin = beginCoordinate;
                                playerPath.end = targetCoordinate;
                                DrawPath(gr, playerPath);
                            }
                        } else if (!recomputeRoute && playerPath != null) {
                            DrawPath(gr, playerPath);
                        }

                        foreach (TibiaPath path in paths) {
                            DrawPath(gr, path);
                        }

                        foreach (Target target in targets) {
                            if (target.coordinate.z == mapCoordinate.z) {
                                int x = target.coordinate.x - (mapCoordinate.x - sourceWidth / 2);
                                int y = target.coordinate.y - (mapCoordinate.y - sourceWidth / 2);
                                if (x >= 0 && y >= 0 && x < sourceWidth && y < sourceWidth) {
                                    x = (int)((double)x / sourceWidth * bitmap.Width);
                                    y = (int)((double)y / sourceWidth * bitmap.Height);
                                    lock (target.image) {
                                        int targetWidth = (int)((double)target.size / target.image.Height * target.image.Width);
                                        gr.DrawImage(target.image, new Rectangle(x - targetWidth, y - target.size, targetWidth * 2, target.size * 2));
                                    }
                                }
                            }
                        }
                    }
                    Image oldImage = this.Image;
                    this.Image = bitmap;
                    if (oldImage != null) {
                        oldImage.Dispose();
                    }
                }
                if (MapUpdated != null)
                    MapUpdated();
            }
        }
Пример #4
0
        public static Tuple<DijkstraPoint, List<Rectangle3D>> FindRoute(Point3D point, Point3D target, Bitmap image)
        {
            Node n1 = Pathfinder.GetNode(Tibia_Path_Finder.Form1.beginx, Tibia_Path_Finder.Form1.beginy, 6);
            Node n2 = Pathfinder.GetNode(Tibia_Path_Finder.Form1.beginx, Tibia_Path_Finder.Form1.beginy, 7);

            Node beginNode = Pathfinder.GetNode(point.X, point.Y, point.Z);
            Node endNode = Pathfinder.GetNode(target.X, target.Y, target.Z);

            List<Rectangle3D> collisionBounds = null;
            DijkstraNode highresult = Dijkstra.FindRoute(beginNode, endNode, target);
            SpecialConnection connection = null;
            if (highresult != null) {
                collisionBounds = new List<Rectangle3D>();
                while (highresult != null) {
                    highresult.rect.Inflate(5, 5);
                    collisionBounds.Add(new Rectangle3D(highresult.rect, highresult.node.z));
                    /*Point tl = new Point(convertx(highresult.rect.X), converty(highresult.rect.Y));
                    Point tr = new Point(convertx(highresult.rect.X + highresult.rect.Width), converty(highresult.rect.Y + highresult.rect.Height));
                    gr.DrawRectangle(Pens.Yellow, new Rectangle(tl.X, tl.Y, (tr.X - tl.X), (tr.Y - tl.Y)));*/
                    if (highresult.connection.connection != null) {
                        connection = highresult.connection.connection;
                    }
                    highresult = highresult.previous;
                }
                if (collisionBounds.Count == 0) collisionBounds = null;
            }

            return new Tuple<DijkstraPoint, List<Rectangle3D>>(Dijkstra.FindRoute(image, point, target, collisionBounds, null, connection), collisionBounds);
        }
Пример #5
0
 public bool Contains(Point3D point)
 {
     return point.Z == Z ? Rect.Contains(point.X, point.Y) : false;
 }
Пример #6
0
 public static bool isWalkable(Point3D point, Color color)
 {
     return walkableColors.Contains(color) || Pathfinder.doors[point.Z].ContainsKey(new Tuple<int, int>(point.X, point.Y));
 }
Пример #7
0
 public DijkstraPoint(DijkstraPoint previous, Point3D point, double cost)
 {
     this.previous = previous;
     this.cost = cost;
     this.point = point;
 }
Пример #8
0
        public static DijkstraNode FindRoute(Node start, Node goal, Point3D exactGoal)
        {
            // Dijkstra algorithm
            // We use Dijkstra instead of A* because there are random teleports in Tibia (e.g. boats)
            // And it is difficult to create a good A* heuristic that takes random teleports into account
            // and Dijkstra has more consistently good performance than A* with a bad heuristic
            List<DijkstraNode> openSet = new List<DijkstraNode> { new DijkstraNode(null, new Connection(start), 0) };
            HashSet<Node> closedSet = new HashSet<Node>();

            double closestDistance = double.MaxValue;
            DijkstraNode closestNode = null;

            while (openSet.Count > 0) {
                // Extract path with current minimal cost
                DijkstraNode current = GetMinimum(openSet);
                if (current.node == goal) {
                    return current;
                }
                double distance = Distance(current.node, exactGoal);
                if (distance < closestDistance) {
                    closestNode = current;
                    closestDistance = distance;
                }
                // Add node to closed set
                openSet.Remove(current);
                closedSet.Add(current.node);

                // Iterate over all neighboring nodes
                foreach (Connection neighbor in current.node.neighbors) {
                    if (closedSet.Contains(neighbor.node)) continue;

                    // If node is not in closed set, create a new path, we use conn.settings.cost for 'special' connections (e.g. teleports, stairs)
                    double newCost = current.cost + (neighbor.connection == null ? Distance(current.node, neighbor.node) : 100);

                    DijkstraNode neighborAStar = openSet.Find(o => o.node == neighbor.node);
                    if (neighborAStar == null) {
                        // The node is not in the open set; add it
                        openSet.Add(new DijkstraNode(current, neighbor, newCost));
                    } else if (neighborAStar.cost < newCost) {
                        // If the node is already in the open set and with a lower cost than this path, this path cannot be optimal, so skip it
                        continue;
                    } else {
                        // If the node is already in the open set but with a higher cost, remove it and add this node
                        openSet.Remove(neighborAStar);
                        openSet.Add(new DijkstraNode(current, neighbor, newCost));
                    }
                }
            }
            return closestNode;
        }
Пример #9
0
 public static IEnumerable<Point3D> getNeighbors(Point3D point)
 {
     if (point.X > 0 && point.Y > 0 && point.X < Coordinate.MaxWidth && point.Y < Coordinate.MaxHeight) {
         yield return new Point3D(point.X - 1, point.Y - 1, point.Z);
         yield return new Point3D(point.X, point.Y - 1, point.Z);
         yield return new Point3D(point.X - 1, point.Y, point.Z);
         yield return new Point3D(point.X + 1, point.Y + 1, point.Z);
         yield return new Point3D(point.X + 1, point.Y, point.Z);
         yield return new Point3D(point.X, point.Y + 1, point.Z);
         yield return new Point3D(point.X - 1, point.Y + 1, point.Z);
         yield return new Point3D(point.X + 1, point.Y - 1, point.Z);
         if (Pathfinder.specialConnection.ContainsKey(point.Z)) {
             var tpl = new Tuple<int, int>(point.X, point.Y);
             if (Pathfinder.specialConnection[point.Z].ContainsKey(tpl)) {
                 foreach (SpecialConnection connection in Pathfinder.specialConnection[point.Z][tpl]) {
                     yield return new Point3D(connection.destination);
                 }
             }
         }
     }
     yield break;
 }
Пример #10
0
        public static DijkstraPoint FindRoute(Bitmap mapImage, Point3D start, Point3D end, List<Rectangle3D> bounds, List<Color> additionalWalkableColors, SpecialConnection connection = null)
        {
            Point3D connectionPoint = connection == null ? new Point3D(-1, -1, 0) : (connection.source.z == start.Z ? new Point3D(connection.source) : new Point3D(connection.destination));

            List<DijkstraPoint> openSet = new List<DijkstraPoint> { new DijkstraPoint(null, start, 0) };
            HashSet<Point3D> closedSet = new HashSet<Point3D>();
            DijkstraPoint closestNode = null;
            double closestDistance = double.MaxValue;

            while (openSet.Count > 0) {
                DijkstraPoint current = GetMinimum(openSet);
                if (current.point.Equals(end)) {
                    return current;
                }
                if (Distance(current.point, end) < closestDistance) {
                    closestDistance = Distance(current.point, end);
                    closestNode = current;
                }

                openSet.Remove(current);
                closedSet.Add(current.point);

                //check all the neighbors of the current point
                foreach (Point3D p in getNeighbors(current.point)) {
                    double newCost = current.cost + Distance(current.point, p);

                    if (connection != null && p == connectionPoint) {
                        return new DijkstraPoint(current, p, newCost);
                    }

                    if (current.point.Z != start.Z) {
                        continue;
                    }

                    if (closedSet.Contains(p)) continue;
                    if (!isWalkable(p, mapImage.GetPixel(p.X, p.Y))) {
                        closedSet.Add(p);
                        continue;
                    }
                    if (bounds != null) {
                        bool found = false;
                        foreach (Rectangle3D bound in bounds) {
                            if (bound.Contains(p)) {
                                found = true;
                                break;
                            }
                        }
                        if (!found) continue;
                    }

                    DijkstraPoint neighborPoint = openSet.Find(o => o.point == p);
                    if (neighborPoint == null) {
                        openSet.Add(new DijkstraPoint(current, p, newCost));
                    } else if (neighborPoint.cost < newCost) {
                        continue;
                    } else {
                        openSet.Remove(neighborPoint);
                        openSet.Add(new DijkstraPoint(current, p, newCost));
                    }
                }
            }
            return closestNode;
        }
Пример #11
0
 public static double Distance(Node node, Point3D goal)
 {
     return Math.Abs(node.z - goal.Z) * 100 + node.rect.Distance(new Point(goal.X, goal.Y));
 }
Пример #12
0
 public static double Distance(Point3D a, Point3D b)
 {
     // Euclidean distance
     return Math.Sqrt(Math.Pow(a.X - b.X, 2) + Math.Pow(a.Y - b.Y, 2));
 }
Пример #13
0
        public void RedrawRoute()
        {
            Stopwatch sw;

            sw = Stopwatch.StartNew();
            Point3D start = new Point3D(beginx, beginy, beginz);
            Point3D target = new Point3D(endx, endy, endz);
            var res = Pathfinder.FindRoute(start, target, new Bitmap(mapImages[start.Z]));
            DijkstraPoint point = res.Item1;
            var rects = res.Item2;
            sw.Stop();
            Console.WriteLine("Find Route: {0}ms", sw.Elapsed.TotalMilliseconds);

            Bitmap bitmap = new Bitmap(mapImages[beginz]);

            DijkstraPoint tempPoint = point;
            while (point != null) {
                if (point.point.X < mapX) {
                    mapX = point.point.X - 20;
                }
                if (point.point.X > mapX + mapWidth) {
                    mapWidth = point.point.X - mapX + 20;
                }
                if (point.point.Y < mapY) {
                    mapY = point.point.Y - 20;
                }
                if (point.point.Y > mapY + mapHeight) {
                    mapHeight = point.point.Y - mapY + 20;
                }
                point = point.previous;
            }
            point = tempPoint;
            using (Graphics gr = Graphics.FromImage(bitmap)) {
                while (point.previous != null) {
                    gr.DrawLine(Pens.Black, new Point((int)point.point.X, (int)point.point.Y), new Point((int)point.previous.point.X, (int)point.previous.point.Y));
                    point = point.previous;
                }

                foreach (Rectangle3D rect in rects) {
                    gr.DrawRectangle(Pens.Yellow, rect.Rect);
                }
            }
            bigMap = bitmap;
            UpdateMap();
        }
Пример #14
0
 public static double Distance(Node node, Point3D goal)
 {
     return Math.Abs(node.z - goal.Z) * 100 + Distance(node.x, node.y, goal.X, goal.Y);
 }