C++11代码展示:简单的手势识别和响应,上下左右

2015-07-20 17:05:35 · 作者: · 浏览: 2

因为这个是跑酷类游戏的代码,所以向左向右就按照正常的逻辑,上下滑动本来应该是要执行跳跃操作的,暂时场景属于静止状态,所以先逻辑暂时未拉动摄像机前后移动。

?

C++11的lambda函数实现,用于STL中比较操作。

虽然我明知当前的3D投影视角的摄像机只有一台,对应的pRenderNode查找到的cameraMask的值是camera3D->setCameraFlag(CameraFlag::USER3);设置的,但是以后增加camera做双摄像机操作就会很方便啦。

?

我打算把这次的跑酷实现为,角色模型和摄像机模型完成跳跃操作,主场景只负责动态加载。

摄像机的操作暂时比较简单,每秒固定的位移。

主要的问题在于角色移动有点小问题,角色向前移动的过程中增加一个跳跃操作,这个时候需要动画融合(模型不支持就忽略),物理位移轨迹为双动作,然后切回普通的步行操作。

?

手势识别中默认为单点触控的识别模式,先记录上一次敲击点,在触摸确定为非cancel状态,即end时候,调用此手势。取两点的向量法向,和正右方法向做点乘,正负号可确认偏上下操作。根据左右偏向对比阀值,优先识别为左右滑动操作。

?

?

void PlayerInputController::reveiveTouchBegin(Vec2 pos, Node * pRenderNode)
{
	this->_touchBeginPos = std::move(pos);
}

void PlayerInputController::reveiveTouchEnd(Vec2 pos, Node * pRenderNode)
{
	this->_touchEndPos = std::move(pos);

	Vec2 diff = _touchEndPos - _touchBeginPos;

	diff.normalize();

	auto temp = Vec2(1, 0);//horizontal line

	auto result = Vec2::dot(diff, temp);

	//转向动作抖动阀值,偏移绝对量大于阀值才认定为有效的左右移动
	const float Threshold = std::sqrt(2) / 2;//假如刚好移动方向和水平方位处于45度角(-135°)时,点乘值为sqrt(2)/2,即平行四边形的面积

	if (std::abs(result) > Threshold)
	{
		if (result > 0) // right
		{
			//可以移动 且 不是正执行左右移动操作 Gets an action from the running action list by its tag.
			if (_pPlayer->getCurPlayerSprite()->getPositionX() <= MIDDLE_LINE_POS_X
				&& !_pPlayer->getCurPlayerSprite()->getActionByTag(TURN_LEFT)
				&& !_pPlayer->getCurPlayerSprite()->getActionByTag(TURN_RIGHT)
				)
			{
				auto action = MoveBy::create(0.2f, Vec3(10, 0, 0));
				action->setTag(TURN_RIGHT);
				this->_pPlayer->getCurPlayerSprite()->runAction(action);
			}
		}
		else //left
		{
			//可以移动 且 不是正执行左右移动操作 Gets an action from the running action list by its tag.
			if (_pPlayer->getCurPlayerSprite()->getPositionX() >= MIDDLE_LINE_POS_X
				&& !_pPlayer->getCurPlayerSprite()->getActionByTag(TURN_LEFT)
				&& !_pPlayer->getCurPlayerSprite()->getActionByTag(TURN_RIGHT)
				)
			{
				auto action = MoveBy::create(0.2f, Vec3(-10, 0, 0));
				action->setTag(TURN_LEFT);
				this->_pPlayer->getCurPlayerSprite()->runAction(action);
			}
		}
	}
	else //up or down
	{

#define MOVE_FORWARD(POS_X) 
		auto cameraMask = _pPlayer->getCurPlayerSprite()->getCameraMask();
		
		std::vector
  
    cameras = pRenderNode->getScene()->getCameras();
		
		auto func = [cameraMask](decltype(*cameras.begin()) targetCamera) ->bool
		{
			return ((unsigned short)targetCamera->getCameraFlag() & cameraMask) != 0;
		};
		
		auto it = std::find_if(cameras.begin(), cameras.end(), func);
		while (it != cameras.end())
		{
			auto temp = (*it)->getPosition3D();
			temp.add(Vec3(0, 0, POS_X));
			(*it)->setPosition3D(temp);
			std::find_if(++it, cameras.end(), func);
		}

		if (diff.y > 0)
		{
			MOVE_FORWARD(-5);
		}
		else
		{
			MOVE_FORWARD(5);
		}
	}
}
  


?

?