Skip to content

Commit

Permalink
astar
Browse files Browse the repository at this point in the history
  • Loading branch information
booirror committed Mar 7, 2016
1 parent e9f8bc8 commit 5a7af12
Show file tree
Hide file tree
Showing 2 changed files with 296 additions and 0 deletions.
216 changes: 216 additions & 0 deletions algorithm/AstarLayer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
#include "AstarLayer.h"

using namespace cocos2d;

static AStar* _instance = nullptr;

ANode* ANode::create()
{
ANode* node = new ANode();
if (node && node->init()) {
node->autorelease();
return node;
}
else {
CC_SAFE_DELETE(node);
return nullptr;
}
}

bool ANode::init()
{
if (!Node::init()) {
return false;
}
drawNode = DrawNode::create();
setType(Type::kNormal);
this->addChild(drawNode);
this->setContentSize(Size(aWidth, aWidth));
this->setAnchorPoint(Vec2(0.5, 0.5));
return true;
}

bool ANode::setType(Type type)
{
Color4F color;
switch (type)
{
case ANode::Type::kNormal:
color = Color4F::MAGENTA;
break;
case ANode::Type::kWall:
color = Color4F(0x8b/255.0f, 0x57/255.0f, 0x42/255.0f, 1);
break;
case ANode::Type::kSrc:
color = Color4F(0x41/255.0f, 0x69/255.0f, 0xE1/255.0f, 0.8);
break;
case ANode::Type::kDst:
color = color = Color4F(0x22 / 255.0f, 0x8B / 255.0f, 0x22 / 255.0f, 0.8);
break;
case ANode::Type::kAddOpen:
color = Color4F::BLUE;
break;
case ANode::Type::kAddClose:
color = Color4F(0xF0/255.0f, 0x80/255.0f, 0x80/255.0f, 1);
break;
default:
color = Color4F::MAGENTA;
break;
}
drawNode->clear();
drawNode->drawSolidRect(Vec2(0, 0), Vec2(aWidth, aWidth), color);
drawNode->drawRect(Vec2(0, 0), Vec2(aWidth, aWidth), Color4F::ORANGE);
return true;
}

/////////////////////////////////////////////////

void AstarNode::calcValue(AstarNode* dst)
{
int v = abs(parent->row - row) + abs(parent->col - col);
if (v == 1) {
gValue = parent->gValue + 10;
}
else {
gValue = parent->gValue + 14;
}
hValue = abs(dst->col - col) + abs(dst->row - row);
}

////////////////////////////////////////////////

Scene* AstarLayer::createScene()
{
Scene* scene = Scene::create();
AstarLayer* layer = AstarLayer::create();
scene->addChild(layer);
return scene;
}

AstarLayer* AstarLayer::create()
{
AstarLayer* layer = new (std::nothrow) AstarLayer();
if (layer && layer->init()) {
layer->autorelease();
return layer;
}
else {
delete layer;
layer = nullptr;
return nullptr;
}
}

bool AstarLayer::init()
{
if (!Layer::init()) {
return false;
}
auto winSize = Director::getInstance()->getVisibleSize();

auto bgLayer = LayerColor::create(Color4B(0x12, 0x12, 0x12, 0xff));
bgLayer->setPosition(Vec2(0, 0));
this->addChild(bgLayer);
ANode* temp = ANode::create();
float startx = (winSize.width - maxcol * temp->getContentSize().width)/2;
float starty = (winSize.height - maxrow * temp->getContentSize().height) / 2;
auto nsize = temp->getContentSize();
for (int i = 0; i < maxcol; i++) {
for (int j = 0; j < maxrow; j++) {
auto node = ANode::create();
node->setPosition(startx + (i+0.5)*nsize.width, starty + (j+0.5)*nsize.height);
this->addChild(node);
mNodes[j][i] = node;
}
}

src = AstarNode(10, 3);
dst = AstarNode(3, 21);

mNodes[src.row][src.col]->setType(ANode::Type::kSrc);
mNodes[dst.row][dst.col]->setType(ANode::Type::kDst);

for (int row = 4; row < maxrow; row++) {
mNodes[row][5]->setType(ANode::Type::kWall);
}

for (int row = 3; row < maxrow-3; row++) {
mNodes[row][10]->setType(ANode::Type::kWall);
}

for (int row = 0; row < maxrow - 4; row++) {
mNodes[row][18]->setType(ANode::Type::kWall);
}

return true;
}
////////////////////////////

