NGUI版虚拟摇杆joystick

http://blog.csdn.net/anyuanlzh/article/details/40107577

下面是我用nui实现的一个虚拟摇杆。

1,示图



2、代码如下,都有比较详细的注释,就不说明了。

[csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. using UnityEngine;  
  2. using System.Collections;  
  3. using System.Collections.Generic;  
  4.   
  5.   
  6. [ExecuteInEditMode]  
  7. public class Joystick : MonoBehaviour  
  8. {      
  9.     #region Delegate & Event  
  10.     public delegate void JoystickEventHandler(Joystick joystick);  
  11.     /// <summary>  
  12.     /// 开如  
  13.     /// </summary>  
  14.     public static event JoystickEventHandler On_JoystickMoveStart;  
  15.     /// <summary>  
  16.     /// Occurs when the joystick move.  
  17.     /// </summary>  
  18.     public static event JoystickEventHandler On_JoystickMove;  
  19.     /// <summary>  
  20.     /// thumb偏离中心位置,并牌按住时,每帧的回调  
  21.     /// </summary>  
  22.     public static event JoystickEventHandler On_JoystickHolding;  
  23.     /// <summary>  
  24.     /// Occurs when the joystick stops move  
  25.     /// </summary>  
  26.     public static event JoystickEventHandler On_JoystickMoveEnd;  
  27.      
  28.     #endregion      
  29.  
  30.     #region   property  
  31.     [SerializeField] bool isRunInEditor = false;  
  32.     [SerializeField]private string joystickName = "NguiJoystick";  
  33.     public string JoystickName { get { return this.joystickName; } }  
  34.     [HideInInspector]private bool isLimitInCircle = true;  
  35.     public bool IsLimitInCircle { get { return this.isLimitInCircle; } }  
  36.     [SerializeField]private int radius = 100;  
  37.     public int Radius { getreturn this.radius; } }  
  38.   
  39.     [SerializeField]  
  40.     private float minAlpha = 0.3f;  
  41.     public float MinAlpha { get { return this.minAlpha; } }  
  42.   
  43.     private Vector2 joystickAxis = Vector2.zero;  
  44.     /// <summary>  
  45.     /// Gets the joystick axis value between -1 & 1...  
  46.     /// </summary>  
  47.     /// <value>  
  48.     /// The joystick axis.  
  49.     /// </value>  
  50.     public Vector2 JoystickAxis { get { return this.joystickAxis; } }  
  51.   
  52.     private Vector2 lastJoystickAxis = Vector2.zero;  
  53.     public Vector2 LastJoystickAxis { get { return this.lastJoystickAxis; } }  
  54.       
  55.     bool isForBid = false;  
  56.     /// <summary>  
  57.     /// 判断joystick是否被禁用  
  58.     /// </summary>  
  59.     public bool IsForBid { get { return this.isForBid; } }  
  60.     bool isHolding = false;  
  61.     public bool IsHolding { get { return this.isHolding; } }  
  62.     #endregion  
  63.   
  64.     UIWidget root;  
  65.     [SerializeField]UISprite bg;  
  66.     [SerializeField]UISprite thumb;  
  67.   
  68.     void Awake()  
  69.     {  
  70.         this.name = this.JoystickName;  
  71.         root = this.GetComponent<UIWidget>();  
  72.         Init();  
  73.     }  
  74.       
  75.       
  76.     // Update is called once per frame     
  77.     void Update ()  
  78.     {  
  79.         if (isRunInEditor && Application.isEditor && !Application.isPlaying)  
  80.         {  
  81.             SetJoystickSize(radius);  
  82.         }  
  83.   
  84.         if (!isForBid && isHolding)  
  85.         {  
  86.             Debug.Log("111111");  
  87.             if (On_JoystickHolding != null)  
  88.             {  
  89.                 On_JoystickHolding(this);  
  90.             }  
  91.         }  
  92.     }  
  93.   
  94.     void Init()  
  95.     {  
  96.         bg.transform.localPosition = Vector3.zero;  
  97.         thumb.transform.localPosition = Vector3.zero;  
  98.         SetJoystickSize(radius);  
  99.         Lighting(minAlpha);  
  100.     }  
  101.  
  102.     #region ngui event  
  103.     / <summary>  
  104.     / test  
  105.     / </summary>  
  106.     //void OnClick ()  
  107.     //{  
  108.     //    Debug.Log("mouse pos :" + Input.mousePosition + " -- touch pos :" + ScreenPos_to_NGUIPos(Input.mousePosition));  
  109.     //    thumb.transform.localPosition = ScreenPos_to_NGUIPos(Input.mousePosition);  
  110.     //}  
  111.     void OnPress (bool isPressed)  
  112.     {  
  113.         if (isForBid)  
  114.         {  
  115.             Debug.Log("joystick is forbid!");  
  116.             return;  
  117.         }  
  118.         Debug.Log("OnPress:" + isPressed.ToString());  
  119.         if(isPressed)  
  120.         {  
  121.             Lighting(1f);  
  122.             CalculateJoystickAxis();  
  123.             if (On_JoystickMoveStart != null)  
  124.             {  
  125.                 On_JoystickMoveStart(this);  
  126.             }  
  127.             isHolding = true;  
  128.         }  
  129.         else  
  130.         {  
  131.             CalculateJoystickAxis();  
  132.             if (On_JoystickMoveEnd != null)  
  133.             {  
  134.                 On_JoystickMoveEnd(this);  
  135.             }  
  136.             thumb.transform.localPosition = Vector3.zero;  
  137.             FadeOut(1f, minAlpha);  
  138.             isHolding = false;  
  139.         }  
  140.     }  
  141.   
  142.     //void OnDragStart ()  
  143.     //{  
  144.     //    if (isForBid)  
  145.     //    {  
  146.     //        Debug.Log("joystick is forbid!");  
  147.     //        return;  
  148.     //    }  
  149.   
  150.     //    Debug.Log("OnDragStart");  
  151.     //    Lighting(1f);  
  152.     //    CalculateJoystickAxis();  
  153.     //    if(On_JoystickMoveStart!=null)  
  154.     //    {  
  155.     //        On_JoystickMoveStart(this);  
  156.     //    }  
  157.     //    isHolding = true;  
  158.     //    Debug.Log(string.Format("time:{0} - axis:{1}", Time.time, joystickAxis));  
  159.     //}  
  160.   
  161.     void OnDrag(Vector2 delta)  
  162.     {  
  163.         if (isForBid)  
  164.         {  
  165.             return;  
  166.         }  
  167.   
  168.         //Debug.Log("OnDrag:"+delta.ToString());          
  169.         CalculateJoystickAxis();  
  170.         if (On_JoystickMoveStart != null)  
  171.         {  
  172.             On_JoystickMoveStart(this);  
  173.         }  
  174.     }  
  175.   
  176.   
  177.     //void OnDragEnd ()  
  178.     //{  
  179.     //    if (isForBid)  
  180.     //    {  
  181.     //        return;  
  182.     //    }  
  183.   
  184.     //    Debug.Log("OnDragEnd");               
  185.     //    CalculateJoystickAxis();  
  186.     //    if (On_JoystickMoveEnd != null)  
  187.     //    {  
  188.     //        On_JoystickMoveEnd(this);  
  189.     //    }  
  190.     //    thumb.transform.localPosition = Vector3.zero;  
  191.     //    FadeOut(1f, minAlpha);  
  192.     //    isHolding = false;  
  193.     //}  
  194.     #endregion  
  195.  
  196.     #region utile  
  197.   
  198.     /// <summary>  
  199.     /// 计算JoystickAxis  
  200.     /// </summary>  
  201.     /// <returns></returns>  
  202.     void CalculateJoystickAxis()  
  203.     {  
  204.         Vector3 offset = ScreenPos_to_NGUIPos(UICamera.currentTouch.pos);  
  205.         offset -= transform.localPosition;  
  206.         if (isLimitInCircle)  
  207.         {  
  208.             if (offset.magnitude > radius)  
  209.             {  
  210.                 offset = offset.normalized * radius;  
  211.             }  
  212.         }  
  213.         thumb.transform.localPosition = offset;  
  214.   
  215.         lastJoystickAxis = joystickAxis;  
  216.         joystickAxis = new Vector2(offset.x / radius, offset.y / radius);  
  217.     }  
  218.   
  219.     /// <summary>  
  220.     /// Axis2s the angle.  
  221.     /// </summary>  
  222.     /// <returns>  
  223.     /// The angle.  
  224.     /// </returns>  
  225.     public float Axis2Angle(bool inDegree = true)  
  226.     {  
  227.         float angle = Mathf.Atan2(joystickAxis.x, joystickAxis.y);  
  228.   
  229.         if (inDegree)  
  230.         {  
  231.             return angle * Mathf.Rad2Deg;  
  232.         }  
  233.         else  
  234.         {  
  235.             return angle;  
  236.         }  
  237.     }  
  238.   
  239.     /// <summary>  
  240.     /// Axis2s the angle.  
  241.     /// </summary>  
  242.     /// <returns>  
  243.     /// The angle.  
  244.     /// </returns>  
  245.     public float Axis2Angle(Vector2 axis, bool inDegree = true)  
  246.     {  
  247.         float angle = Mathf.Atan2(axis.x, axis.y);  
  248.   
  249.         if (inDegree)  
  250.         {  
  251.             return angle * Mathf.Rad2Deg;  
  252.         }  
  253.         else  
  254.         {  
  255.             return angle;  
  256.         }  
  257.     }  
  258.   
  259.   
  260.   
  261.     /// <summary>  
  262.     /// 屏幕坐标-->ui坐标  
  263.     /// </summary>  
  264.     /// <param name="screenPos"></param>  
  265.     /// <returns></returns>  
  266.     Vector3 ScreenPos_to_NGUIPos(Vector3 screenPos)  
  267.     {  
  268.         Vector3 uiPos = UICamera.currentCamera.ScreenToWorldPoint(screenPos);  
  269.         uiPos = UICamera.currentCamera.transform.InverseTransformPoint(uiPos);  
  270.         return uiPos;  
  271.     }  
  272.   
  273.     /// <summary>  
  274.     /// 屏幕坐标-->ngui坐标  
  275.     /// </summary>  
  276.     /// <param name="screenPos"></param>  
  277.     /// <returns></returns>  
  278.     Vector3 ScreenPos_to_NGUIPos(Vector2 screenPos)  
  279.     {  
  280.         return ScreenPos_to_NGUIPos(new Vector3(screenPos.x, screenPos.y, 0f));  
  281.     }  
  282.   
  283.     /// <summary>  
  284.     /// 设置摇杆的大小  
  285.     /// </summary>  
  286.     /// <param name="radius"></param>  
  287.     void SetJoystickSize(int radius)  
  288.     {  
  289.         root.width = 2 * radius;  
  290.         root.height = 2 * radius;  
  291.         thumb.width = (int)(40f / 100f * root.width);  
  292.         thumb.height = (int)(40f / 100f * root.height);  
  293.     }  
  294.   
  295.     /// <summary>  
  296.     /// 点亮摇杆  
  297.     /// </summary>  
  298.     void Lighting(float alpha)  
  299.     {  
  300.         iTween.Stop(this.gameObject, "value");  
  301.         root.alpha = alpha;  
  302.     }  
  303.   
  304.     /// <summary>  
  305.     /// 渐变摇杆的透明度  
  306.     /// </summary>  
  307.     void FadeOut(float fromAlpha, float toAlpha)  
  308.     {  
  309.         Hashtable itweenArgs = new Hashtable();  
  310.         itweenArgs.Add("easetype", iTween.EaseType.linear);  
  311.         itweenArgs.Add("from", fromAlpha);  
  312.         itweenArgs.Add("to", toAlpha);         
  313.         itweenArgs.Add("time", 0.5f);  
  314.         itweenArgs.Add("onupdate""OnFadeOutTween");  
  315.         iTween.ValueTo(this.gameObject, itweenArgs);  
  316.     }  
  317.     void OnFadeOutTween(float value)  
  318.     {  
  319.         root.alpha = value;  
  320.     }  
  321.  
  322.     #endregion  
  323.  
  324.     #region 激活、禁用的控制  
  325.     List<string> keys = new List<string>();  
  326.       
  327.    /// <summary>  
  328.     /// 禁用  
  329.    /// </summary>  
  330.    /// <returns>返回值是,取消这个禁用要用到的key</returns>  
  331.     public string ForbidJosystick()  
  332.     {  
  333.         string key = System.Guid.NewGuid().ToString();  
  334.         keys.Add(key);  
  335.         isForBid = true;  
  336.         return key;  
  337.     }  
  338.   
  339.     /// <summary>  
  340.     /// 启用  
  341.     /// </summary>  
  342.     /// <param name="key"></param>  
  343.     public void ActivizeJosystick(string key)  
  344.     {  
  345.         if(keys.Contains(key))  
  346.         {  
  347.             keys.Remove(key);  
  348.         }  
  349.   
  350.         isForBid = true;  
  351.         if(keys.Count==0)  
  352.         {  
  353.             isForBid = false;  
  354.         }  
  355.     }  
  356.  
  357.     #endregion  
  358. }  
