C++ 如何在C+中使用*追溯路径+;?

C++ 如何在C+中使用*追溯路径+;?,c++,sfml,path-finding,a-star,C++,Sfml,Path Finding,A Star,几周来,我一直在尝试实现一个*以便敌人可以在我的游戏中追逐玩家,但我无法让它工作。我整个周末都在写这本书,我甚至把它的大部分都刮下来重新写了一遍。我可以画一条从起始位置到目标的路径,但我不能追溯它,就像写下路径一样。我使用的是来自SFML的Vector2f(有序浮点数对)和Sprite,但是那里的所有代码都非常简单,所以您不需要真正理解它 编辑:问题在于Node.cameFrom。出于某种原因,它除了墙壁什么也不能做 这是Node.h #ifndef NODE_H #define NODE_H

几周来,我一直在尝试实现一个*以便敌人可以在我的游戏中追逐玩家,但我无法让它工作。我整个周末都在写这本书,我甚至把它的大部分都刮下来重新写了一遍。我可以画一条从起始位置到目标的路径,但我不能追溯它,就像写下路径一样。我使用的是来自SFML的Vector2f(有序浮点数对)和Sprite,但是那里的所有代码都非常简单,所以您不需要真正理解它

编辑:问题在于Node.cameFrom。出于某种原因,它除了墙壁什么也不能做

这是Node.h

#ifndef NODE_H
#define NODE_H
#include <SFML/Graphics.hpp>

using namespace sf;

class Node {
    public:
        Vector2f pos;
        // Distance traveled already to reach node
        int level;
        // Level + estimated dist to goal
        int priority;

        Node *cameFrom;

        Node(Vector2f npos, int lv, Vector2f dest, Node *cf=nullptr);

        bool operator == (const Node &nhs) const {
            return nhs.priority == priority;
        }

};

#endif // NODE_H
\ifndef节点
#定义节点
#包括
使用名称空间sf;
类节点{
公众:
矢量2f位置;
//已到达节点的距离
智力水平;
//级别+估计距离目标
int优先级;
节点*来自;
节点(Vector2f npos、int lv、Vector2f dest、Node*cf=nullptr);
布尔运算符==(常量节点和nhs)常量{
返回nhs.priority==优先级;
}
};
#endif//NODE_H
Node.cpp

#include "Node.h"
#include <SFML/Graphics.hpp>
#include <math.h>
#include <iostream>

using namespace std;
using namespace sf;

int estimatedDist(Vector2f pos, Vector2f dest) {
    return abs(dest.x - pos.x) + abs(dest.y - pos.y);
}

Node::Node(Vector2f npos, int lv, Vector2f dest, Node *cf) {
    cameFrom = cf;
    level = lv;
    pos = npos;
    priority = level + estimatedDist(pos, dest);
}
#包括“Node.h”
#包括
#包括
#包括
使用名称空间std;
使用名称空间sf;
int估算数据表(矢量2F位置,矢量2F目的地){
返回abs(目标x-位置x)+abs(目标y-位置y);
}
Node::Node(Vector2f npos、int lv、Vector2f dest、Node*cf){
cameFrom=cf;
电平=低压;
pos=非营利组织;
优先级=级别+估计数据(pos、dest);
}
.cpp路径查找函数

bool occupies(Vector2f pos, vector<Wall> walls) {
    for (unsigned w = 0; w < walls.size(); w++) {
        if (walls.at(w).collisionBox.getGlobalBounds().contains(pos.x * 32, pos.y * 32)) {
            return true;
        }
    }
    return false;
}

bool nFind(Node n, vector<Node> nodes) {
    for (unsigned i = 0; i < nodes.size(); i++) {
        if (nodes.at(i).pos == n.pos) {
            return true;
        }
    }
    return false;
}