AStar* AStar::getInstance()
{
if (_instance == nullptr) {
_instance = new AStar();
}
return _instance;
}

void AStar::init(AstarNode(&astarNodes)[maxrow][maxcol], AstarLayer* astar)
{
std::swap(nodes, astarNodes);
layer = astar;
}

bool AStar::find(AstarNode src, AstarNode dst, std::vector<AstarNode*> &list)
{
std::vector<AstarNode*> queue;

memset(openlist, 0, sizeof(openlist));
memset(closelist, 0, sizeof(closelist));

queue.push_back(&nodes[src.row][src.col]);

while (!queue.empty()) {
auto it = queue.begin();
for (auto iter = queue.begin(); iter != queue.end(); iter++) {
if ((*it)->getFValue() > (*iter)->getFValue()) {
it = iter;
}
}
auto node = *it;
queue.erase(it);
closelist[node->row*maxcol + node->col] = true;

int row = node->row + 1;
int col = node->col;

if (isValid(row, col) && !isUnwalkable(row, col)) {
if (openlist[row*maxcol + col]) {
if (nodes[row][col].gValue > node->gValue + 10)
{
nodes[row][col].parent = node;
nodes[row][col].calcValue(&dst);
}
}
else {
nodes[row][col].parent = node;
nodes[row][col].calcValue(&dst);
queue.push_back(&nodes[row][col]);
}
}
}

return true;
}

bool AStar::isUnwalkable(int row, int col)
{
return layer->getNode(row, col)->getType == ANode::Type::kWall;
}

bool AStar::isValid(int row, int col)
{
if (row >= 0 && row < maxrow && col >= 0 && col < maxcol) {
return !closelist[row * maxcol + col];
}
return false;
}
80 changes: 80 additions & 0 deletions algorithm/AstarLayer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#ifndef _ASTAR_LAYER_H_
#define _ASTAR_LAYER_H_
#include "cocos2d.h"

class ANode : public cocos2d::Node {
public:
enum class Type {
kNormal,
kWall,
kSrc,
kDst,
kAddOpen,
kAddClose,
};
static ANode* create();
virtual bool init() override;
bool setType(Type type);
Type getType() { return aType; }
private:
cocos2d::DrawNode *drawNode;
Type aType;
int aWidth = 40;
};

struct AstarNode {
AstarNode* parent;
int hValue;
int gValue;
int row;
int col;

int getFValue() { return hValue + gValue; }
void calcValue(AstarNode* dst);

AstarNode() :AstarNode(0, 0) {

}
AstarNode(int r, int c) :
row(r), col(c), parent(nullptr), hValue(0), gValue(0)
{

}
};

const int maxrow = 15;
const int maxcol = 23;

class AstarLayer : public cocos2d::Layer {
public:

static AstarLayer* create();
static cocos2d::Scene* createScene();
virtual bool init() override;

ANode* getNode(int row, int col) { return mNodes[row][col]; }
private:
ANode* mNodes[maxrow][maxcol];
AstarNode src;
AstarNode dst;

};

class AStar {
public:
static AStar* getInstance();

bool find(AstarNode src, AstarNode dst, std::vector<AstarNode*> &list);

void init(AstarNode (&astarNodes)[maxrow][maxcol], AstarLayer* astarLayer);

private:
bool isValid(int row, int col);
bool isUnwalkable(int row, int col);
AstarLayer* layer = nullptr;
AstarNode nodes[maxrow][maxcol];
bool openlist[maxrow*maxcol];
bool closelist[maxrow*maxcol];
};

#endif

0 comments on commit 5a7af12

Please sign in to comment.