C ++ - 寻路角落问题

时间:2015-01-26 23:00:45

标签: c++ path-finding

所以我试图让角色在瓷砖地图上走动,使用下面的代码。 tilePath返回其目标路径中的tile矢量,然后它们的代码使它们前进到矢量中的下一个tile。问题是,当他们到达一个角落时,他们会试图过早地移动它并最终卡在墙上。

白色方块是可步行的方块,灰色是墙,红色是字符。如果角色到达角落可行走的瓷砖,它会过早地绕墙移动,从而被它阻挡。它们通常会最终制作它,但非常明显的是它们已经卡在墙上了一段时间。

std::vector<Tile*> TileMap::tilePath(Tile *p_start, Tile *p_end)
{
    std::vector<Tile*> path;
    std::vector<Tile*> open;
    std::map<uint64_t, Tile*> closed;

    p_start->previousTile = p_start;

    p_start->g = 0;
    p_start->h = 0;
    p_start->f = 0;

    float g, h, f, cost;

    Tile* current = p_start;
    Tile* previous = nullptr;
    while(current != p_end) {
        current->m_sprite.setColor(sf::Color(255,255,255,255));
        for(auto neighbor : getNeighbors(current))
        {
            if(neighbor == current) continue;
            if(!(neighbor->m_walkable)) continue;

            previous = current;

            if(tileTrace(current->previousTile, neighbor)) {
                cost = manhattan(current->previousTile, neighbor);
                g = current->previousTile->g + cost;
                h = manhattan(neighbor, p_end);
                f = g + h;
                previous = current->previousTile;
            } else {
                cost = ((current->m_coordinates.x != neighbor->m_coordinates.x) && (current->m_coordinates.y != neighbor->m_coordinates.y)) ? 1.4 : 1;
                g = current->g + cost;
                h = manhattan(neighbor, p_end);
                f = g + h;
            }

            if(std::find(open.begin(), open.end(), neighbor) != open.end() ||
               closed.find(neighbor->key()) != closed.end()) {
                if(neighbor->f > f) {
                    neighbor->f = f;
                    neighbor->g = g;
                    neighbor->h = h;
                    neighbor->previousTile = previous;
                }
            } else {
                neighbor->f = f;
                neighbor->g = g;
                neighbor->h = h;
                neighbor->previousTile = previous;
                for(auto i = open.begin(); i != open.end(); i++)
                {
                    if(neighbor->f < (*i)->f) {
                        open.insert(i, neighbor);
                        break;
                    }
                }
                open.push_back(neighbor);
            }
        }

        closed[current->key()] = current;
        if(open.size() == 0) {
            return std::vector<Tile*>();
        }
        current = open.front();
        open.erase(open.begin());
    }
    current = p_end;
    path.insert(path.begin(), current);
    while(current->previousTile != p_start)
    {
        current->m_sprite.setColor(sf::Color(255,0,0,255));
        path.insert(path.begin(), current->previousTile);
        current = current->previousTile;
    }

    return path;
}

bool TileMap::tileTrace(Tile* p_start, Tile* p_end)
{
    int sx = p_start->m_coordinates.x;
    int sy = p_start->m_coordinates.y;
    int ex = p_end->m_coordinates.x;
    int ey = p_end->m_coordinates.y;
    int dx = fabsf(ex - sx);
    int dy = fabsf(ey - sy);

    int _x = sx, _y = sy;
    int x_inc = (ex > sx) ? 1 : -1;
    int y_inc = (ey > sy) ? 1 : -1;
    int error = dx - dy;

    for(int n = dx + dy; n > 0; n--) {
        Tile& t = m_tiles[_y * m_width + _x];
        if(!(t.m_walkable)) return false;
        if(error < 0) {
            _y += y_inc;
            error += dx;
        } else {
            _x += x_inc;
            error -= dy;
        }
    }
    return true;
}

我能做些什么才能让它变得更顺畅?我宁愿这些角色也不会从墙上反弹。

更新

我已经添加了这个内容,以查看角色是朝着还是远离它的#34;&#34;在#34;上。认为它在角落周围获得角色更有效,但它有时会产生一些奇怪的动作。

sf::Vector2f d = start->m_position - p_object->m_position;
float dot = p_object->m_velocity.x * d.x + p_object->m_velocity.y * d.y;
if(dot > 0) {
    path.insert(path.begin(), start);
}

0 个答案:

没有答案