⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 airrpathfind.cpp

📁 RPG3D演示 国外著名3D引擎 鬼火 这是一个开发团队做的演示 有完整源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "irrlicht.h"
#include "Airrpathfind.h"

// Copyright (C) 2005 Cestmir "CZestmyr" Houska
// This file is using some classes from "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in Irrlicht.h

using namespace irr;

/****************
/   PathNode    /
****************/

// constructor
PathNode::PathNode(core::vector3df& pos)
: position(pos), list(PIL_NONE){}

// returns the distance from another PathNode
u32 PathNode::distance(PathNode* other)
{
    return (u32)(position.getDistanceFrom(other->position));
}

// returns overestimated distance to a PathNode. It is used by the 
// pathfinding algorithm to explore those PathNodes first, that are more
// likely to lead to the goal.
u32 PathNode::Hdist(PathNode* other)
{
    return (u32)(position.getDistanceFrom(other->position) * 1.2f);
}

// adds the other PathNode to the list of the neighbours
void PathNode::setNeighbour(PathNode* other)
{
    neighbours.push_back(other);
}

// removes the other PathNode from the list of the neighbours
void PathNode::removeNeighbour(PathNode* other)
{
    core::list<PathNode*>::Iterator iter = neighbours.begin();

    while (iter != neighbours.end()){
        if (*iter == other) iter = neighbours.erase(iter);
        else iter++;
    }
}

// checks, whether the other PathNode is a neighbour of this node
bool PathNode::isNeighbour(PathNode* other)
{
    core::list<PathNode*>::Iterator iter = neighbours.begin();

    while (iter != neighbours.end()){
        if (*iter == other) return true;
        iter++;
    }
    
    return false;
}

// draws the node with the given driver, using the given color
void PathNode::draw(video::IVideoDriver* driver, video::SColor& color)
{
    video::S3DVertex NodeMeshVertices[4];

    NodeMeshVertices[0] = video::S3DVertex(0,2,0, 0,1,0,color,0,1);
    NodeMeshVertices[1] = video::S3DVertex(2,-2,-2, 1,0,-1,color,0,1);
    NodeMeshVertices[2] = video::S3DVertex(0,-2,2, 0,0,1,color,0,1);
    NodeMeshVertices[3] = video::S3DVertex(-2,-2,-2, -1,0,-1,color,0,1);

    u16 indices[] = { 0,2,3, 2,1,3, 1,0,3, 2,0,1 };

    core::matrix4 translation;

    translation.makeIdentity();
    translation.setTranslation(position);

    driver->setTransform(video::ETS_WORLD, translation);
    driver->drawIndexedTriangleList(&NodeMeshVertices[0], 4, &indices[0], 4);

    core::list<PathNode*>::Iterator iter = neighbours.begin();
    while (iter != neighbours.end()){
        driver->setTransform(video::ETS_WORLD, core::matrix4());
        driver->draw3DLine(position, (*iter)->position, video::SColor(255,255,255,0));
        iter++;
    }
}

/*********
/  path  /
*********/

// constructor
path::path(): core::list<PathNode*>(){}

// Copy constructor
path::path(path& other): core::list<PathNode*>()
{
    clear();
    core::list<PathNode*>::Iterator iter = other.begin();
    while (iter != other.end())
    {
        push_back(*iter);
        iter++;
    }
}

// = operator
path& path::operator=(path& other)
{
    if (&other == this) return *this;
    clear();
    core::list<PathNode*>::Iterator iter = other.begin();
    while (iter != other.end())
    {
        push_back(*iter);
        iter++;
    }
    return *this;
}

// checks, whether the path contains the searched node
bool path::contains(PathNode* searchedNode)
{
    core::list<PathNode*>::Iterator iter = begin();

    while (iter != end()){
        if (*iter == searchedNode) return true;
        iter++;
    }

    return false;
}

/*****************
/     Network    /
*****************/

