使用 A* 实现寻路的类似口吃的运动

发布于 2025-01-18 17:27:46 字数 2865 浏览 4 评论 0原文

我正在尝试开发一个基本的 RTS 游戏,并且使用 A* 库的寻路工作正常。然而,当发出新的目标位置时,该实现会导致角色精灵口吃或向后“传送”一点。

当短时间内连续发出呼叫时,这会变成一个大问题。

我使用的方法是 main 循环将鼠标坐标输入到 User 类和 create_path() 方法中。创建路径使用一个名为“pathfinding”的 A* 库来使用矩阵生成路径坐标列表。

然后方法create_collision_rects()在每个路径节点坐标的中心创建小矩形对象。

然后,方法create_direction() 创建一个从Unit 对象到寻路矩形 的第一个实例的向量。

每一帧都会运行 path_collisions() 方法来检查用户是否与系列中的第一个 rect 发生碰撞。如果是这样,请删除 rect[0]path[0] 并再次运行 create_direction()

因此寻路工作如所描述的那样,但是正如前面提到的,最大的问题是当生成新路径时,Unit 对象会向后卡顿。当需要在短时间内连续改变路径时,这是一个大问题。

我已经考虑这个问题很长一段时间了,但还没有找到任何解决方案。任何帮助将不胜感激!

Code

在用户发出寻路命令时运行一次(例如,单击屏幕):

    #-----Create pathfinding-----
    def create_path(self, mouse_x, mouse_y):
        
            start_x, start_y = self.get_coord()
            start = self.grid.node(start_x, start_y)
            
            end_x, end_y = abs(mouse_x) // tile_size, abs(mouse_y) // tile_size
            end = self.grid.node(end_x,end_y) 

            self.path,_ = self.finder.find_path(start, end, self.grid)
            self.grid.cleanup()

            self.create_collision_rects()

create_path() 之后运行一次

    #-----Create collision rects-----
    def create_collision_rects(self):        
        self.collision_rects = []

        for point in self.path:
            x = ((point[0] * tile_size) + tile_size//2)
            y = ((point[1] * tile_size) + tile_size//2)

            rect = pygame.Rect(((x - 4), (y - 4)), (8, 8))
            self.collision_rects.append(rect)

        self.get_direction()

create_collision_rects() 之后运行一次>

    #-----Create vector-----
    def get_direction(self):
        if self.collision_rects:
            start = pygame.math.Vector2(self.pos)
            end = pygame.math.Vector2(self.collision_rects[0].center)

            if start != end:
                self.direction = (end - start).normalize()
                
        else:
            self.direction = pygame.math.Vector2(0,0)
            self.path = []

运行 Unit 类的 update() 方法中的每一帧

    #-----Check path collisions-----
    def path_collisions(self):
        if self.collision_rects:
            if self.collision_rects[0].collidepoint(self.pos):

                self.pos = self.collision_rects[0].center
                self.collision_rects.pop(0)
                self.path.pop(0)

                self.get_direction()
        else:
            self.path = []

I'm trying to develop a rudimentary RTS game and the pathfinding using a A* library is working fine. However the implementation is causing the character sprite to stutter or to get "teleported" backwards a bit when issued a new target location to path towards.

This turns into a big issue when issued continous calls during a short time.

The method I use is the main-loop feeds mouse-coordinates into the User-class and the create_path()-method. The create path uses an A* library called simply "pathfinding" to generate a list of path coordinates using a matrix.

Then the method create_collision_rects() creates small rect objects at the center of the coordinates of each path node.

Then the method create_direction() creates a vector from the Unit-object to the first instance of the pathfinding rects.

Every frame the method path_collisions() is run to check if the user has collided with the first rectin the series. If so remove rect[0] and path[0] and run create_direction() again.

So the pathfinding works as described, however as mentioned the big problem is that the Unit-object stutters backward when a new path is generated. This is a big problem when the path needs to be changed continously during a short time.

I've thought about this for quite some time now and haven't found any solution. Any help would be much appreciated!

Code

Runs once on user issuing a pathfinding command (eg. clicks on the screen):

    #-----Create pathfinding-----
    def create_path(self, mouse_x, mouse_y):
        
            start_x, start_y = self.get_coord()
            start = self.grid.node(start_x, start_y)
            
            end_x, end_y = abs(mouse_x) // tile_size, abs(mouse_y) // tile_size
            end = self.grid.node(end_x,end_y) 

            self.path,_ = self.finder.find_path(start, end, self.grid)
            self.grid.cleanup()

            self.create_collision_rects()

Runs once after create_path()

    #-----Create collision rects-----
    def create_collision_rects(self):        
        self.collision_rects = []

        for point in self.path:
            x = ((point[0] * tile_size) + tile_size//2)
            y = ((point[1] * tile_size) + tile_size//2)

            rect = pygame.Rect(((x - 4), (y - 4)), (8, 8))
            self.collision_rects.append(rect)

        self.get_direction()

Runs once after create_collision_rects()

    #-----Create vector-----
    def get_direction(self):
        if self.collision_rects:
            start = pygame.math.Vector2(self.pos)
            end = pygame.math.Vector2(self.collision_rects[0].center)

            if start != end:
                self.direction = (end - start).normalize()
                
        else:
            self.direction = pygame.math.Vector2(0,0)
            self.path = []

Runs every frame in the Unit-class' update()-method

    #-----Check path collisions-----
    def path_collisions(self):
        if self.collision_rects:
            if self.collision_rects[0].collidepoint(self.pos):

                self.pos = self.collision_rects[0].center
                self.collision_rects.pop(0)
                self.path.pop(0)

                self.get_direction()
        else:
            self.path = []

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

℡Ms空城旧梦 2025-01-25 17:27:46

我在另一个线程中找到了一个答案,以回答此问题,以便其他任何正在搜索的人都可以找到它:

用pygame实现A*算法,我找到了我的单元“ back-tracks”

if unit is standing still
  compute pathfinding as you would normally do
else
  compute pathfinding from the unit cell
  discard the first cell of the pathfinding route (since it would backtrack)
  compute the route directly to the next cell (by drawing a correct path)

I found an answer in another thread, answering this so that anyone else searching may find it:

Implementing an A* algorithm with pygame I find my unit "back-tracks"

if unit is standing still
  compute pathfinding as you would normally do
else
  compute pathfinding from the unit cell
  discard the first cell of the pathfinding route (since it would backtrack)
  compute the route directly to the next cell (by drawing a correct path)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文