轉自: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是自己定義的宏:
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