原由:需要理解异性控件控制,一般的图像控件都是方形的,由于一些需要,做成像摇杆类似的控件控制,将摇杆限制在一个圆内,并且返回对应值。

源码不多,通俗易理解,每个变量作用都有注释

//绘制摇杆两个圆形的TICK函数
void SVirtualJoystick::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
{// 状态判定,是否显示摇杆图像if (State == State_WaitForStart || State == State_CountingDownToStart){CurrentOpacity = 0.f;}else{// lerp to the desired opacity based on whether the user is interacting with the joystick // 根据用户是否与操纵杆交互,调整到所需的不透明度(翻译)// CurrentOpacity默认值为0.1f// GetBaseOpacity()如果激活摇杆时激活状态,则返回1.0f。否则0.1f// 插值类型为Tick每帧时间间隔CurrentOpacity = FMath::Lerp(CurrentOpacity, GetBaseOpacity(), OPACITY_LERP_RATE * InDeltaTime);}// 以上这个IF设置当前不透明的值---*---// count how many controls are active// 计算有多少控件处于活动状态int32 NumActiveControls = 0;// figure out how much to scale the control sizes// 计算控件大小的缩放比例   --->1float ScaleFactor = GetScaleFactor(AllottedGeometry);// 两个摇杆则循环两次for (int32 ControlIndex = 0; ControlIndex < Controls.Num(); ControlIndex++){//获取摇杆信息FControlData& Control = Controls[ControlIndex];// 更新中心位置,则摇杆跟着拇指位置走if (Control.bNeedUpdatedCenter){// 增加摇杆启动的时间Control.ElapsedTime += InDeltaTime;// 当启动时间大于延迟激活时(未激活时)if (Control.ElapsedTime > ActivationDelay){Control.bNeedUpdatedCenter = false;CurrentOpacity = ActiveOpacity;// 如果剧中if (!bPreventReCenter){// 设置摇杆对中的位置Control.VisualCenter = Control.NextCenter;}// 触摸事件HandleTouch(ControlIndex, Control.NextCenter, AllottedGeometry.GetLocalSize());}}// calculate absolute positions based on geometry// @todo: Need to manage geometry changing!//基于几何计算绝对位置//@todo:需要管理几何变化!// 不需要根据几何图形定位控件 or 当前缩放值不等于上次使用缩放值 --->1if (!Control.bHasBeenPositioned || ScaleFactor != PreviousScalingFactor){// 获得摇杆的信息(图片、透明度设置等)const FControlInfo& ControlInfo = Control.Info;// update all the sizes// 校正的实际控制中心Control.CorrectedCenter = FVector2D(ResolveRelativePosition(ControlInfo.Center.X, AllottedGeometry.GetLocalSize().X, ScaleFactor), ResolveRelativePosition(ControlInfo.Center.Y, AllottedGeometry.GetLocalSize().Y, ScaleFactor));// 重新对中位置Control.VisualCenter = Control.CorrectedCenter;// 可在交互大小区域内重新居中的操纵杆的校正大小 --->操纵杆Control.CorrectedVisualSize = FVector2D(ResolveRelativePosition(ControlInfo.VisualSize.X, AllottedGeometry.GetLocalSize().X, ScaleFactor), ResolveRelativePosition(ControlInfo.VisualSize.Y, AllottedGeometry.GetLocalSize().Y, ScaleFactor));// 中心周围可交互区域的校正大小Control.CorrectedInteractionSize = FVector2D(ResolveRelativePosition(ControlInfo.InteractionSize.X, AllottedGeometry.GetLocalSize().X, ScaleFactor), ResolveRelativePosition(ControlInfo.InteractionSize.Y, AllottedGeometry.GetLocalSize().Y, ScaleFactor));// 可以在交互大小区域内重新居中的拇指的校正大小 --->拇指Control.CorrectedThumbSize = FVector2D(ResolveRelativePosition(ControlInfo.ThumbSize.X, AllottedGeometry.GetLocalSize().X, ScaleFactor), ResolveRelativePosition(ControlInfo.ThumbSize.Y, AllottedGeometry.GetLocalSize().Y, ScaleFactor));// 控制输入的校正刻度Control.CorrectedInputScale = ControlInfo.InputScale; // *ScaleFactor;// 是否需要根据几何图形定位控件Control.bHasBeenPositioned = true;}// 有交互 或者 向下一个TICK发送“释放”事件(可能是UNHandled或者Handled)if (Control.CapturedPointerIndex >= 0 || Control.bSendOneMoreEvent){Control.bSendOneMoreEvent = false;// Get the corrected thumb offset scale (now allows ellipse instead of assuming square)// 获得正确的拇指偏移比例(现在允许椭圆而不是假设正方形)--->重点来了!// 2D向量:值为((拇指的X位置*2/摇杆的位置X),(拇指的Y位置*2/摇杆的位置Y))FVector2D ThumbScaledOffset = FVector2D(Control.ThumbPosition.X * 2.0f / Control.CorrectedVisualSize.X, Control.ThumbPosition.Y * 2.0f / Control.CorrectedVisualSize.Y);// 拇指平方和(x*x+y*y)float ThumbSquareSum = ThumbScaledOffset.X * ThumbScaledOffset.X + ThumbScaledOffset.Y * ThumbScaledOffset.Y;// 拇指平方根float ThumbMagnitude = FMath::Sqrt(ThumbSquareSum);// 拇指Norm值FVector2D ThumbNormalized = FVector2D(0.f, 0.f);// 一般不为假,除非手指大过屏幕if (ThumbSquareSum > SMALL_NUMBER){// 限制比例1以内const float Scale = 1.0f / ThumbMagnitude;ThumbNormalized = FVector2D(ThumbScaledOffset.X * Scale, ThumbScaledOffset.Y * Scale);}// Find the scale to apply to ThumbNormalized vector to project onto unit square// 找到要应用于ThumbNormalized向量的比例,以投影到单位正方形上//同样开平方根float ToSquareScale = fabs(ThumbNormalized.Y) > fabs(ThumbNormalized.X) ? FMath::Sqrt((ThumbNormalized.X * ThumbNormalized.X) / (ThumbNormalized.Y * ThumbNormalized.Y) + 1.0f): ThumbNormalized.X == 0.0f ? 1.0f : FMath::Sqrt((ThumbNormalized.Y * ThumbNormalized.Y) / (ThumbNormalized.X * ThumbNormalized.X) + 1.0f);// Apply proportional offset corrected for projection to unit square// 将投影校正的比例偏移应用于单位平方FVector2D NormalizedOffset = ThumbNormalized * Control.CorrectedInputScale * ThumbMagnitude * ToSquareScale;// now pass the fake joystick events to the game// 现在将虚拟操纵杆事件传递给游戏const FGamepadKeyNames::Type XAxis = (Control.Info.MainInputKey.IsValid() ? Control.Info.MainInputKey.GetFName() : (ControlIndex == 0 ? FGamepadKeyNames::LeftAnalogX : FGamepadKeyNames::RightAnalogX));const FGamepadKeyNames::Type YAxis = (Control.Info.AltInputKey.IsValid() ? Control.Info.AltInputKey.GetFName() : (ControlIndex == 0 ? FGamepadKeyNames::LeftAnalogY : FGamepadKeyNames::RightAnalogY));// 设置焦点为活动窗口FSlateApplication::Get().SetAllUserFocusToGameViewport();// 传递控制值(值是轴映射)FSlateApplication::Get().OnControllerAnalog(XAxis, 0, NormalizedOffset.X);FSlateApplication::Get().OnControllerAnalog(YAxis, 0, -NormalizedOffset.Y);}// is this active?if (Control.CapturedPointerIndex != -1){// 记录交互的变量NumActiveControls++;}}// we need to store the computed scale factor so we can compare it with the value computed in the following frame and, if necessary, recompute widget position//我们需要存储计算出的比例因子,以便将其与下一帧中计算出的值进行比较,并在必要时重新计算小部件位置// 下面就不分析了PreviousScalingFactor = ScaleFactor;// STATE MACHINE!if (NumActiveControls > 0 || bPreventReCenter){// any active control snaps the state to active immediatelyState = State_Active;}else{switch (State){case State_WaitForStart:{State = State_CountingDownToStart;Countdown = StartupDelay;}break;case State_CountingDownToStart:// update the countdownCountdown -= InDeltaTime;if (Countdown <= 0.0f){State = State_Inactive;}break;case State_Active:if (NumActiveControls == 0){// start going to inactiveState = State_CountingDownToInactive;Countdown = TimeUntilDeactive;}break;case State_CountingDownToInactive:// update the countdownCountdown -= InDeltaTime;if (Countdown <= 0.0f){// should we start counting down to a control reset?if (TimeUntilReset > 0.0f){State = State_CountingDownToReset;Countdown = TimeUntilReset;}else{// if not, then just go inactiveState = State_Inactive;}}break;case State_CountingDownToReset:Countdown -= InDeltaTime;if (Countdown <= 0.0f){// reset all the controlsfor (int32 ControlIndex = 0; ControlIndex < Controls.Num(); ControlIndex++){Controls[ControlIndex].Reset();}// finally, go inactiveState = State_Inactive;}break;}}
}