3、demo包,有兴趣的,也可以看看。

        下载:




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在一些手机游戏中,玩家可以通过虚拟控制盘来控制游戏角色的行动。 无人机和玩具操控App中也有这一类控制盘的应用。用自定义View的方式来实现类似手柄的控件。相关代码请见 github.com/RustFisher/…JoystickView特性目前JoystickView特性如下2种风格固定控制盘;浮动跟随模式;控制盘会移动到手指第一次点击的地方可以在背景上添加“箭头”,即添加效果图片自定义的“触摸球”图片和背景图片手指移出了控制盘范围,仍然能够保持追随能获取到移动位置的百分比参数实现思路用自定义View的方式实现这个控制盘。创建TouchView。控制盘的基本要求是跟随手指做出反应。为了获取到手指触屏的坐标,会用到View的onTouchEvent方法。控件中的“触摸球”和背景由图片得来。在自定义view中先获取相应的bitmap,缩放成指定的尺寸。onTouchEvent中获取到相应的坐标,计算出图片应该出现的位置;onDraw中根据坐标进行绘制。 计算出手指位置与控制盘中心的距离等信息,通过listener传递出去。代码示例样式设定有固定和浮动这两种风格,未来可能还会添加public enum PadStyle {     FLOATING /* 随用户手指重新定位 */,     FIXED    /* 固定位置 */ }控制盘配置我们可以不直接操作TouchView,创建TouchViewModel存放相关的配置。    private int bgResId;           // 背景图片资源ID     private int touchBmpResId;     // 触摸图资源ID - 例如一个圆球     private int directionPicResId; // 指示当前触摸点与圆心相对方向的图片ID     private float mWholeViewWid;    // 整个View的宽     private float mWholeViewHeight; // 整个View的高     private float mWholePadWid;    // 盘的宽度,包括箭头;并不是View的总宽度     private float mWholePadHeight; // 盘的高度,包括箭头;并不是View的总宽度     private int mRoundBgRadius;    // 背景圆的半径 背景圆位置可以变化     private int mTouchBallRadius = 100; // 触摸球的半径     private int mRoundBgPadding;   // 背景圆到Pad边界的px  一般是留给方向箭头的位置     private boolean showDirectionPic = false;    // 是否显示指示图片     private PadStyle mPadStyle = PadStyle.FIXED; // 默认为固定位置的     private PadLocationType mPadLocationType = PadLocationType.LEFT_BOT;     // .........控制盘管理器控制盘的配置项比较多,抽象出一个DefaultController来管理控制盘。这个控制器不是必要的。 管理器需要控制盘所在的父View,这里用的是RelativeLayout。创建一个“左控制盘”。将各个尺寸配置传入。最后添加到containerView中。    private void createLeftControlTouchView() {         TouchViewModel model = new TouchViewModel(                 R.drawable.ui_pic_joystick_left_pad,                 R.drawable.ui_pic_joystick_control_ball);         model.setWholeViewSize(ctx.getResources().getDimensionPixelSize(R.dimen.ui_joystick_whole_field_wid),                 ctx.getResources().getDimensionPixelSize(R.dimen.ui_joystick_whole_field_height));         model.setPadSize(ctx.getResources().getDimensionPixelSize(R.dimen.ui_joystick_pad_size),                 ctx.getResources().getDimensionPixelSize(R.dimen.ui_joystick_pad_size));         int roundBgRadius = ctx.getResources().getDimensionPixelSize(R.dimen.ui_joystick_round_bg_radius);         model.setContentSize(roundBgRadius, (int) (roundBgRadius / 3.5));         model.setStyle(padStyle, PadLocationType.LEFT_BOT);         model.setRoundBgPadding(ctx.getResources().getDimensionPixelSize(R.dimen.ui_joystick_circle_bg_padding));         leftControlTouchView = new TouchView(ctx);         leftControlTouchView.init(model);         // View的总大小         RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(                 ctx.getResources().getDimensionPixelSize(R.dimen.ui_joystick_whole_field_wid),                 ctx.getResources().getDimensionPixelSize(R.dimen.ui_joystick_whole_field_height)         );         params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);         params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);         leftControlTouchView.setLayoutParams(params);     }     // ............     createLeftControlTouchView();     containerView.addView(leftControlTouchView);管理器初始化时需要一个ViewGroup来承载控制盘。    public DefaultController(Context context, RelativeLayout containerView, PadStyle padStyle) {         this.ctx = context;         this.containerView = containerView;         this.padStyle = padStyle;     }Fragment中使用初始化管理器初始化管理器,创建控制盘    mDefaultController =             new DefaultController(getContext(),                     (RelativeLayout) root.findViewById(R.id.joystick_container));     mDefaultController.createViews();     mDefaultController.showViews(false);设置监听器,获取用户的操作信息通过控制器来设置监听器        mDefaultController.setLeftTouchViewListener(new JoystickTouchViewListener() {             @Override             public void onTouch(float horizontalPercent, float verticalPercent) {                 Log.d(TAG, "onTouch left: "   horizontalPercent   ", "   verticalPercent);             }             @Override             public void onReset() {                 Log.d(TAG, "onReset: left");             }             @Override             public void onActionDown() {                 Log.d(TAG, "onActionDown: left");             }             @Override             public void onActionUp() {                 Log.d(TAG, "onActionUp: left");             }         });至此,我们实现了一个简单的控制盘控件。在一些控制类应用中可以使用这个控件。若想要做出更优美,更吸引人的控件,需要我们有好的审美水平。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值