关卡数据已经能显示出来了,现在需要添加角色精灵的移动。这就需要添加触屏点击事件。在点击事件中对触屏的进行手势识别,手势识别非常简单,就是判断玩家是想让角色向上移动和是向哪移动。
思路:
两个Vec2类型的变量,记录点击开始的点和移动过程中的点。
一个RoleSprite类型的变量,记录当前选中的精灵。
Float类型的变量,指定最小的判断距离,也就是说,如果,移动距离比较小是不会有反应的。
用一个二维数组来记录当前每个格子的状态,移动RoleSprite的时候判断是否可以移动。
代码:
GameLayer.h
#ifndef _GAME_LAYER_H_ #define _GAME_LAYER_H_ #include "cocos2d.h" class Level ; class RoleSprite ; class GameLayer : public cocos2d::Layer { public: static cocos2d::Scene* createScene(); CREATE_FUNC(GameLayer); public: GameLayer(); ~GameLayer(); virtual bool init(); //@biref 初始化地图 void initMap() ; //@biref 更新m_mapState void updateMapData() ; //@biref 重置m_mapState中的数据 void resetMapData(); virtual bool onTouchBegan(cocos2d::Touch *touch,cocos2d::Event *unused_event) ; virtual void onTouchMoved(cocos2d::Touch *touch,cocos2d::Event *unused_event) ; virtual void onTouchEnded(cocos2d::Touch *touch,cocos2d::Event *unused_event) ; //@biref 是否可以移动,参数:要移动的方向,是往加的方向移动还是往减的方向移动 bool isCanMove(bool isMoveHor,bool moveAdd); private: Level * m_pLevel;//<关卡数据的引用 cocos2d::Vector<RoleSprite*> m_pRoleSpriteVec ;//<存储角色精灵 cocos2d::Vec2 m_touchBegin ;//<开始点击的位置 cocos2d::Vec2 m_touchMove ;//<移动过程中的点 float m_minDis ;//<最小移动距离,>=他的时候才判断是否移动 RoleSprite * m_pSeleNode ;//<选中的角色 int m_mapState[5][4] ;//<5行4列,0是空,1是已填充 }; #endif
GameLayer.cpp
#include "GameLayer.h" #include "RoleSprite.h" #include "data/Role.h" #include "data/Level.h" USING_NS_CC ; Scene* GameLayer::createScene() { auto scene = Scene::create() ; auto layer = GameLayer::create() ; scene->addChild(layer); return scene ; } GameLayer::GameLayer() :m_pLevel(nullptr),m_pSeleNode(nullptr),m_touchBegin(Vec2(0,0)),m_touchMove(Vec2(0,m_minDis(0) { m_pLevel = Level::s_levelVec.at(0) ; CC_SAFE_RETAIN(m_pLevel) ; m_minDis = 20.0f ; } GameLayer::~GameLayer() { CC_SAFE_RELEASE_NULL(m_pLevel) ; } bool GameLayer::init() { Size size = Director::getInstance()->getWinSize(); auto bgSprite = Sprite::create("main_bg0.png") ; bgSprite->setPosition(size.width / 2,size.height / 2) ; addChild(bgSprite); initMap() ; auto lisener = EventListenerTouchOneByOne::create() ; lisener->onTouchBegan = CC_CALLBACK_2(GameLayer::onTouchBegan,this) ; lisener->onTouchMoved = CC_CALLBACK_2(GameLayer::onTouchMoved,this) ; lisener->onTouchEnded = CC_CALLBACK_2(GameLayer::onTouchEnded,this); _eventDispatcher->addEventListenerWithSceneGraPHPriority(lisener,this) ; return true ; } void GameLayer::initMap() { Size size = Director::getInstance()->getWinSize(); float x = 0 ; float y = 0 ; float paddingLeft = 10.0f ; float paddingBottom = 53.0f ; for (unsigned i = 0 ; i < m_pLevel->getRoleID().size() ;i++) { Role * pRole = Role::s_roleVec.at(m_pLevel->getRoleID().at(i)) ; Sprite * pp = Sprite::create(pRole->getImageName()->getCString()); int col = m_pLevel->getRolePos().at(i).x ; int row = m_pLevel->getRolePos().at(i).y ; x = paddingLeft + col * 1.0f * 75.0f ; y = paddingBottom + row * 1.0f * 75.0f ; RoleSprite * pRoleSprite = RoleSprite::create(pRole,row,col,Rect(x,y,pp->getContentSize().width,pp->getContentSize().height),this,this->getLocalZOrder()) ; m_pRoleSpriteVec.pushBack(pRoleSprite) ; } updateMapData() ; } bool GameLayer::onTouchBegan(Touch *touch,Event *unused_event) { auto loction = this->convertToNodeSpace(touch->getLocation()) ; for (unsigned int i = 0 ; i < m_pRoleSpriteVec.size() ; i++) { RoleSprite * pRoleSprite = m_pRoleSpriteVec.at(i) ; if (pRoleSprite->getBoundingBox().containsPoint(loction)) { //得到点击的位置和选中的角色 m_touchBegin = loction ; m_pSeleNode = pRoleSprite ; break; } } return true ; } void GameLayer::onTouchMoved(Touch *touch,Event *unused_event) { //角色移动过程中或者角色为null的时候不需要检测是否移动 if ((m_pSeleNode && m_pSeleNode->getNumberOfRunningActions() > 0) || !m_pSeleNode) { return ; } auto loction = this->convertToNodeSpace(touch->getLocation()) ; m_touchMove = loction ; float dis = m_touchMove.getDistance(m_touchBegin) ;//触点移动的距离 auto var = m_touchMove - m_touchBegin ; auto moveByPos = Vec2(0,0) ; auto varColRow = Vec2(0,0) ; if (dis >= m_minDis)//移动 { bool isMoveHor = abs(var.x) > abs(var.y) ;//判断是检测竖直方向的移动还是水平方向的移动 bool isMoveTop ;//<如果是竖直方向上,判断是向上还是向下 bool isMoveRight ;//<如果是水平方向上,判断死向右还是向左 if (isMoveHor)//水平方向移动 { isMoveRight = var.x > 0 ; if (var.x > 0)//right { moveByPos = Vec2(75.0f,0) ; varColRow = Vec2(1,0) ; } else//left { moveByPos = Vec2(-75.0f,0) ; varColRow = Vec2(-1,0) ; } } else//竖直方向移动 { isMoveTop = var.y > 0 ; if (var.y > 0)//top { moveByPos = Vec2(0,75.0f) ; varColRow = Vec2(0,1) ; } else//bottom { moveByPos = Vec2(0,-75.0f) ; varColRow = Vec2(0,-1) ; } } if (isCanMove(isMoveHor,isMoveHor ? isMoveRight : isMoveTop)) { m_pSeleNode->setCol(m_pSeleNode->getCol() + (int)varColRow.x) ; m_pSeleNode->setRow(m_pSeleNode->getRow() + (int)varColRow.y) ; m_pSeleNode->runAction( MoveBy::create(0.5f,moveByPos) ) ; updateMapData() ;//更新地图的状态 } } } void GameLayer::onTouchEnded(Touch *touch,Event *unused_event) { //重置 m_touchBegin = Vec2(0,0) ; m_touchMove = Vec2(0,0) ; m_pSeleNode = nullptr ; } bool GameLayer::isCanMove(bool isMoveHor,bool moveAdd) { bool isMove = false; CCAssert(m_pSeleNode,"select node should not is null!!") ; int width = m_pSeleNode->getWidth() ; int height = m_pSeleNode->getHeight() ; int row = m_pSeleNode->getRow() ; int col = m_pSeleNode->getCol() ; if (isMoveHor)//水平方向 { if (moveAdd) { int colTem = col + width; int rowTem = row ; int filledNum = 0 ; for (int i = 0; i < height ; i++) { rowTem += i; if (m_mapState[rowTem][colTem] == 1) { filledNum++ ; } } isMove = (filledNum == 0) ? true : false; if (m_pSeleNode->getCol() == 3) { isMove = false ; } } else { int colTem = col - 1; int rowTem = row ; int filledNum = 0 ; for (int i = 0; i < height ; i++) { rowTem += i; if (m_mapState[rowTem][colTem] == 1) { filledNum++ ; } } isMove = (filledNum == 0) ? true : false; if (m_pSeleNode->getCol() == 0) { isMove = false ; } } } else//竖直方向 { if (moveAdd) { int colTem = col ; int rowTem = row + height ; int filledNum = 0 ; for (int i = 0; i < width; i++) { colTem += i; if (m_mapState[rowTem][colTem] == 1) { filledNum++ ; } } isMove = (filledNum == 0) ? true : false; if (m_pSeleNode->getHeight() == 2) { if (m_pSeleNode->getRow() == 3) { isMove = false ; } } else{ if (m_pSeleNode->getRow() == 4) { isMove = false ; } } } else { int colTem = col ; int rowTem = row - 1 ; int filledNum = 0 ; for (int i = 0; i < width; i++) { colTem += i; if (m_mapState[rowTem][colTem] == 1) { filledNum++ ; } } isMove = (filledNum == 0) ? true : false; if (m_pSeleNode->getRow() == 0)//在最下层的时候,就不能再往下动了 { isMove = false ; } } } return isMove ; } void GameLayer::updateMapData() { resetMapData() ; if (m_pRoleSpriteVec.size() == 10)//<需要10个角色1Boss,5将军,4兵 { for (unsigned int i = 0 ;i < m_pRoleSpriteVec.size() ;i++) { RoleSprite * pRoleSprite = m_pRoleSpriteVec.at(i) ; int width = pRoleSprite->getWidth() ; int heigit = pRoleSprite->getHeight() ; int row = pRoleSprite->getRow() ; int col = pRoleSprite->getCol() ; for (int i = 0 ; i < heigit ; i++) { for (int j = 0 ; j < width ; j++) { m_mapState[row + i][col + j] = 1 ; } } } } /*CCLOG("================Test==========================") ; for (int i = 0; i < 5 ; i++) { const char *ppp = "" ; for (int j = 0; j < 4; j++) { ppp = CCString::createWithFormat("%s%d,",ppp,m_mapState[i][j])->getCString() ; } CCLOG(ppp) ; }*/ } void GameLayer::resetMapData() { for (int row = 0 ;row < 5 ; row++) { for (int col = 0 ; col < 4 ; col++) { m_mapState[row][col] = 0; } } }