当前类还有个OnPaint函数,有机会在分析以下,但是我发现大多数使用了废弃函数,如果要复现起来也是很麻烦

(拉吉CSDN,发发发NM的发文助手)

UE4-分析自带虚拟摇杆TICK函数相关推荐

  1. EasyTouch5 之 Joystick 虚拟摇杆

    一.EasyTouch 资源结构 EasyTouchBundle [插件的根目录] |-EasyTouch [插件核心,核心功能的实现,偏向底层] |-EasyTouchControls [插件控制器 ...

  2. cocos2dx游戏开发学习——虚拟摇杆(8方向)讲解

    写这篇博客的目的主要是记录一下 虚拟摇杆的实现过程.虚拟摇杆一般分文四方向和八方向,也主要根据项目需求来决定.直接进入主题吧. 先上效果图: 方向的思路分析 看图,说先我们可以将8个方向在坐标系中画出 ...

  3. 《Cocos Creator游戏实战》虚拟摇杆实现

    虚拟摇杆实现 摇杆布局实现 摇杆功能实现 用摇杆控制主角 该功能已收录在Many Widgets插件中,使用Cocos Creator 3.x版本的小伙伴可以用该插件快速生成摇杆. 插件地址:http ...

  4. EasyTouch 学习之——ETCJoystick 虚拟摇杆

    ETC Joystick 继承自 ETCBase类, 并且要实现 PointerEnterHandler  IDragHandler, IBeginDragHander IPointerDownHan ...

  5. Cocos 2d-js 虚拟摇杆

    虚拟摇杆是在手机格斗游戏中经常看到的一个东西,用来控制人物的8个方向的行走,今天就来了解一下如何在cocos2d-js实现一个虚拟摇杆... // 虚拟摇杆类型 var ROCKER_TYPE = R ...

  6. Cocos2d-x虚拟摇杆控制精灵上下左右运动----之游戏开发《赵云要格斗》(1)

      这里是Evankaka的博客,欢迎大家前面讨论与交流------      转载请注明出处http://blog.csdn.net/evankaka/article/details/4204350 ...

  7. Cocos2d-x虚拟摇杆控制精灵上下左右运动之————“赵云要格斗”(1)

    转载请注明出处http://blog.csdn.net/evankaka/article/details/42043509 有需要源代码和材料的邮箱留个,这里实现了能通过虚拟摇杆控制精灵的运动,而且能 ...

  8. 【功能实现】手机游戏虚拟摇杆功能实现

    [UNITY3D] 声明: 查API和根据自己的想法实现此功能.如果你喜欢我这个实现,希望你能有所收获,如果你能改进那就更棒了,但如果你想直接拿走,希望标明出处. 只需要把脚本交给画布下的空物体,自行 ...

  9. Unity3D学习日记(二)使用UGUI制作虚拟摇杆控制摄像机

    前天撸了一个简单的UGUI虚拟摇杆,今天我就利用前天做的虚拟摇杆做了一个简单的摄像机控制器,主要看看UGUI虚拟摇杆是否可以完美的控制移动和旋转.(PS:主要是为接下来的项目做技术测试),手游版的CF ...

最新文章

  1. 智源青年科学家林乾:揭开人工智能的黑匣,从解答最基本的问题开始
  2. SpringBoot整合SpringBatch实用简例
  3. 报错:TypeError: can‘t pickle _thread.RLock objects
  4. (转)Java随机数
  5. html5进度条插件 传递参数,Html5进度条插件(自写)
  6. linux ioctl 设备只读,linux – 尝试SSH时设备的ioctl不合适
  7. datax 不识别字段过滤_静电式空气过滤器有什么特点 静电式空气过滤器特点介绍【详解】...
  8. html保存为svg,JavaScript – 将内联SVG保存为JPEG / PNG / SVG
  9. java数组元素的输入_java基础--键盘输入一个数,输出数组中指定元素
  10. ssh: connect to host gitee.com port 22: Connection timed out fatal: Could not read from remote repos
  11. 最简单的java代码【java基本语法】
  12. 服务器中的虚拟化是什么意思,虚拟化是什么意思
  13. outlook2016登录163邮箱教程
  14. 清华大学计算机系2016名单,2016年本科生表彰名单
  15. 澤天夬 (易經大意 韓長庚)
  16. python将姓王的都改成老王_全域明星-第46章:校长姓王,隔壁老王?-爱阅小说网...
  17. 程序猿给娃取名的正确姿势
  18. 呀,要解析的xml文件有1G大,怎么办?
  19. Python周刊505期
  20. python的turtle怎么画曲线_利用 turtle库绘制简单图形

热门文章

  1. bapi (物料主数据导入)的部分基础用法
  2. 51单片机控制系统的人机交互接口设计【51单片机与LED数码管的动态显示接口案例分析】
  3. 1022. Digital Library (30)
  4. 传智黑马Python人工智能15期视频课程
  5. HTML 设置浏览器小图标
  6. 2023南京中医药大学计算机考研信息汇总
  7. 【机器学习】9种回归算法及实例总结,建议学习收藏
  8. 国内外人工智能AI工具网站大全
  9. 智慧农业物联网—解决方案
  10. 【Vue】 组件封装