C++11代碼展示:簡單的手勢識別和響應,上下左右

因爲這個是跑酷類遊戲的代碼,所以向左向右就按照正常的邏輯,上下滑動本來應該是要執行跳躍操作的,暫時場景屬於靜止狀態,所以先邏輯暫時未拉動攝像機前後移動。


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<Camera*> 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);
		}
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章