觸屏裝置上的多點觸碰檢測C++代碼實現

來源:互聯網
上載者:User

標籤:virtual   tar   pre   cas   client   epo   自己實現   ide   代碼   

轉自:http://aigo.iteye.com/blog/2272698

代碼還是參考自Epic官方的塔防項目:StrategyGame

看了下C++的API,現成的API中貌似只支援單點觸碰檢測,用法如下:
註冊:

// support touch devices       InputComponent->BindTouch(EInputEvent::IE_Pressed, this, &ATD_MobilePlayerController::MoveToTouchLocation);      InputComponent->BindTouch(EInputEvent::IE_Repeat, this, &ATD_MobilePlayerController::MoveToTouchLocation);  

觸發回調:

void ATD_MobilePlayerController::MoveToTouchLocation(const ETouchIndex::Type FingerIndex, const FVector Location)  {      FVector2D ScreenSpaceLocation(Location);        // Trace to see what is under the touch location      FHitResult HitResult;      GetHitResultAtScreenPosition(ScreenSpaceLocation, CurrentClickTraceChannel, true, HitResult);      if (HitResult.bBlockingHit)      {          // We hit something, move there          SetNewMoveDestination(HitResult.ImpactPoint);      }  }  

如果要實現多點觸碰檢測,比如實現兩個手指捏動來縮放螢幕,StrategyGame項目自己實現了一套演算法來實現多點螢幕檢測,具體做法如下:
StrategyPlayerController.h

1,先重寫StrategyPlayerController的ProcessPlayerInput()和SetupInputComponent()函數

protected:      /** update input detection */      virtual void ProcessPlayerInput(const float DeltaTime, const bool bGamePaused) override;      virtual void SetupInputComponent() override;  

在SetupInputComponent()函數中綁定事件(這個事件機制也是自己寫的),其中BIND_1P_ACTION和BIND_2P_ACTION是自己定義的宏:

 
void AStrategyPlayerController::SetupInputComponent()  {      Super::SetupInputComponent();        InputHandler = NewObject<UStrategyInput>(this);        BIND_1P_ACTION(InputHandler, EGameKey::Tap, IE_Pressed, &AStrategyPlayerController::OnTapPressed);      BIND_1P_ACTION(InputHandler, EGameKey::Hold, IE_Pressed, &AStrategyPlayerController::OnHoldPressed);      BIND_1P_ACTION(InputHandler, EGameKey::Hold, IE_Released, &AStrategyPlayerController::OnHoldReleased);      BIND_1P_ACTION(InputHandler, EGameKey::Swipe, IE_Pressed, &AStrategyPlayerController::OnSwipeStarted);      BIND_1P_ACTION(InputHandler, EGameKey::Swipe, IE_Repeat, &AStrategyPlayerController::OnSwipeUpdate);      BIND_1P_ACTION(InputHandler, EGameKey::Swipe, IE_Released, &AStrategyPlayerController::OnSwipeReleased);      BIND_2P_ACTION(InputHandler, EGameKey::SwipeTwoPoints, IE_Pressed, &AStrategyPlayerController::OnSwipeTwoPointsStarted);      BIND_2P_ACTION(InputHandler, EGameKey::SwipeTwoPoints, IE_Repeat, &AStrategyPlayerController::OnSwipeTwoPointsUpdate);      BIND_2P_ACTION(InputHandler, EGameKey::Pinch, IE_Pressed, &AStrategyPlayerController::OnPinchStarted);      BIND_2P_ACTION(InputHandler, EGameKey::Pinch, IE_Repeat, &AStrategyPlayerController::OnPinchUpdate);        FInputActionBinding& ToggleInGameMenuBinding = InputComponent->BindAction("InGameMenu", IE_Pressed, this, &AStrategyPlayerController::OnToggleInGameMenu);      ToggleInGameMenuBinding.bExecuteWhenPaused = true;    }  

 

ProcessPlayerInput()來檢測觸碰點變化,這是一個連續執行的函數,大概邏輯是:每次執行時都會把當前的螢幕觸碰資訊和上次的觸碰資訊做對比,檢測是單點觸碰,還是按住不放,還是多點觸碰或多點按住不放等等,具體邏輯在InputHandler->UpdateDetection(DeltaTime);中。

void AStrategyPlayerController::ProcessPlayerInput(const float DeltaTime, const bool bGamePaused)  {      if (!bGamePaused && PlayerInput && InputHandler && !bIgnoreInput)      {          InputHandler->UpdateDetection(DeltaTime);      }        Super::ProcessPlayerInput(DeltaTime, bGamePaused);                if (!bIgnoreInput )      {          const ULocalPlayer* LocalPlayer = Cast<ULocalPlayer>(Player);          AStrategySpectatorPawn* StrategyPawn = GetStrategySpectatorPawn();                if(( StrategyPawn != NULL ) && ( LocalPlayer != NULL ))          {              // Create the bounds for the minimap so we can add it as a ‘no scroll‘ zone.              AStrategyHUD* const HUD = Cast<AStrategyHUD>(GetHUD());              AStrategyGameState const* const MyGameState = GetWorld()->GetGameState<AStrategyGameState>();              if( (MyGameState != NULL ) && ( MyGameState->MiniMapCamera.IsValid() == true ) )              {                  if( LocalPlayer->ViewportClient != NULL )                  {                      const FIntPoint ViewportSize = LocalPlayer->ViewportClient->Viewport->GetSizeXY();                      const uint32 ViewTop = FMath::TruncToInt(LocalPlayer->Origin.Y * ViewportSize.Y);                      const uint32 ViewBottom = ViewTop + FMath::TruncToInt(LocalPlayer->Size.Y * ViewportSize.Y);                        FVector TopLeft( HUD->MiniMapMargin, ViewBottom - HUD->MiniMapMargin - MyGameState->MiniMapCamera->MiniMapHeight, 0 );                      FVector BottomRight( (int32)MyGameState->MiniMapCamera->MiniMapWidth, MyGameState->MiniMapCamera->MiniMapHeight, 0 );                      FBox MiniMapBounds( TopLeft, TopLeft + BottomRight );                      StrategyPawn->GetStrategyCameraComponent()->AddNoScrollZone( MiniMapBounds );                      StrategyPawn->GetStrategyCameraComponent()->UpdateCameraMovement( this );                  }              }          }             }  }  

 

StrategyInput.cpp

void UStrategyInput::UpdateDetection(float DeltaTime)  {      UpdateGameKeys(DeltaTime);      ProcessKeyStates(DeltaTime);  }    void UStrategyInput::UpdateGameKeys(float DeltaTime)  {      AStrategyPlayerController* MyController = CastChecked<AStrategyPlayerController>(GetOuter());        // gather current states      uint32 CurrentTouchState = 0;      for (int32 i = 0; i < ARRAY_COUNT(MyController->PlayerInput->Touches); i++)      {          if (MyController->PlayerInput->Touches[i].Z != 0)          {              CurrentTouchState |= (1 << i);          }      }        // detection      FVector2D LocalPosition1 = FVector2D(MyController->PlayerInput->Touches[0]);      FVector2D LocalPosition2 = FVector2D(MyController->PlayerInput->Touches[1]);        DetectOnePointActions(CurrentTouchState & 1, PrevTouchState & 1, DeltaTime, LocalPosition1, TouchAnchors[0], Touch0DownTime);      DetectTwoPointsActions((CurrentTouchState & 1) && (CurrentTouchState & 2), (PrevTouchState & 1) && (PrevTouchState & 2),          DeltaTime, LocalPosition1, LocalPosition2);        // save states      PrevTouchState = CurrentTouchState;  }    void UStrategyInput::ProcessKeyStates(float DeltaTime)  {      for (const FActionBinding1P& AB : ActionBindings1P)      {          const FSimpleKeyState* KeyState = KeyStateMap.Find(AB.Key);            if (KeyState && KeyState->Events[AB.KeyEvent] > 0)          {              AB.ActionDelegate.ExecuteIfBound(KeyState->Position, KeyState->DownTime);          }      }        for (const FActionBinding2P& AB : ActionBindings2P)      {          const FSimpleKeyState* KeyState = KeyStateMap.Find(AB.Key);            if (KeyState && KeyState->Events[AB.KeyEvent] > 0)          {              AB.ActionDelegate.ExecuteIfBound(KeyState->Position, KeyState->Position2, KeyState->DownTime);          }      }        // update states      for (TMap<EGameKey::Type,FSimpleKeyState>::TIterator It(KeyStateMap); It; ++It)      {          FSimpleKeyState* const KeyState = &It.Value();            if (KeyState->Events[IE_Pressed])          {              KeyState->bDown = true;          }          else if (KeyState->Events[IE_Released])          {              KeyState->bDown = false;          }            FMemory::Memzero(KeyState->Events, sizeof(KeyState->Events));      }  }  

 

 

觸屏裝置上的多點觸碰檢測C++代碼實現

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.