华容道06--屏幕点击事件和角色间的碰撞

关卡数据已经能显示出来了,现在需要添加角色精灵的移动。这就需要添加触屏点击事件。在点击事件中对触屏的进行手势识别,手势识别非常简单,就是判断玩家是想让角色向上移动和是向哪移动。

思路:

两个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; 
		}
	}
}



 源码:http://download.csdn.net/detail/c_boy_lu/8594823

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值