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