代码还是参考自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学习触摸屏的同学,移动开发,或者触摸屏开发
UE4 socket 数据接收以及发送,功能示例
毕业设计基于C++的一款UE4射击游戏源码。一款UE4射击游戏Demo,包含UE4游戏框架及整套联网射击游戏功能。一款UE4射击游戏Demo,包含UE4游戏框架及整套联网射击游戏功能。一款UE4射击游戏Demo,包含UE4游戏框架及整套...
UE4\UE5在触摸屏上移动、旋转、缩放事件
该工具适用于UE4的触控屏开发,单指,双指,点击缩放等等,功能齐全
实现了通过蓝图把场景中的AStaticMeshActor和两个动态材质实例UMaterialInstanceDynamic 传给c++ 自定义函数参数。 并在自定义函数里面实现两张材质的动态交替变更,其中一张材质还动态加载了本地1.png图片,使得能...
UE4 C++教程 虚幻四C++教程
一个简单实现点击按钮更换图片的UE4C++代码例子,例子很简洁,使用到了简单的UI创建、类型转换等等相关常用的UE4中需要的方法
UE4 C++ 离线API 下载直接使用 无障碍
亲测可用,内涵UE4的插件设置,从此敲C++代码的速度就起飞了
多点触摸屏模拟
Learning C++ by Creating Games With UE4 will start with the basics of C++: installing a code editor so you can begin to write C++ code. You will then learn how to write small, self-contained C++ ...
①:得到线段我们的线段集合S(本次项目鼠标点击得到线段(p1,p2两点)已经在ue4蓝图里面实现,这一步就不过多阐述) ②:移除孤立的线段(两端的点都是孤立的); ③:拆分所有的线段(就是将所有的相交线线段拆...
UE4学习笔记----使用C++之控制球体运动并使用移动粒子效果(源代码)
UE4 Render Target 的使用具体的蓝图应用方法。 从数学原理上讲解 在一个mesh 上画图案的方法
这样写完后放到ue4里面测试,开始比较顺利,当但遇到凹多边形时,就发现问题了。着实一想确实有问题,这样只能判断凸多边形,对于凹多边形时不行的。于是乎查询资料,找到这篇文档 ,按照上面的思路一想确实可行,便...
1.默认关卡中,在函数中填写本地exe程序的绝对路径 2.打开工程前,重新生成VS文件
1. 继承C++类的蓝图类直接调用 2.C++类中的全局函数,任意蓝图都能调用的方式。
将一个多边形的所有点(点数组)按顺序输入,顺逆皆可,将其拆分成多个不重叠的三角形,输出所有三角形的点的index;
TUIO协议下多点触摸的调试工具。