cocos2dx A* + tiledMap(改良升级)

来源:互联网 发布:网上看房用什么软件 编辑:程序博客网 时间:2024/04/30 13:38

此次在之前那篇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,CCPoint(0,-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, _adjacent, _endNode);_adjacent = getObjFromInspectArray(  _x -1, _y);inspectTheAdjacentNodes(_node, _adjacent, _endNode);_adjacent = getObjFromInspectArray(  _x , _y+1);inspectTheAdjacentNodes(_node, _adjacent, _endNode);_adjacent = getObjFromInspectArray( _x + 1, _y + 1);inspectTheAdjacentNodes(_node, _adjacent, _endNode);_adjacent = getObjFromInspectArray(  _x +1, _y-1);inspectTheAdjacentNodes(_node, _adjacent, _endNode);_adjacent = getObjFromInspectArray(  _x -1, _y - 1);inspectTheAdjacentNodes(_node, _adjacent, _endNode);_adjacent = getObjFromInspectArray(  _x -1, _y+1);inspectTheAdjacentNodes(_node, _adjacent, _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, _y);inspectTheAdjacentNodes(_node, _adjacent, _endNode);_adjacent = getObjFromInspectArray(  _x , _y -1);inspectTheAdjacentNodes(_node, _adjacent, _endNode);_adjacent = getObjFromInspectArray(  _x -1, _y);inspectTheAdjacentNodes(_node, _adjacent, _endNode);_adjacent = getObjFromInspectArray(  _x , _y+1);inspectTheAdjacentNodes(_node, _adjacent, _endNode);_adjacent = getObjFromInspectArray( _x + 1, _y + 1);inspectTheAdjacentNodes(_node, _adjacent, _endNode);_adjacent = getObjFromInspectArray(  _x +1, _y-1);inspectTheAdjacentNodes(_node, _adjacent, _endNode);_adjacent = getObjFromInspectArray(  _x -1, _y - 1);inspectTheAdjacentNodes(_node, _adjacent, _endNode);_adjacent = getObjFromInspectArray(  _x -1, _y+1);inspectTheAdjacentNodes(_node, _adjacent, _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* adjacent, 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;#endifadjacent->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_PATHCCPoint _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_PATHm_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));#elsem_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,_terminalPosition), CCCallFunc::create(this, SEL_CallFunc(&PathSearchInfo::moveObj)), 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开空枪,4armature->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, 0, 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, %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://线性方程 一元二次方法 求ystatic 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;}//线性方程 一元二次方法 求xstatic float linearEquationWithOneUnknown_solveXRequiredY(CCPoint knownPoint1, CCPoint knownPoint2, 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 knownPoint2, 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-iphonevirtual bool init();  // there's no 'id' in cpp, so we recommend returning the class instance pointerstatic cocos2d::CCScene* scene();// a selector callbackvoid menuCloseCallback(CCObject* pSender);// implement the "static node()" method manuallyCREATE_FUNC(HelloWorld);void onEnter();virtual bool ccTouchBegan(CCTouch* touch, CCEvent* event);virtual void ccTouchMoved(CCTouch* touch, CCEvent* event);virtual void ccTouchEnded(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 objectCCScene *scene = CCScene::create();// 'layer' is an autorelease objectHelloWorld *layer = HelloWorld::create();// add layer as a child to scenescene->addChild(layer);// return the scenereturn scene;}// on "init" you need to initialize your instancevoid HelloWorld::onEnter(){CCDirector* pDirector = CCDirector::sharedDirector();pDirector->getTouchDispatcher()->addTargetedDelegate(this, -1, false);CCLayer::onEnter();}bool HelloWorld::init(){//////////////////////////////// 1. super init firstif ( !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,this,std::placeholders::_1);m_pathSearch->setDrawPathCallback(_funDrawPath);std::function<void(CCPoint point, Paddle* selectObj)> _funcSelect = std::bind(&HelloWorld::selectObjCallback,this,std::placeholders::_1,std::placeholders::_2);  m_pathSearch->setSelectCallback(_funcSelect);///////////////////////////// CCMenuItemSprite* _menuItemSprite = CCMenuItemSprite::create(CCSprite::create("CloseNormal.png"),CCSprite::create("CloseSelected.png"),NULL,this,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 screenpLabel->setPosition(ccp(origin.x + visibleSize.width/2, origin.y + visibleSize.height - pLabel->getContentSize().height));// add the label as a child to this layerthis->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//精确的寻 路系统, 需要消耗额外的运算(魔兽争霸级的!)



0 0