此次在之前那篇cocos2dx A* + tiledMap文章中新加了些功能并且调整了结构
拥有的功能:
能避开障碍物,搜寻最优路径
优化了行走的路径,使之平滑行走(之前的是瓦片级的,现在是像素级的,#define PRECISE_SEARCH_PATH 开启精确的路径行走)
添加了人物的骨骼动画(行走和站立)
PathSearchInfo 搜索路径引擎
Player 玩家类
PathSprite 瓦片精灵类
Paddle物体类(桌子,椅子等)
MathLogic 数学逻辑类
- #pragma once
- #include "StaticValue.h"
- #include "PathSprite.h"
- #include "MathLogic.h"
- #include "cocos2d.h"
- #include <functional>
- #include "paddle.h"
- USING_NS_CC;
- class PathSearchInfo:public CCNode//寻路类(主要负责寻路的参数和逻辑)
- {
- public:
- PathSearchInfo(CCTMXTiledMap* tiledMap);
- private:
- int m_playerMoveStep;//人物当前的行程的索引
- std::function<void(CCPoint)> m_moveDone;//移动结束回调
- bool m_isSetMoveDoneCallback;
- std::function<void(vector<PathSprite*>)> m_drawPath;//画线回调 调试用
- bool m_isSetDrawPathCallback;
- std::function<void(CCPoint point,Paddle* selectObj)> m_selectObj;//选中物体回调
- bool m_isSetSelectObjCallback;
- CCTMXTiledMap* m_map;//地图
- CCTMXLayer* m_road;//道路
- CCSize m_mapSize;//地图大小
- CCSize m_tileSize;//地图的块大小
- vector<PathSprite*> m_openList;//开放列表(里面存放相邻节点)
- PathSprite* m_inspectArray[MAP_WIDTH][MAP_HEIGHT];//全部需要检测的点
- vector<PathSprite*> m_pathList;//路径列表
- vector<PathSprite*> m_haveInspectList;//检测过的列表
- PathSprite* m_moveObj;//移动的物体
- bool m_enableMove;//是否能移动
- bool m_isMoving;//是否正在移动
- public:
- CCTMXTiledMap* getMap()
- {
- return m_map;
- }
- void setEnableMove(bool isEnable)
- {
- m_enableMove = isEnable;
- }
- bool getEnableMove()
- {
- return m_enableMove;
- }
- bool getIsMoving()
- {
- return m_isMoving;
- }
- void setMoveDoneCallback(function<void(CCPoint)>& pFunc);//设置回调
- void setDrawPathCallback(function<void(vector<PathSprite*>)>& pFunc);//设置回调
- void setSelectCallback(function<void(CCPoint point,Paddle* selectObj)> &pFunc);//设置回调
- void initMapObject(const char* layerName,const char* objName);////初始化地图里的物体(设置深度,设置物体回调函数)
- CCPoint getMapPositionByWorldPosition(CCPoint point);//根据世界坐标得到地图坐标
- CCPoint getWorldPositionByMapPosition(CCPoint point);//根据地图坐标得到世界坐标
- void pathFunction( CCPoint point,PathSprite* obj );//计算路径函数
- private:
- void calculatePath();//计算路径
- float calculateTwoObjDistance(PathSprite* obj1,PathSprite* obj2);//计算两个物体间的距离
- void inspectTheAdjacentNodes(PathSprite* node,PathSprite* adjacent,PathSprite* endNode);//把相邻的节点放入开放节点中
- PathSprite* getMinPathFormOpenList();//从开放节点中获取F值最小值的点
- PathSprite* getObjFromInspectArray(int x,int y);//根据横纵坐标从检测数组中获取点
- bool removeObjFromOpenList( PathSprite* sprite);//从开放列表中移除对象
- void resetInspectArray();//重置检测列表
- bool detectWhetherCanPassBetweenTwoPoints(CCPoint p1,CCPoint p2);//检测2个位置中是否有障碍物
- void resetObjPosition();//重置玩家位置
- void clearPath();//清除路径
- void moveObj();//移动实现函数
- };
- #include "PathSearchInfo.h"
- PathSearchInfo::PathSearchInfo( CCTMXTiledMap* tiledMap )
- {
- memset(m_inspectArray,NULL,MAP_WIDTH*MAP_HEIGHT*sizeof(PathSprite*));
- m_isSetMoveDoneCallback = false;
- m_isSetDrawPathCallback = false;
- m_isSetSelectObjCallback = false;
- m_enableMove = true;
- m_map = tiledMap;
- m_mapSize = m_map->getMapSize();//获取地图的尺寸 地图单位
- m_tileSize = m_map->getTileSize();//获取瓦片的尺寸 世界单位
- m_road = m_map->layerNamed("road");//行走路径的地图
- for (int j = 0; j < m_mapSize.height; j++) {
- for (int i = 0; i < m_mapSize.width; i++) {
- CCSprite* _sp = m_road->tileAt(CCPoint(i,j));
- if (_sp) {
- PathSprite* _pathSprite = new PathSprite(_sp);
- _pathSprite->m_x = i;
- _pathSprite->m_y = j;
- m_inspectArray[i][j] = _pathSprite;//把地图中所有的点一一对应放入检测列表中
- }
- }
- }
- }
- void PathSearchInfo::setMoveDoneCallback( function<void(CCPoint)>& pFunc )
- {
- m_moveDone = pFunc;
- m_isSetMoveDoneCallback = true;
- }
- void PathSearchInfo::setDrawPathCallback( function<void(vector<PathSprite*>)>& pFunc )
- {
- m_drawPath = pFunc;
- m_isSetDrawPathCallback = true;
- }
- void PathSearchInfo::setSelectCallback( function<void(CCPoint point,Paddle* selectObj)> &pFunc )
- {
- m_selectObj = pFunc;
- m_isSetSelectObjCallback = true;
- }
- void PathSearchInfo::initMapObject( const char* layerName,const char* objName )
- {
- //图片层
- CCTMXLayer* _layer = m_map->layerNamed(layerName);
- if (!_layer)
- {
- return;
- }
- //对象层
- CCTMXObjectGroup* pipeGroup = m_map->objectGroupNamed(objName);
- if (!pipeGroup)
- {
- return;
- }
- //得到所有的对象
- CCArray* _array = pipeGroup->getObjects();
- CCObject *_obj;
- CCARRAY_FOREACH(_array,_obj )
- {
- //得一个
- CCDictionary* _dictionary = (CCDictionary*)_obj;
- //得到属性
- float _x = ((CCString*)_dictionary->objectForKey("x"))->floatValue();//世界单位
- float _y= ((CCString*)_dictionary->objectForKey("y"))->floatValue();
- float _widht = ((CCString*)_dictionary->objectForKey("width"))->floatValue();//世界单位
- float _height = ((CCString*)_dictionary->objectForKey("height"))->floatValue();
- CCString* _terminalX = ((CCString*)_dictionary->objectForKey("terminalX"));//终点x坐标
- CCString* _terminalY = ((CCString*)_dictionary->objectForKey("terminalY"));//终点y坐标
- CCString* _type = ((CCString*)_dictionary->objectForKey("type"));//物体类型
- CCString* _enableSit = ((CCString*)_dictionary->objectForKey("enableSit"));//是否能坐下
- CCString* _enableTouch =(( CCString*)_dictionary->objectForKey("enableTouch"));//是否能触摸
- CCString* _enablePickUp =(( CCString*)_dictionary->objectForKey("enablePickUp"));//是否能触摸
- Paddle* _parent = Paddle::paddleWithContentSize(CCSize(_widht,_height));//创建一个物体类
- //设置物体属性
- if (_terminalX && _terminalY)
- {
- _parent->m_terminal = CCPoint( _terminalX->floatValue(),_terminalY->floatValue());
- if (m_isSetSelectObjCallback)
- {
- _parent->m_selectCallback =m_selectObj;
- }
- }
- else
- {
- _parent->m_terminal = CCPoint(-1,-1);
- }
- _parent->m_type = _type? (OBJTYPE)_type->intValue():NONE_TYPE;
- _parent->m_enableSit = _enableSit? _enableSit->boolValue():false;
- _parent->m_enableTouch = _enableTouch?_enableTouch->boolValue():false;
- if (_enablePickUp)
- {
- _parent->m_enablePickUp = _enablePickUp->boolValue();
- _parent->m_selectCallback =m_selectObj;
- }
- else
- {
- _parent->m_enablePickUp =false;
- }
- //设置物体位置
- CCPoint _offset = CCPoint(_x,_y );//偏移量
- _parent->setPosition(_offset);
- _parent->setAnchorPoint(CCPoint(0,0));
- for (int i = 0; i < _widht/m_tileSize.width; i++)
- {
- for (int j = 0; j < _height/m_tileSize.height; j++)
- {
- CCSprite* _Sprite = _layer->tileAt(CCPoint(_x/m_tileSize.width+i,m_mapSize.height-1-_y/m_tileSize.height-j));
- if (_Sprite)
- {
- _Sprite->retain();
- _Sprite->removeFromParent();
- _Sprite->setPosition(_Sprite->getPosition()-_offset);
- _parent->addChild(_Sprite);
- _Sprite->release();
- #if 0//测试该物体
- CCMoveBy* action = CCMoveBy::create(1,CCPoint(0,50));
- CCMoveBy* actionR = CCMoveBy::create(1,-50));
- CCSequence* seq = CCSequence::create(action,actionR,NULL);
- _Sprite->runAction(CCRepeatForever::create(seq));
- #endif
- }
- }
- }
- //设置对象深度
- if (_parent->m_enablePickUp)
- {
- m_map->addChild(_parent,BASE_ZODER - getWorldPositionByMapPosition(m_mapSize).y );
- }
- else
- {
- m_map->addChild(_parent,BASE_ZODER - _y );
- }
- }
- }
- void PathSearchInfo::pathFunction( CCPoint point,PathSprite* obj )
- {
- if (!m_enableMove)
- {
- return;
- }
- if (point.x <0 || point.y<0)
- {
- return;
- }
- // if (m_moveDone())//判断是否到达目的地
- // {
- // return;
- // }
- //m_moveDone();//判断是否到达目的地
- m_moveObj = obj;
- resetObjPosition();
- clearPath();
- PathSprite*_sp = m_inspectArray[(int)point.x][(int)(point.y)];
- if (_sp) {
- //获取触摸点,设置为终点
- obj->m_endX = _sp->m_x;
- obj->m_endY = _sp->m_y;
- //计算路径
- calculatePath();
- resetInspectArray();
- //移动物体
- moveObj();
- //绘制路径
- if (m_isSetDrawPathCallback)
- {
- m_drawPath(m_pathList);
- }
- }
- }
- void PathSearchInfo::calculatePath()
- {
- #ifdef PRECISE_SEARCH_PATH
- //得到开始点的节点
- PathSprite* _endNode= m_inspectArray[m_moveObj->m_startX][m_moveObj->m_startY];
- //得到结束点的节点
- PathSprite* _startNode = m_inspectArray[m_moveObj->m_endX][m_moveObj->m_endY];
- //因为是开始点 把到起始点的距离设为0,F值也为0
- _startNode->m_costToSource = 0;
- _startNode->m_FValue = 0;
- //把已经检测过的点从检测列表中删除
- m_inspectArray[m_moveObj->m_endX][m_moveObj->m_endY] = NULL;
- //把该点放入已经检测过点的列表中
- m_haveInspectList.push_back(_startNode);
- //然后加入开放列表
- m_openList.push_back(_startNode);
- PathSprite* _node = NULL;
- while (true)
- {
- //得到离起始点最近的点(如果是第一次执行,得到的是起点)
- _node = getMinPathFormOpenList();
- if (!_node)
- {
- //找不到路径
- break;
- }
- //把计算过的点从开放列表中删除
- removeObjFromOpenList( _node);
- int _x = _node->m_x;
- int _y = _node->m_y;
- //
- if (_x ==m_moveObj->m_startX && _y == m_moveObj->m_startY)
- {
- break;
- }
- //检测8个方向的相邻节点是否可以放入开放列表中
- PathSprite* _adjacent = NULL;
- _adjacent = getObjFromInspectArray( _x +1,_y);
- inspectTheAdjacentNodes(_node,_adjacent,_endNode);
- _adjacent = getObjFromInspectArray( _x,_y -1);
- inspectTheAdjacentNodes(_node,_endNode);
- _adjacent = getObjFromInspectArray( _x -1,_y+1);
- inspectTheAdjacentNodes(_node,_endNode);
- _adjacent = getObjFromInspectArray( _x + 1,_y + 1);
- inspectTheAdjacentNodes(_node,_endNode);
- _adjacent = getObjFromInspectArray( _x +1,_y-1);
- inspectTheAdjacentNodes(_node,_y - 1);
- inspectTheAdjacentNodes(_node,_endNode);
- }
- while (_node)
- {
- //把路径点加入到路径列表中
- //m_pathList.insert(m_pathList.begin(),_node);
- m_pathList.push_back(_node);
- _node = _node->m_parent;
- }
- #else
- //得到开始点的节点
- PathSprite* _startNode = m_inspectArray[m_moveObj->m_startX][m_moveObj->m_startY];
- //得到结束点的节点
- PathSprite* _endNode = m_inspectArray[m_moveObj->m_endX][m_moveObj->m_endY];
- //因为是开始点 把到起始点的距离设为0,F值也为0
- _startNode->m_costToSource = 0;
- _startNode->m_FValue = 0;
- //把已经检测过的点从检测列表中删除
- m_inspectArray[m_moveObj->m_startX][m_moveObj->m_startY] = NULL;
- //把该点放入已经检测过点的列表中
- m_haveInspectList.push_back(_startNode);
- //然后加入开放列表
- m_openList.push_back(_startNode);
- PathSprite* _node = NULL;
- while (true)
- {
- //得到离起始点最近的点(如果是第一次执行,得到的是起点)
- _node = getMinPathFormOpenList();
- if (!_node)
- {
- //找不到路径
- break;
- }
- //把计算过的点从开放列表中删除
- removeObjFromOpenList( _node);
- int _x = _node->m_x;
- int _y = _node->m_y;
- //
- if (_x ==m_moveObj->m_endX && _y == m_moveObj->m_endY)
- {
- break;
- }
- //检测8个方向的相邻节点是否可以放入开放列表中
- PathSprite* _adjacent = NULL;
- _adjacent = getObjFromInspectArray( _x +1,_endNode);
- }
- while (_node)
- {
- //把路径点加入到路径列表中
- m_pathList.insert(m_pathList.begin(),_node);
- //m_pathList.push_back(_node);
- _node = _node->m_parent;
- }
- #endif // PRECISE_SEARCH_PATH
- }
- float PathSearchInfo::calculateTwoObjDistance( PathSprite* obj1,PathSprite* obj2 )
- {
- float _x = abs(obj2->m_x - obj1->m_x);
- float _y = abs(obj2->m_y - obj1->m_y);
- return _x + _y;
- }
- void PathSearchInfo::inspectTheAdjacentNodes( PathSprite* node,PathSprite* endNode )
- {
- if (adjacent)
- {
- float _x = abs(endNode->m_x - adjacent->m_x);
- float _y = abs(endNode->m_y - adjacent->m_y);
- float F,G,H1,H2,H3;
- adjacent->m_costToSource = node->m_costToSource + calculateTwoObjDistance(node,adjacent);//获得累计的路程
- G = adjacent->m_costToSource;
- //三种算法,感觉H2不错
- H1 = _x + _y;
- H2 = hypot(_x,_y);
- H3 = max(_x,_y);
- #if 1 //A*算法 = Dijkstra算法 + 最佳优先搜索
- F = G + H1;
- #endif
- #if 0//Dijkstra算法
- F = G;
- #endif
- #if 0//最佳优先搜索
- F = H2;
- #endif
- adjacent->m_FValue = F;
- adjacent->m_parent = node;//设置父节点
- adjacent->m_sprite->setColor(ccORANGE);//搜寻过的节点设为橘色(测试用)
- m_haveInspectList.push_back(adjacent);
- node->m_child = adjacent;//设置子节点
- PathSearchInfo::m_inspectArray[adjacent->m_x][adjacent->m_y] = NULL;//把检测过的点从检测列表中删除
- PathSearchInfo::m_openList.push_back(adjacent);//加入开放列表
- }
- }
- PathSprite* PathSearchInfo::getMinPathFormOpenList()
- {
- if (m_openList.size()>0) {
- PathSprite* _sp =* m_openList.begin();
- for (vector<PathSprite*>::iterator iter = m_openList.begin(); iter != m_openList.end(); iter++)
- {
- if ((*iter)->m_FValue < _sp->m_FValue)
- {
- _sp = *iter;
- }
- }
- return _sp;
- }
- else
- {
- return NULL;
- }
- }
- PathSprite* PathSearchInfo::getObjFromInspectArray( int x,int y )
- {
- if (x >=0 && y >=0 && x < m_mapSize.width && y < m_mapSize.height) {
- return m_inspectArray[x][y];
- }
- return NULL;
- }
- bool PathSearchInfo::removeObjFromOpenList( PathSprite* sprite )
- {
- if (!sprite) {
- return false;
- }
- for (vector<PathSprite*>::iterator iter = m_openList.begin(); iter != m_openList.end(); iter++)
- {
- if (*iter == sprite)
- {
- m_openList.erase(iter);
- return true;
- }
- }
- return false;
- }
- cocos2d::CCPoint PathSearchInfo::getMapPositionByWorldPosition( CCPoint point )
- {
- return CCPoint((int)(point.x/PathSearchInfo::m_tileSize.width),(int)(PathSearchInfo::m_mapSize.height - point.y/PathSearchInfo::m_tileSize.height) );
- }
- cocos2d::CCPoint PathSearchInfo::getWorldPositionByMapPosition( CCPoint point )
- {
- return CCPoint(PathSearchInfo::m_tileSize.width * point.x,(PathSearchInfo::m_mapSize.height + point.y)*PathSearchInfo::m_tileSize.height);
- }
- void PathSearchInfo::resetInspectArray()
- {
- for (vector<PathSprite*>::iterator iter = m_haveInspectList.begin(); iter != m_haveInspectList.end(); iter++)
- {
- //(*iter)->m_sprite->setColor(ccWHITE);
- (*iter)->m_costToSource = 0;
- (*iter)->m_FValue = 0;
- (*iter)->m_parent = NULL;
- (*iter)->m_child = NULL;
- m_inspectArray[(*iter)->m_x][(*iter)->m_y] = (*iter);
- }
- }
- bool PathSearchInfo::detectWhetherCanPassBetweenTwoPoints( CCPoint p1,CCPoint p2 )
- {
- float _maxX = p1.x>p2.x?p1.x:p2.x;
- float _maxY = p1.y>p2.y?p1.y:p2.y;
- float _minX = p1.x<p2.x?p1.x:p2.x;
- float _minY = p1.y<p2.y?p1.y:p2.y;
- if (p1.x == p2.x)
- {
- if (_maxY - _minY >1)
- {
- return false;
- }
- float _x = p1.x;
- for (int _y = _minY; _y <=_maxY; _y++)
- {
- PathSprite*_sp = m_inspectArray[(int)_x][(int)(_y)];
- if (!_sp)
- {
- return false;
- }
- }
- }
- else if (p1.y == p2.y)
- {
- if (_maxX - _minX > 1)
- {
- return false;
- }
- float _y = p1.y;
- for (int _x = _minX; _x <=_maxX; _x++ )
- {
- PathSprite*_sp = m_inspectArray[(int)_x][(int)(_y)];
- if (!_sp)
- {
- return false;
- }
- }
- }
- else
- {
- for (int _y = _minY; _y <= _maxY; _y++)
- {
- for (int _x = _minX; _x <= _maxX; _x++)
- {
- float _length = MathLogic::linearEquationWithOneUnknown_solveShortLenghtrequiredPoint(p1,p2,CCPoint(_x,_y));
- float _maxLength = MathLogic::calculateLengthrequiredTwoPoint(CCPoint(0,0),CCPoint(0.5,0.5));
- if (_length < _maxLength)
- {
- PathSprite*_sp = m_inspectArray[(int)_x][(int)(_y)];
- if (!_sp)
- {
- return false;
- }
- }
- }
- }
- }
- return true;
- }
- void PathSearchInfo::resetObjPosition( )
- {
- #ifdef PRECISE_SEARCH_PATH
- CCPoint _point = getMapPositionByWorldPosition(m_moveObj->m_sprite->getPosition());
- CCSprite* _sp = m_road->tileAt(_point);
- if (_sp)
- {
- m_moveObj->m_x = _point.x;
- m_moveObj->m_y = _point.y;
- }
- else
- {
- CCSprite* _up = m_road->tileAt(_point + CCPoint(0,-1));
- if (_up)
- {
- m_moveObj->m_x = _point.x;
- m_moveObj->m_y = _point.y - 1;
- return;
- }
- CCSprite* _down = m_road->tileAt(_point + CCPoint(0,1));
- if (_down)
- {
- m_moveObj->m_x = _point.x;
- m_moveObj->m_y = _point.y +1;
- return;
- }
- CCSprite* _left = m_road->tileAt(_point + CCPoint(-1,0));
- if (_left)
- {
- m_moveObj->m_x = _point.x -1;
- m_moveObj->m_y = _point.y ;
- return;
- }
- CCSprite* _right = m_road->tileAt(_point + CCPoint(1,0));
- if (_right)
- {
- m_moveObj->m_x = _point.x + 1;
- m_moveObj->m_y = _point.y ;
- return;
- }
- }
- #endif // PRECISE
- }
- void PathSearchInfo::clearPath( )
- {
- for (vector<PathSprite*>::iterator iter = m_haveInspectList.begin(); iter != m_haveInspectList.end(); iter++)
- {
- (*iter)->m_sprite->setColor(ccWHITE);
- }
- resetInspectArray();
- //把移除了障碍物的地图放入检测列表中
- //m_inspectList = m_mapList;
- m_openList.clear();
- m_pathList.clear();
- m_haveInspectList.clear();
- m_moveObj->m_startX = m_moveObj->m_x;
- m_moveObj->m_startY = m_moveObj->m_y;
- m_moveObj->m_sprite->stopAllActions();
- m_playerMoveStep = 0;
- }
- void PathSearchInfo::moveObj()
- {
- #ifndef PRECISE_SEARCH_PATH
- m_playerMoveStep++;
- m_isMoving = true;
- //如果运动完毕
- if (m_playerMoveStep >= m_pathList.size())
- {
- if (m_isSetMoveDoneCallback)
- {
- m_isMoving = false;
- m_moveDone(CCPoint((*(m_pathList.end()-1))->m_x,(*(m_pathList.end()-1))->m_y));
- }
- return;
- }
- //存储当前的移动进程
- m_moveObj->m_x = m_pathList[m_playerMoveStep]->m_x;
- m_moveObj->m_y = m_pathList[m_playerMoveStep]->m_y;
- //设置深度
- m_moveObj->m_sprite->setZOrder(BASE_ZODER - m_pathList[m_playerMoveStep]->m_sprite->getPositionY());
- //根据路径列表移动人物
- CCPoint _terminalPosition = m_pathList[m_playerMoveStep]->m_sprite->getPosition()+m_tileSize/2;
- float _length = MathLogic::calculateLengthrequiredTwoPoint(_terminalPosition,m_moveObj->m_sprite->getPosition());
- m_moveObj->m_sprite->runAction(CCSequence::create(CCMoveTo::create(MOVE_SPEED * _length,_terminalPosition),CCCallFunc::create(this,SEL_CallFunc(&PathSearchInfo::moveObj)),NULL));
- #else
- m_isMoving = true;
- if (m_playerMoveStep == m_pathList.size()-1)
- {
- //sitChairJudge();
- if (m_isSetMoveDoneCallback)
- {
- m_isMoving = false;
- m_moveDone(CCPoint((*(m_pathList.end()-1))->m_x,(*(m_pathList.end()-1))->m_y));
- }
- return ;
- }
- for (int i = 1;i <= m_pathList.size() ;i++)
- {
- m_playerMoveStep = m_pathList.size()-i;
- if(detectWhetherCanPassBetweenTwoPoints(CCPoint(m_moveObj->m_x,m_moveObj->m_y),CCPoint(m_pathList[m_playerMoveStep]->m_x,m_pathList[m_playerMoveStep]->m_y)))
- {
- CCPoint _terminalPosition = m_pathList[m_playerMoveStep]->m_sprite->getPosition()+m_tileSize/2;
- float _length = MathLogic::calculateLengthrequiredTwoPoint(_terminalPosition,m_moveObj->m_sprite->getPosition());
- m_moveObj->m_sprite->runAction(CCSequence::create(CCMoveTo::create(MOVE_SPEED * _length,NULL));
- //存储当前的移动进程
- m_moveObj->m_x = m_pathList[m_playerMoveStep]->m_x;
- m_moveObj->m_y = m_pathList[m_playerMoveStep]->m_y;
- m_moveObj->m_sprite->setZOrder(BASE_ZODER - m_pathList[m_playerMoveStep]->m_sprite->getPositionY());
- break;
- }
- }
- #endif
- }
- #pragma once
- #include "cocos2d.h"
- #include "vector"
- #include "cocos-ext.h"
- using namespace std;
- USING_NS_CC;
- USING_NS_CC_EXT;
- class PathSprite
- {
- public:
- PathSprite(CCSprite* sprite):m_parent(NULL),m_child(NULL),m_costToSource(0),m_FValue(0),m_sprite(sprite),m_startX(0),m_startY(0),m_endX(0),m_endY(0)
- {
- };
- public:
- CCSprite* m_sprite;//包含的瓦片精灵
- PathSprite* m_parent;//父节点
- PathSprite* m_child;//子节点
- float m_costToSource;//到起始点的距离
- int m_x;//地图坐标
- int m_y;
- float m_FValue;
- int m_startX;//开始点
- int m_startY;
- int m_endX;//结束点
- int m_endY;
- };
- #pragma once
- #include "PathSprite.h"
- enum WalkState
- {
- WALK_LEFT,WALK_RIGHT,WALK_STAND
- };
- class Player:public PathSprite
- {
- public:
- CCArmature *armature;
- WalkState m_walkState;
- public:
- Player(CCSprite* sprite);
- public:
- void walkLeft();
- void walkRight();
- void stand();
- void walking();
- };
- #include "Player.h"
- Player::Player(CCSprite* sprite):PathSprite(sprite)
- {
- //创建一个人物
- CCArmatureDataManager::sharedArmatureDataManager()->addArmatureFileInfo("DemoPlayer/DemoPlayer.ExportJson");
- armature = NULL;
- armature = CCArmature::create("DemoPlayer");//0走路,1开枪,2开枪,3开空枪,4
- armature->setAnchorPoint(CCPoint(0.7,0));
- sprite->addChild(armature);
- }
- void Player::walkLeft()
- {
- if (m_walkState == WALK_LEFT)
- {
- return;
- }
- armature->getAnimation()->playWithIndex(1);
- armature->setScaleX(1);
- m_walkState = WALK_LEFT;
- }
- void Player::walkRight()
- {
- if (m_walkState == WALK_RIGHT)
- {
- return;
- }
- armature->getAnimation()->playWithIndex(1);
- armature->setScaleX(-1);
- m_walkState = WALK_RIGHT;
- }
- void Player::stand()
- {
- if (m_walkState == WALK_STAND)
- {
- return;
- }
- if (m_walkState == WALK_LEFT)
- {
- armature->getAnimation()->playWithIndex(2);
- armature->setScaleX(1);
- }
- if (m_walkState == WALK_RIGHT)
- {
- armature->getAnimation()->playWithIndex(2);
- armature->setScaleX(-1);
- }
- m_walkState = WALK_STAND;
- }
- void Player::walking()
- {
- if (m_endX - m_startX >=0)
- {
- walkRight();
- }
- else
- {
- walkLeft();
- }
- }
- #ifndef _PADDLE_H_
- #define _PADDLE_H_
- #include "cocos2d.h"
- #include <functional>
- //#include "stdafx.h"
- //using namespace std;
- USING_NS_CC;
- typedef enum tagPaddleState
- {
- kPaddleStateGrabbed,kPaddleStateUngrabbed
- } PaddleState;
- enum OBJTYPE
- {
- NONE_TYPE = 0,CHAIR_LEFT = 1,CHAIR_FRON = 2,CHAIR_RIGHT = 3,CHAIR_BACK = 4
- };
- class Paddle : public CCSprite,public CCTargetedTouchDelegate
- {
- public:
- PaddleState m_state;
- bool m_isSelect;
- bool m_enableSit;
- bool m_enableTouch;
- bool m_enablePickUp;
- CCPoint m_terminal;
- std::function<void(CCPoint,Paddle* )> m_selectCallback;
- OBJTYPE m_type;
- CCSprite* m_playerSprite;
- CCSprite* m_chairPartSprite;
- public:
- Paddle(void);
- virtual ~Paddle(void);
- CCRect rect();
- bool initWithTexture();
- virtual void onEnter();
- virtual void onExit();
- bool containsTouchLocation(CCPoint point);
- virtual bool ccTouchBegan(CCTouch* touch,CCEvent* event);
- virtual void ccTouchMoved(CCTouch* touch,CCEvent* event);
- virtual void ccTouchEnded(CCTouch* touch,CCEvent* event);
- virtual CCObject* copyWithZone(CCZone *pZone);
- virtual void touchDelegateRetain();
- virtual void touchDelegateRelease();
- static Paddle* paddleWithContentSize(CCSize);//创建物体
- void setSelect(bool isSelect);//选中时
- void setOpacity(GLubyte opacity);
- void sitChair();//坐下
- void standUp();//站起
- };
- #endif
- #include "Paddle.h"
- #include "FilePath.h"
- using namespace std;
- Paddle::Paddle(void):m_chairPartSprite(NULL),m_playerSprite(NULL),m_enableSit(false)
- {
- }
- Paddle::~Paddle(void)
- {
- }
- CCRect Paddle::rect()
- {
- CCSize s = this->getContentSize();
- return CCRectMake(this->getPositionX(),this->getPositionY(),s.width,s.height);
- }
- Paddle* Paddle::paddleWithContentSize(CCSize size)
- {
- Paddle* pPaddle = new Paddle();
- pPaddle->initWithTexture();
- pPaddle->setContentSize(size);
- pPaddle->autorelease();
- return pPaddle;
- }
- bool Paddle::initWithTexture()
- {
- if( CCSprite::init() )
- {
- m_state = kPaddleStateUngrabbed;
- }
- return true;
- }
- void Paddle::onEnter()
- {
- CCDirector* pDirector = CCDirector::sharedDirector();
- pDirector->getTouchDispatcher()->addTargetedDelegate(this,false);
- CCSprite::onEnter();
- }
- void Paddle::onExit()
- {
- CCDirector* pDirector = CCDirector::sharedDirector();
- pDirector->getTouchDispatcher()->removeDelegate(this);
- CCSprite::onExit();
- }
- bool Paddle::containsTouchLocation(CCPoint point)
- {
- //CCLog("%f,%f",convertToNodeSpaceAR(point).x,convertToNodeSpaceAR(point).y);
- return rect().containsPoint((point));
- }
- bool Paddle::ccTouchBegan(CCTouch* touch,CCEvent* event)
- {
- if (m_isSelect) {
- setSelect(false);
- }
- auto nodePosition = this->getParent()->convertToNodeSpace( touch->getLocation() );
- CCLog("%f,nodePosition.x,nodePosition.y);
- if (m_state != kPaddleStateUngrabbed) return false;
- if ( !containsTouchLocation(nodePosition) ) return false;
- CCLog("touchSuccess") ;
- m_state = kPaddleStateGrabbed;
- setSelect(true);
- if (m_selectCallback)
- {
- m_selectCallback(m_terminal,this);
- }
- //sitChair();
- return true;
- }
- void Paddle::ccTouchMoved(CCTouch* touch,CCEvent* event)
- {
- // If it weren't for the TouchDispatcher,you would need to keep a reference
- // to the touch from touchBegan and check that the current touch is the same
- // as that one.
- // Actually,it would be even more complicated since in the Cocos dispatcher
- // you get CCSets instead of 1 UITouch,so you'd need to loop through the set
- // in each touchXXX method.
- CCAssert(m_state == kPaddleStateGrabbed,"Paddle - Unexpected state!");
- // CCPoint touchPoint = touch->getLocation();
- //setPosition( ccp(touchPoint.x,getPosition().y) );
- }
- CCObject* Paddle::copyWithZone(CCZone *pZone)
- {
- this->retain();
- return this;
- }
- void Paddle::ccTouchEnded(CCTouch* touch,CCEvent* event)
- {
- CCAssert(m_state == kPaddleStateGrabbed,"Paddle - Unexpected state!");
- m_state = kPaddleStateUngrabbed;
- }
- void Paddle::touchDelegateRetain()
- {
- this->retain();
- }
- void Paddle::touchDelegateRelease()
- {
- this->release();
- }
- void Paddle::setSelect(bool isSelect)
- {
- CCArray* _array = this->getChildren();
- CCObject *_obj;
- m_isSelect = isSelect;
- CCARRAY_FOREACH(_array,_obj )
- {
- CCSprite* _sp = (CCSprite *)_obj;
- if (isSelect)
- {
- _sp->setColor(ccRED);
- }
- else
- {
- _sp->setColor(ccWHITE);
- }
- }
- }
- void Paddle::setOpacity( GLubyte opacity )
- {
- CCArray* _array = this->getChildren();
- CCObject *_obj;
- CCARRAY_FOREACH(_array,_obj )
- {
- CCSprite* _sp = (CCSprite *)_obj;
- _sp->setOpacity(opacity);
- }
- }
- void Paddle::sitChair()
- {
- switch (m_type)
- {
- case NONE_TYPE:
- break;
- case CHAIR_LEFT:
- {
- m_playerSprite = CCSprite::create(g_chair_left_player);
- m_playerSprite->setAnchorPoint(CCPoint());
- m_playerSprite->setPosition(CCPoint(-8,-15));
- this->addChild(m_playerSprite,100);
- m_chairPartSprite= CCSprite::create(g_chair_left_part);
- m_chairPartSprite->setAnchorPoint(CCPoint());
- m_chairPartSprite->setPosition(CCPoint(-15,-5));
- this->addChild(m_chairPartSprite,100);
- break;
- }
- case CHAIR_FRON:
- break;
- case CHAIR_RIGHT:
- break;
- case CHAIR_BACK:
- {
- m_playerSprite = CCSprite::create(g_chair_back_player);
- m_playerSprite->setAnchorPoint(CCPoint());
- m_playerSprite->setPosition(CCPoint(-15,-5));
- this->addChild(m_playerSprite);
- break;
- }
- default:
- break;
- }
- }
- void Paddle::standUp()
- {
- if (m_playerSprite)
- {
- m_playerSprite->removeFromParentAndCleanup(true);
- m_playerSprite = NULL;
- }
- if (m_chairPartSprite)
- {
- m_chairPartSprite->removeFromParentAndCleanup(true);
- m_chairPartSprite = NULL;
- }
- }
- //
- // MathLogic.h
- // MapGame
- //
- // Created by TinyUlt on 14/10/11.
- //
- //
- #ifndef __MapGame__MathLogic__
- #define __MapGame__MathLogic__
- #include <stdio.h>
- #include "cocos2d.h"
- USING_NS_CC;
- class MathLogic
- {
- public:
- //线性方程 一元二次方法 求y
- static float linearEquationWithOneUnknown_solveYrequiredX(CCPoint knownPoint1,CCPoint knownPoint2,float x)
- {
- float _x1 = knownPoint1.x;
- float _y1 = knownPoint1.y;
- float _x2 = knownPoint2.x;
- float _y2 = knownPoint2.y;
- float m_p1 = (_y1 -_y2)/(_x1-_x2);
- float m_p2 = _y1 - m_p1 * _x1;
- // float m_p1 = (knownPoint1.y -knownPoint2.y)/(knownPoint1.x-knownPoint2.x);
- // float m_p2 = knownPoint1.y - m_p1 * knownPoint1.x;
- return m_p1* x + m_p2;
- }
- //线性方程 一元二次方法 求x
- static float linearEquationWithOneUnknown_solveXrequiredY(CCPoint knownPoint1,float y)
- {
- float _x1 = knownPoint1.x;
- float _y1 = knownPoint1.y;
- float _x2 = knownPoint2.x;
- float _y2 = knownPoint2.y;
- float m_p1 = (_y1 -_y2)/(_x1-_x2);
- float m_p2 = _y1 - m_p1 * _x1;
- // float m_p1 = (knownPoint1.y -knownPoint2.y)/(knownPoint1.x-knownPoint2.x);
- // float m_p2 = knownPoint1.y - m_p1 * knownPoint1.x;
- return (y - m_p2)/m_p1;
- }
- //求点到直线最短路径长度
- static float linearEquationWithOneUnknown_solveShortLenghtrequiredPoint(CCPoint knownPoint1,CCPoint point)
- {
- if ((point.x == knownPoint1.x && point.y == knownPoint1.y) || (point.x == knownPoint2.x && point.y == knownPoint2.y))
- {
- return 0;
- }
- float _x1 = knownPoint1.x;
- float _y1 = knownPoint1.y;
- float _x2 = knownPoint2.x;
- float _y2 = knownPoint2.y;
- float m_p1 = (_y1 -_y2)/(_x1-_x2);
- float m_p2 = _y1 - m_p1 * _x1;
- CCPoint p1((point.y - m_p2)/m_p1,point.y);
- CCPoint p2(point.x,m_p1* point.x + m_p2);
- float offsetY = abs( p2.y - point.y);
- float offsetX = abs(p1.x - point.x);
- if (offsetX == 0 && offsetY == 0)
- {
- return 0;
- }
- return offsetX * offsetY / calculateLengthrequiredTwoPoint(p1,p2);
- }
- //计算2点距离
- static float calculateLengthrequiredTwoPoint(CCPoint p1,CCPoint p2)
- {
- float _offsetX = abs( p1.x - p2.x);
- float _offsetY =abs( p1.y - p2.y);
- return sqrt(_offsetX * _offsetX + _offsetY * _offsetY);
- }
- //绝对值
- static float abs(float value)
- {
- return value>0?value:-value;
- }
- };
- #endif /* defined(__MapGame__MathLogic__) */
- #ifndef __HELLOWORLD_SCENE_H__
- #define __HELLOWORLD_SCENE_H__
- #include "PathSearchInfo.h"
- #include "Player.h"
- class Paddle;
- class HelloWorld : public cocos2d::CCLayer
- {
- public:
- // Here's a difference. Method 'init' in cocos2d-x returns bool,instead of returning 'id' in cocos2d-iphone
- virtual bool init();
- // there's no 'id' in cpp,so we recommend returning the class instance pointer
- static cocos2d::CCScene* scene();
- // a selector callback
- void menuCloseCallback(CCObject* pSender);
- // implement the "static node()" method manually
- CREATE_FUNC(HelloWorld);
- void onEnter();
- virtual bool ccTouchBegan(CCTouch* touch,CCEvent* event);
- void drawPath(vector<PathSprite*>& vec);//绘制路径(测试用)
- void update(float dt);//跟新大地图(行走时,人不动,地图跟着人动);
- void selectObjCallback(CCPoint point,Paddle* selectObj);//选择物体回调
- void moveDone(CCPoint point);//移动结束回调
- public:
- PathSearchInfo* m_pathSearch;//寻路引擎类
- CCPoint m_orignPoint;//人物的起始点
- Player* m_player;//人物
- Paddle* m_currentSelect;//当前选中的物品
- };
- #endif // __HELLOWORLD_SCENE_H__
- #include "HelloWorldScene.h"
- #include "Paddle.h"
- #include "MathLogic.h"
- #include <functional>
- USING_NS_CC;
- CCScene* HelloWorld::scene()
- {
- // 'scene' is an autorelease object
- CCScene *scene = CCScene::create();
- // 'layer' is an autorelease object
- HelloWorld *layer = HelloWorld::create();
- // add layer as a child to scene
- scene->addChild(layer);
- // return the scene
- return scene;
- }
- // on "init" you need to initialize your instance
- void HelloWorld::onEnter()
- {
- CCDirector* pDirector = CCDirector::sharedDirector();
- pDirector->getTouchDispatcher()->addTargetedDelegate(this,-1,false);
- CCLayer::onEnter();
- }
- bool HelloWorld::init()
- {
- //////////////////////////////
- // 1. super init first
- if ( !CCLayer::init() )
- {
- return false;
- }
- CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
- CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();
- CCTMXTiledMap* _map = CCTMXTiledMap::create("gameMap.tmx");
- _map->setPosition(CCPoint());
- this->addChild(_map);
- m_pathSearch = new PathSearchInfo(_map);
- std::function<void (CCPoint point)> _fun = std::bind(&HelloWorld::moveDone,this,std::placeholders::_1);
- m_pathSearch->setMoveDoneCallback(_fun);
- std::function<void (vector<PathSprite*>)> _funDrawPath = std::bind(&HelloWorld::drawPath,std::placeholders::_1);
- m_pathSearch->setDrawPathCallback(_funDrawPath);
- std::function<void(CCPoint point,Paddle* selectObj)> _funcSelect = std::bind(&HelloWorld::selectObjCallback,std::placeholders::_1,std::placeholders::_2);
- m_pathSearch->setSelectCallback(_funcSelect);
- /////////////////////////////
- CCMenuItemSprite* _menuItemSprite = CCMenuItemSprite::create(CCSprite::create("CloseNormal.png"),CCSprite::create("CloseSelected.png"),SEL_MenuHandler(&HelloWorld::menuCloseCallback));
- CCMenu* _menu = CCMenu::create(_menuItemSprite,NULL);
- this->addChild(_menu,1000);
- m_currentSelect = NULL;
- //m_isMoving = false;
- CCLabelTTF* pLabel = CCLabelTTF::create("A* + tiledMap","Arial",24);
- // position the label on the center of the screen
- pLabel->setPosition(ccp(origin.x + visibleSize.width/2,origin.y + visibleSize.height - pLabel->getContentSize().height));
- // add the label as a child to this layer
- this->addChild(pLabel,1);
- this->scheduleUpdate();
- //设置起始和终点
- m_orignPoint = CCDirector::sharedDirector()->getWinSize()/2 ;//+ CCSize(0,100);
- //创建一个人物
- CCSprite* _sp = CCSprite::create();
- _sp->setScale(0.08);
- m_player = new Player(_sp);
- m_player->m_sprite->setOpacity(100);
- m_pathSearch->getMap()->addChild(m_player->m_sprite,BASE_ZODER);
- m_player->m_sprite->setPosition(m_orignPoint);//设置人物的起始的世界坐标
- m_player->m_startX =m_pathSearch->getMapPositionByWorldPosition(m_orignPoint).x;
- m_player->m_startY =m_pathSearch->getMapPositionByWorldPosition(m_orignPoint).y;
- m_player->m_x = m_player->m_startX;
- m_player->m_y = m_player->m_startY;
- m_pathSearch->initMapObject("desk","desk");
- m_pathSearch->initMapObject("chairLeft","chairLeft");
- m_pathSearch->initMapObject("chairFront","chairFront");
- m_pathSearch->initMapObject("chairBack","chairBack");
- m_pathSearch->initMapObject("zhuzi","zhuzi");
- m_pathSearch->initMapObject("goods","goods");
- return true;
- }
- void HelloWorld::drawPath( vector<PathSprite*>& vec )
- {
- for (vector<PathSprite*>::iterator iter = vec.begin(); iter != vec.end(); iter++)
- {
- (*iter)->m_sprite->setColor(ccGREEN);
- }
- }
- CCRect getBoundingBox(float x,float y,float width,float height)
- {
- return CCRect(x - width/2,y - height/2,width,height);
- }
- bool HelloWorld::ccTouchBegan(CCTouch* touch,CCEvent* event)
- {
- if (m_pathSearch->getEnableMove())
- {
- m_currentSelect = NULL;
- auto nodePosition = convertToNodeSpace( touch->getLocation() );
- m_pathSearch ->pathFunction(m_pathSearch->getMapPositionByWorldPosition(nodePosition),m_player);
- }
- return true;
- }
- void HelloWorld::ccTouchMoved(CCTouch* touch,CCEvent* event)
- {
- }
- void HelloWorld::ccTouchEnded(CCTouch* touch,CCEvent* event)
- {
- }
- void HelloWorld::menuCloseCallback(CCObject* pSender)
- {
- if (!m_pathSearch->getEnableMove())
- {
- m_pathSearch->setEnableMove(true);
- m_currentSelect->standUp();
- m_player->m_sprite->setVisible(true);
- }
- }
- void HelloWorld::update(float dt)
- {
- //移动层
- this->setPosition(m_orignPoint - m_player->m_sprite->getPosition());
- if(m_pathSearch->getIsMoving())
- {
- m_player->walking();
- }
- else
- {
- m_player->stand();
- }
- }
- void HelloWorld::selectObjCallback( CCPoint point,Paddle* selectObj )
- {
- //如果不能移动物体的话,不能点击其他物体
- if (m_pathSearch->getEnableMove())
- {
- m_currentSelect = selectObj;
- m_pathSearch ->pathFunction( point,m_player);
- }
- }
- void HelloWorld::moveDone(CCPoint point)
- {
- //判断是有选择的物体
- if (m_currentSelect)
- {
- //判断是否能坐下
- if (m_currentSelect->m_enableSit/* && point.x == m_currentSelect->m_terminal.x&& point.y == m_currentSelect->m_terminal.y*/)
- {
- m_currentSelect->sitChair();
- m_pathSearch->setEnableMove(false);
- m_player->m_sprite->setVisible(false);
- }
- //判断是否能捡起
- if (m_currentSelect->m_enablePickUp)
- {
- m_currentSelect->m_enablePickUp = false;
- m_currentSelect->runAction(CCSequence::create(CCFadeOut::create(0.5),CCRemoveSelf::create(true),NULL));
- m_currentSelect = NULL;
- }
- }
- }
- static char* g_chair_left_player = "player_1/chair_left_player.png";
- static char* g_chair_back_player = "player_1/chair_back_player.png";
- static char* g_chair_left_part = "player_1/chair_left_part.png";
- #define MAP_WIDTH 600//要比tmx中的map大1
- #define MAP_HEIGHT 600
- #define BASE_ZODER 100000
- #define MOVE_SPEED 1/200.0
- #define PRECISE_SEARCH_PATH//精确的寻 路系统,需要消耗额外的运算(魔兽争霸级的!)