`
aigo
  • 浏览: 2626673 次
  • 性别: Icon_minigender_1
  • 来自: 宜昌
社区版块
存档分类
最新评论

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

UE4 
阅读更多

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

 

 

分享到:
评论

相关推荐

    UE4\UE5在触摸屏上移动、旋转、缩放事件

    总的来说,UE4和UE5为开发者提供了丰富的工具和API,以支持在触摸屏设备上实现移动、旋转和缩放等交互操作。通过理解和熟练运用这些功能,可以创建出更加直观和自然的用户体验。在实际项目中,应根据具体需求进行...

    UE4触摸屏,单指旋转,双指缩放,双指移动

    能够实现单指旋转双指缩放,控制相机远近,点击事件按钮,适合UE4学习触摸屏的同学,移动开发,或者触摸屏开发

    UE4触控屏手势输入SDK,单指点击,双指缩放,功能齐全

    在UE4(Unreal Engine 4)中,触控屏手势输入是移动设备和触控设备游戏开发的关键组成部分。UE4触控屏手势输入SDK提供了一整套解决方案,以支持不同类型的触摸操作,如单指点击、双指缩放等,从而丰富用户的交互体验...

    UE4项目触摸输入两点缩放

    在UE4(Unreal Engine 4)中,触摸输入是一种常见的交互方式,特别是在移动设备或支持触控的桌面系统上。"UE4项目触摸输入两点缩放" 是一个专为实现这种交互方式而设计的项目,它允许用户通过在屏幕上同时触摸两个点...

    UE4使用C++在蓝图中实现打开外部exe程序功能(含源码)

    在UE4(Unreal Engine 4)中,开发者经常需要集成各种自定义功能,其中之一就是通过C++代码在蓝图中实现打开外部exe程序。这个功能对于游戏中的交互性或者工具集成非常有用,例如启动辅助编辑器、执行数据分析脚本等...

    UE4 C++开发超好用的VS插件 Visual Assist X 10.9.2301

    Visual Assist X是一款强大的Visual Studio(VS)插件,专为提升C++开发效率而设计,尤其在使用Unreal Engine 4(UE4)时效果显著。这款插件提供了丰富的代码补全、重构、高亮显示、智能感知等功能,极大地提高了...

    UE4 UI简单例子 C++

    在UE4(Unreal Engine 4)中,UI系统基于UMG(Unreal Motion Graphics),它提供了一种可视化的方式去创建用户界面,并且可以与C++代码深度集成。本示例"UE4 UI简单例子 C++"展示了如何利用C++编程语言在UE4中创建一...

    毕业设计基于C++的一款UE4射击游戏源码.zip

    毕业设计基于C++的一款UE4射击游戏源码。一款UE4射击游戏Demo,包含UE4游戏框架及整套联网射击游戏功能。一款UE4射击游戏Demo,包含UE4游戏框架及整套联网射击游戏功能。一款UE4射击游戏Demo,包含UE4游戏框架及整套...

    Unreal Engine 4 UDP 通信C++代码.zip_UE4 socket_UE4 UDP_UE4用UDP_UE4获

    UE4 socket 数据接收以及发送,功能示例

    多点触摸屏模拟

    4. 汽车与工业控制:汽车导航系统、工业自动化设备等也开始采用多点触摸屏,提升操作的直观性和便捷性。 5. 医疗与科研:医疗设备、实验室仪器通过多点触摸屏提供更精细的操作控制。 总的来说,多点触摸屏技术以其...

    UE4蓝图调用C++函数的工程分享

    在UE4(Unreal Engine 4)中,开发者可以结合蓝图和C++代码来构建游戏逻辑,这提供了灵活性和性能的平衡。本工程分享主要关注如何在蓝图中调用C++函数,分为两种主要方式:一是通过继承C++类的蓝图类直接调用,二是...

    UE4学习笔记----使用C++之控制球体运动并使用移动粒子效果(源代码)

    在UE4(Unreal Engine 4)中,游戏对象的行为和交互主要通过C++或蓝图实现。本笔记将深入探讨如何使用C++编程语言来控制球体的运动,并结合移动粒子效果来提升游戏视觉体验。以下是你需要了解的关键知识点: 1. **...

    ue4 c++ 多边形三角化

    在UE4(Unreal Engine 4)中,C++是一种主要的编程语言,用于实现游戏逻辑和自定义功能。在3D图形处理中,多边形的三角化是一个关键步骤,因为大多数现代图形硬件和软件都支持三角形作为基本渲染单元。本教程将深入...

    ue4蓝图c++动态改变staticmeshactor材质例子动态修改纹理

    实现了通过蓝图把场景中的AStaticMeshActor和两个动态材质实例UMaterialInstanceDynamic 传给c++ 自定义函数参数。 并在自定义函数里面实现两张材质的动态交替变更,其中一张材质还动态加载了本地1.png图片,使得能...

    UE4 C++教程 虚幻四C++教程

    UE4 C++教程 虚幻四C++教程

    UE4 电脑ID和获取插件

    在UE4(Unreal Engine 4)开发过程中,有时候我们需要获取电脑的唯一标识符或硬件信息,例如在实现用户认证、设备绑定等场景时。在UE4 4.25及之后的版本中,蓝图系统不再支持直接获取这些信息,这给开发者带来了一定...

    UE4游戏编程蓝图c++语言教程

    虚幻引擎4(UE4)提供了两种主要的编程方式,即C++和蓝图。C++是一种通用的文本编程语言,适合进行底层逻辑和性能敏感的代码编写,而蓝图则是一种图形化编程工具,更适合快速原型设计和游戏逻辑的可视化表达。 在UE...

    UE4vs代码段.zip

    "UE4vs代码段.zip" 文件集合就是这样一个实用资源,它包含了一些预定义的代码片段,可以帮助开发者快速实现特定功能,提高开发效率。 首先,让我们详细了解一下这些代码段的具体内容: 1. **快捷创建碰撞事件的三...

    Learning.C++.by.Creating.Games.with.UE4.Code.zip

    4. **物理模拟**:UE4内置了强大的物理引擎,学习如何使用C++控制物体的运动、碰撞检测和刚体行为,对于创建真实感的游戏至关重要。 5. **图形渲染**:理解材质、着色器和光照模型,以及如何通过C++接口调整它们,...

    UE4 C++ 离线API

    UE4 C++ 离线API 下载直接使用 无障碍

Global site tag (gtag.js) - Google Analytics