因為這個是跑酷類游戲的代碼,所以向左向右就按照正常的邏輯,上下滑動本來應該是要執行跳躍操作的,暫時場景屬於靜止狀態,所以先邏輯暫時未拉動攝像機前後移動。
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::vectorcameras = 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); } } }