1

所以我一直在玩 Pygame 并遇到了一个我可以解决的问题,但只是不够优雅。

基本上我有一个单位(此时只是一个红色方块)在一个黑色的平原上。如果我单击该单元,然后单击该字段上的任何其他位置,则该单元将继续到该点。该算法本身工作得非常完美,即使引入了障碍物,它也能快速处理寻路。

我的问题在于我的实施。单位是一个 16 x 16 的方格,因此该场被划分为 16 x 16 方格。如果我在运输途中更改单位的目的地,它有时会“回溯”到先前的“航路点”,然后再继续其新路线。

我明白为什么会发生这种情况,路径查找模块将每个正方形视为网格上的一个点,因此当我将鼠标坐标传递给路径方法时,点 (2,2) 的像素坐标实际上是 (32,32)我将它们除以 16 得到向下取整的整数(因此 (34,37) 变为 (2,2)),因此虽然单位可能在实际的“网格点”之间,但路径查找模块从其最后一个实际路径点找到路径,不是它的当前位置。当它通过新路线到单元时,单元必须“回溯”以跟随寻路模块找到的路线

显然每个进行任何类型寻路的游戏开发者都解决了这个问题,所以我希望我能找到一个更优雅的解决方案。我不想在屏幕上的每个像素上找到一条路径,只是航路点,但是回溯有点烦人。有什么建议么?

如下所示是相关代码:

在主 .py 文件中

if pygame.mouse.get_pressed()[0]: # if left mouse button pressed
    mouse_x,mouse_y = pygame.mouse.get_pos()
    if selected: # checks if a unit is selected
        unit.getRoute((mouse_x/16,mouse_y/16))

在 unit.py 文件中

def getRoute(self,target):
    self.route = path((self.x/16,self.y/16), target)

def getNode(self):
    if self.route:
        self.node = route.pop(0)
        dif_x,dif_y = self.node[0] - self.x, self.node[1] - self.y
        if dif_x > 0:
            self.vector_x = self.speed
        if dif_x < 0:
            self.vector_x = self.speed * -1
        else:
            self.vector_x = 0
        if dif_y > 0:
            self.vector_y = self.speed
        if dif_x < 0:
            self.vector_y = self.speed * -1
        else:
            self.vector_y = 0
    else:
        self.node = None
        self.vector_x = 0
        self.vector_y = 0

def update(self):

    if self.route or self.node:
        if self.route and not self.node:
            self.getNode()
        if (self.x,self.y) == self.node:
            self.getNode()

    self.x += self.vector_x
    self.y += self.vector_y
    self.rect.topleft = (self.x,self.y)
4

1 回答 1

1

您应该以一种特殊的方式来管理这第一步。这是因为即使该单元已经在移动它指定的单元格,它仍然保持不变,直到它到达下一个单元格。

现在我建议您确保在移动完成一半后立即更新单元的单元格(这样探路者将搜索下一个单元格的路径,而不是前一个单元格的路径)。此外,您应该使用类似的东西来管理特殊情况

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)

当然,这将根据您的运动自由度而变得更容易或更难,如果您只允许正交运动,这将是简单的,如果您允许对角线运动,那么您应该注意不要越过障碍物(这取决于关于您希望对小故障有多大的容忍度,例如单元与障碍物的一角重叠)。

于 2012-06-16T01:09:34.107 回答