void Enemy::pathFind(Vector2f dest, vector<Wall> walls) {
    char fullMap[32][22];
    vector<Node> openSet;
    vector<Node> closedSet;
    int xStart, yStart;
    for (unsigned y = 0; y < 22; y++) {
        for (unsigned x = 0; x < 32; x++) {
            if (sprite.getGlobalBounds().top >= y * 32 && sprite.getGlobalBounds().top <= (y + 1) * 32) {
                if (sprite.getGlobalBounds().left >= x * 32 && sprite.getGlobalBounds().left <= (x + 1) * 32) {
                    xStart = x;
                    yStart = y;
                }
            } if (occupies(Vector2f(x, y), walls)) {
                fullMap[x][y] = '2';
            } else {
                fullMap[x][y] = ' ';
            }
        }
    }
    fullMap[int(dest.x)][int(dest.y)] = 'D';
    Node *current = new Node(Vector2f(xStart, yStart), 0, dest);
    fullMap[int(current->pos.x)][int(current->pos.y)] = '2';
    openSet.push_back(*current);

    while (openSet.size() > 0) {
        sort(openSet.begin(), openSet.end(), sortByPriority());
        *current = openSet.front();

        if (current->pos == dest) {
            cout << "We gots it ";
            for (unsigned y = 0; y < 22; y++) {
                for (unsigned x = 0; x < 32; x++) {
                    if (occupies(Vector2f(x, y), walls)) {
                        fullMap[x][y] = '2';
                    } else {
                        fullMap[x][y] = ' ';
                    }
                }
            }
            while (current->cameFrom) {
                fullMap[int(current->pos.x)][int(current->pos.y)] = 'P';
                current = current->cameFrom;
                for (unsigned y = 0; y < 22; y++) {
                    for (unsigned x = 0; x < 32; x++) {
                        cout << fullMap[x][y];
                    }
                    cout << endl;
                }
                cout << endl;
            } for (unsigned y = 0; y < 22; y++) {
                for (unsigned x = 0; x < 32; x++) {
                    cout << fullMap[x][y];
                }
                cout << endl;
            }
            cout << endl;
            return;
        }

        openSet.erase(remove(openSet.begin(), openSet.end(), *current), openSet.end());
        closedSet.push_back(*current);
        fullMap[int(current->pos.x)][int(current->pos.y)] = '2';

        vector<Node> neighbors;

        neighbors.push_back(Node(Vector2f(current->pos.x - 1, current->pos.y - 1), current->level + 1, dest));
        neighbors.push_back(Node(Vector2f(current->pos.x, current->pos.y - 1), current->level + 1, dest));
        neighbors.push_back(Node(Vector2f(current->pos.x + 1, current->pos.y - 1), current->level + 1, dest));
        neighbors.push_back(Node(Vector2f(current->pos.x + 1, current->pos.y), current->level + 1, dest));
        neighbors.push_back(Node(Vector2f(current->pos.x + 1, current->pos.y + 1), current->level + 1, dest));
        neighbors.push_back(Node(Vector2f(current->pos.x, current->pos.y + 1), current->level + 1, dest));
        neighbors.push_back(Node(Vector2f(current->pos.x - 1, current->pos.y + 1), current->level + 1, dest));
        neighbors.push_back(Node(Vector2f(current->pos.x - 1, current->pos.y), current->level + 1, dest));

        for (unsigned i = 0; i < neighbors.size(); i++) {
            if (nFind(neighbors.at(i), closedSet) ||
                neighbors.at(i).pos.x > 22 ||
                neighbors.at(i).pos.y > 32 ||
                neighbors.at(i).pos.x < 0 ||
                neighbors.at(i).pos.y < 0 ||
                occupies(neighbors.at(i).pos, walls)) {

                continue;
            } if (!nFind(neighbors.at(i), openSet)) {
                openSet.push_back(neighbors.at(i));
            }
            neighbors.at(i).cameFrom = current;
        }
    }
}
bool占据(矢量2F位置,矢量墙){
对于(无符号w=0;w=y*32&&sprite.getGlobalBounds().top=x*32&&sprite.getGlobalBounds().left pos.x)][int(current->pos.y)]=2';
openSet.push_back(*当前);
while(openSet.size()>0){
排序(openSet.begin()、openSet.end()、sortByPriority());
*当前=openSet.front();
如果(当前->位置==目的地){
(来源){
全图[int(当前->位置x)][int(当前->位置y)]='P';
当前=当前->来自;
for(无符号y=0;y<22;y++){
for(无符号x=0;x<32;x++){
cout pos.x,current->pos.y-1),current->level+1,dest);
推回(节点(向量2F(当前->位置x+1,当前->位置y-1),当前->级别+1,目标));
推回(节点(向量2F(当前->位置x+1,当前->位置y),当前->级别+1,目标));
推回(节点(向量2F(当前->位置x+1,当前->位置y+1),当前->级别+1,目标));
推回(节点(向量2F(当前->位置x,当前->位置y+1),当前->级别+1,目标));
推回(节点(向量2F(当前->位置x-1,当前->位置y+1),当前->级别+1,目标));
推回(节点(向量2F(当前->位置x-1,当前->位置y),当前->级别+1,目标));
for(无符号i=0;i22||
邻居。在(i)位置y>32||
在(i)处,位置x<0||
在(i)位置y<0||
占用(位于(i)位置的邻居,墙壁){
继续;
}if(!nFind(邻居.at(i),openSet)){
openSet.push_back(邻域.at(i));
}
邻居.at(i).cameFrom=当前;
}
}
}

对于每个磁贴,您需要它的成本(到达那里的成本加上启发式),以及您到达它的相邻磁贴的标识


该算法在起点周围有一个由点组成的“气球”,首先分析最佳点。因此,如果路径很简单,气球就会很长。如果路径是卷曲的,气球就会很圆,许多路径会被墙包围而放弃,因为它们已经被瓷砖包围。

对于每一块瓷砖,您都需要它的成本(到达目的地的成本加上启发式),以及您到达目的地的相邻瓷砖的标识


该算法在起点周围有一个由点组成的“气球”,首先分析最佳点。因此,如果路径很简单,气球就会很长。如果路径是卷曲的,气球就会很圆,许多路径会因为被墙壁包围和已经访问过的瓷砖而被放弃。

MCVE将有助于在我们这方面进行尝试(见zett42评论)

因此,通过快速查看,我可以为您提供一些在调试过程中查找的指针,但没有明确的答案

这些线看起来非常可疑:

Node *current = new Node(Vector2f(xStart, yStart), 0, dest);
// ^ no delete in source, will leak memory

*current = openSet.front();
// will overwrite the heap memory with copy constructor
// but the pointer will remain the same
// so all of your nodes will always have "cameFrom"
// pointing to this same memory.
总的来说,这段代码看起来有点复杂。你有固定正方形32x22瓷砖的游戏吗?为什么是“墙”向量

我将只维护单个全局平铺贴图作为级别(但是A*搜索不应该损坏它,而是创建它自己的副本进行搜索,或者创建新的贴图以达到成本,这可能会大大简化代码)

xStart,yStart
可以直接计算,无需每次循环迭代:

xStart = int(sprite.getGlobalBounds().left)>>5;  // left/32
yStart = int(sprite.getGlobalBounds().top)>>5;   // top/32
bool操作符==(const Node&nhs)const
看起来不健康,但它甚至没有在任何地方使用

若要查看邻居是否在墙中,您不需要使用O(N)
占位符
,只需测试地图的
==“2”
?(我的意思是如果
...
P#D
...