此次在之前那篇cocos2dx A* tiledMap文章中新加了些功能并且调整了结构 拥有的功能: 能避开障碍物,搜寻最优路径 优化了行走的路径,使之平滑行走(之前的是瓦片级的, 现在是像素级的, #define PRECISE_SEARCH_PATH 开启精确的路径行走) 添加了人物根据位置会被
此次在之前那篇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> m_moveDone;//移动结束回调 bool m_isSetMoveDoneCallback; std::function<void>)> m_drawPath;//画线回调 调试用 bool m_isSetDrawPathCallback; std::function<void 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>& pFunc);//设置回调 void setDrawPathCallback(function<void>)>& pFunc);//设置回调 void setSelectCallback(function<void 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();//移动实现函数 }; </void></void></void></pathsprite></pathsprite></pathsprite></void></void></void></functional>
#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 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>& pFunc ) { m_moveDone = pFunc; m_isSetMoveDoneCallback = true; } void PathSearchInfo::setDrawPathCallback( function<void>)>& pFunc ) { m_drawPath = pFunc; m_isSetDrawPathCallback = true; } void PathSearchInfo::setSelectCallback( function<void 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 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 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; #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 m_FValue) { _sp = *iter; } } return _sp; } else { return NULL; } } PathSprite* PathSearchInfo::getObjFromInspectArray( int x, int y ) { if (x >=0 && y >=0 && x ::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 float _miny="p1.y<p2.y?p1.y:p2.y;" if p2.x>1) { return false; } float _x = p1.x; for (int _y = _minY; _y 1) { return false; } float _y = p1.y; for (int _x = _minX; _x 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_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 } </pathsprite></p2.x></pathsprite></pathsprite></void></void></void>
#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 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</void></functional>
#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: //线性方程 一元二次方法 求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, 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__) */ </stdio.h>
#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); 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__</pathsprite>
#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 point> _fun = std::bind(&HelloWorld::moveDone,this,std::placeholders::_1); m_pathSearch->setMoveDoneCallback(_fun); std::function<void>)> _funDrawPath = std::bind(&HelloWorld::drawPath,this,std::placeholders::_1); m_pathSearch->setDrawPathCallback(_funDrawPath); std::function<void 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 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; } } } </pathsprite></pathsprite></void></void></void></functional>
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//精确的寻 路系统, 需要消耗额外的运算(魔兽争霸级的!)

MySQL is an open source relational database management system, mainly used to store and retrieve data quickly and reliably. Its working principle includes client requests, query resolution, execution of queries and return results. Examples of usage include creating tables, inserting and querying data, and advanced features such as JOIN operations. Common errors involve SQL syntax, data types, and permissions, and optimization suggestions include the use of indexes, optimized queries, and partitioning of tables.

MySQL is an open source relational database management system suitable for data storage, management, query and security. 1. It supports a variety of operating systems and is widely used in Web applications and other fields. 2. Through the client-server architecture and different storage engines, MySQL processes data efficiently. 3. Basic usage includes creating databases and tables, inserting, querying and updating data. 4. Advanced usage involves complex queries and stored procedures. 5. Common errors can be debugged through the EXPLAIN statement. 6. Performance optimization includes the rational use of indexes and optimized query statements.

MySQL is chosen for its performance, reliability, ease of use, and community support. 1.MySQL provides efficient data storage and retrieval functions, supporting multiple data types and advanced query operations. 2. Adopt client-server architecture and multiple storage engines to support transaction and query optimization. 3. Easy to use, supports a variety of operating systems and programming languages. 4. Have strong community support and provide rich resources and solutions.

InnoDB's lock mechanisms include shared locks, exclusive locks, intention locks, record locks, gap locks and next key locks. 1. Shared lock allows transactions to read data without preventing other transactions from reading. 2. Exclusive lock prevents other transactions from reading and modifying data. 3. Intention lock optimizes lock efficiency. 4. Record lock lock index record. 5. Gap lock locks index recording gap. 6. The next key lock is a combination of record lock and gap lock to ensure data consistency.

The main reasons for poor MySQL query performance include not using indexes, wrong execution plan selection by the query optimizer, unreasonable table design, excessive data volume and lock competition. 1. No index causes slow querying, and adding indexes can significantly improve performance. 2. Use the EXPLAIN command to analyze the query plan and find out the optimizer error. 3. Reconstructing the table structure and optimizing JOIN conditions can improve table design problems. 4. When the data volume is large, partitioning and table division strategies are adopted. 5. In a high concurrency environment, optimizing transactions and locking strategies can reduce lock competition.

In database optimization, indexing strategies should be selected according to query requirements: 1. When the query involves multiple columns and the order of conditions is fixed, use composite indexes; 2. When the query involves multiple columns but the order of conditions is not fixed, use multiple single-column indexes. Composite indexes are suitable for optimizing multi-column queries, while single-column indexes are suitable for single-column queries.

To optimize MySQL slow query, slowquerylog and performance_schema need to be used: 1. Enable slowquerylog and set thresholds to record slow query; 2. Use performance_schema to analyze query execution details, find out performance bottlenecks and optimize.

MySQL and SQL are essential skills for developers. 1.MySQL is an open source relational database management system, and SQL is the standard language used to manage and operate databases. 2.MySQL supports multiple storage engines through efficient data storage and retrieval functions, and SQL completes complex data operations through simple statements. 3. Examples of usage include basic queries and advanced queries, such as filtering and sorting by condition. 4. Common errors include syntax errors and performance issues, which can be optimized by checking SQL statements and using EXPLAIN commands. 5. Performance optimization techniques include using indexes, avoiding full table scanning, optimizing JOIN operations and improving code readability.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

DVWA
Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

MinGW - Minimalist GNU for Windows
This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

Safe Exam Browser
Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

Atom editor mac version download
The most popular open source editor

mPDF
mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),