[UE4]触屏设备上的多点触碰检测C++代码实现

代码还是参考自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 );
				}
			}
		}		
	}
}

 

 

 

你可能感兴趣的:(UE4)