关卡数据已经能显示出来了,现在需要添加角色精灵的移动。这就需要添加触屏点击事件。在点击事件中对触屏的进行手势识别,手势识别非常简单,就是判断玩家是想让角色向上移动和是向哪移动。
思路:
两个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,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;
}
}
}