// constructor
Network::Network(video::IVideoDriver* driv, ITimer* tim, bool createLogFile)
: state(0), log(createLogFile), driver(driv), selectedNode(NULL), startNode(NULL),
endNode(NULL), timer(tim)
{}

// destructor
Network::~Network()
{
    core::list<PathNode*>::Iterator iter = nodes.begin();

    while (iter != nodes.end()){
        delete (*iter);
        iter++;
    }
}

// draws the node, for testing and editiong purposes
void Network::draw()
{
    video::SMaterial material;
    material.Lighting = false;
    video::SColor color;

    core::list<PathNode*>::Iterator iter = nodes.begin();

    while (iter != nodes.end()){
        if (*iter == selectedNode) color = video::SColor(255,0,64,128);
        else if (*iter == startNode || *iter == endNode || pathSegments.contains(*iter))
            color = video::SColor(255,0,128,64);
        else color = video::SColor(255,255,255,128);
        driver->setMaterial(material);
        (*iter)->draw(driver, color);
        iter++;
    }
}

// returns pointer to the node, that is nearest to the given point
PathNode* Network::nearestNodePointer(core::vector3df pos)
{
    u32 dist = 32000;

    core::list<PathNode*>::Iterator ret = nodes.begin();
    core::list<PathNode*>::Iterator iter = nodes.begin();

    while (iter != nodes.end()){
        u32 d = (u32)pos.getDistanceFrom((*iter)->position);
        if (d < dist) {dist = d; ret = iter;}
        iter++;
    }
    return *ret;
}
// adds a node to this network at the given point
void Network::addNode(core::vector3df pos)
{
    PathNode* node = new PathNode(pos);
    nodes.push_back(node);
}

// adds two-way connection between two nodes
void Network::addConnection(PathNode* a, PathNode* b)
{
    if (a == b) return;
    if (connectionExists(a,b)){       //This method not only adds, but also deletes connections
        a->removeNeighbour(b);
        b->removeNeighbour(a);
        return;
    }

    a->setNeighbour(b);
    b->setNeighbour(a);
    return;
}

// adds one-way connection between two nodes
void Network::addOneWayConnection(PathNode* from, PathNode* to)
{
    if (connectionExists(from,to)){       //This method not only adds, but also deletes connections
        from->removeNeighbour(to);
        to->removeNeighbour(from);
        return;
    }

    from->setNeighbour(to);
    return;
}

// removes node from net with all its connections
void Network::removeNodeFromNet(PathNode* a)
{
    core::list<PathNode*>::Iterator iter = nodes.begin();
    core::list<PathNode*>::Iterator toErase;

    while (iter != nodes.end()){
        if (*iter == a) toErase = iter;
        else (*iter)->removeNeighbour(a);
        iter++;
    }

    nodes.erase(toErase);
    delete a;
}

// checks, whether there is any connection between two nodes
bool Network::connectionExists(PathNode* a, PathNode* b)
{
    if (a->isNeighbour(b) || b->isNeighbour(a)) return true;
    else return false;
}

// selects a node for purpose of making a two-way connection
void Network::selectNode(core::vector3df pos)
{
    if (selectedNode == NULL)
    selectedNode = nearestNodePointer(pos);
    else {
        PathNode* helper = nearestNodePointer(pos);
        addConnection(helper, selectedNode);
        selectedNode = NULL;
    }
}

// selects first and then a second node in order to find a path between
// them. Also stores this path to the pathSegments member.
// Returns true in case of success, else returns false
bool Network::findPath(core::vector3df fromOrTo)
{
    if (state == 0) {startNode = nearestNodePointer(fromOrTo); state = 1; return false;}

    // The state flag can now only be 1
    endNode = nearestNodePointer(fromOrTo);

    ofstream soubor;
    u32 timeStats;
    if (log)
    {
        soubor.open("log.txt");
        timeStats = timer->getTime();
        soubor << "Node Number: " << nodes.getSize() << ::endl;
        soubor << "Starting pathfinding..." << ::endl;
        soubor << "Reseting open and closed lists..." << ::endl;
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -