Advertisement
napland

N_joystick.cs

Sep 6th, 2015
208
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 11.73 KB | None | 0 0
  1. using UnityEngine;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5.  
  6.  
  7. public class Boundary
  8. {
  9.     public Vector2 min = Vector2.zero;
  10.     public Vector2 max = Vector2.zero;
  11. }
  12.  
  13.  
  14. [RequireComponent(typeof(GUITexture))]
  15. public class N_Joystick : MonoBehaviour
  16. {
  17.     public bool showDebug = false;
  18.  
  19.     /* Is this joystick a TouchPad? */
  20.     public bool touchPad = false;
  21.     /* In case the joystick is a touchPad, should its GUI be faded when inactive? */
  22.     public bool fadeGUI = false;
  23.     /* Control when position is output */
  24.     public Vector2 deadZone = Vector2.zero;
  25.     /* Normalize output after the dead-zone? */
  26.     public bool normalize = false;
  27.     /* Current tap count */
  28.     public int tapCount = -1;
  29.  
  30.     /* The touchZone of the joystick */
  31.     private Rect touchZone;
  32.  
  33.     /* Finger last used on this joystick */
  34.     private int lastFingerId = -1;
  35.     /* How much time there is left for a tap to occur */
  36.     private float tapTimeWindow;
  37.     private Vector2 fingerDownPos;
  38.     /*
  39.      * Currently unused.
  40.     private float fingerDownTime;
  41.     */
  42.     private float firstDeltaTime;
  43.  
  44.     /* Joystick graphic */
  45.     private GUITexture gui;
  46.     /* Default position / extents of the joystick graphic */
  47.     private Rect defaultRect;
  48.     /* Boundary for joystick graphic */
  49.     private Boundary guiBoundary = new Boundary();
  50.     /* Offset to apply to touch input */
  51.     private Vector2 guiTouchOffset;
  52.     /* Center of joystick */
  53.     private Vector2 guiCenter;
  54.  
  55.     public bool isFingerDown
  56.     {
  57.         get
  58.         {
  59.             return (lastFingerId != -1);
  60.         }
  61.     }
  62.  
  63.     public int latchedFinger
  64.     {
  65.         set
  66.         {
  67.             /* If another joystick has latched this finger, then we must release it */
  68.             if (lastFingerId == value)
  69.             {
  70.                 Restart();
  71.             }
  72.         }
  73.  
  74.         get
  75.         {
  76.             return lastFingerId;
  77.         }
  78.     }
  79.  
  80.     /* The position of the joystick on the screen ([-1, 1] in x,y) for clients to read. */
  81.     public Vector2 position
  82.     {
  83.         get;
  84.         private set;
  85.     }
  86.  
  87.     void OnGUI()
  88.     {
  89.         if(showDebug)
  90.         {
  91.             string label = "joystick pos: " + position.ToString();
  92.             GUI.Label(new Rect(0, 0, 400, 200), label);
  93.         }
  94.     }
  95.  
  96.  
  97.     private static string joysticksTag = "joystick";
  98.     /* A static collection of all joysticks */
  99.     private static List<N_Joystick> joysticks;
  100.     /* Has the joysticks collection been enumerated yet? */
  101.     private static bool enumeratedJoysticks = false;
  102.     /* Time allowed between taps */
  103.     private static float tapTimeDelta = 0.3f;
  104.  
  105.  
  106.     private void Reset()
  107.     {
  108.         try
  109.         {
  110.             gameObject.tag = joysticksTag;
  111.         }
  112.         catch (Exception)
  113.         {
  114.             Debug.LogError("The \"" + joysticksTag + "\" tag has not yet been defined in the Tag Manager.");
  115.             throw;
  116.         }
  117.     }
  118.  
  119.  
  120.     private void Awake()
  121.     {
  122.         gui = GetComponent<GUITexture>();
  123.         if (gui.texture == null)
  124.         {
  125.             Debug.LogError("Joystick object requires a valid texture!");
  126.             gameObject.SetActive(false);
  127.             return;
  128.         }
  129.  
  130.         if (!enumeratedJoysticks)
  131.         {
  132.             try
  133.             {
  134.                 /* Collect all joysticks in the game, so we can relay finger latching messages */
  135.                 GameObject[] objs = GameObject.FindGameObjectsWithTag(joysticksTag);
  136.                 joysticks = new List<N_Joystick>(objs.Length);
  137.                 foreach (GameObject obj in objs)
  138.                 {
  139.                     N_Joystick newJoystick = obj.GetComponent<N_Joystick>();
  140.                     if (newJoystick == null)
  141.                     {
  142.                         throw new NullReferenceException("Joystick gameObject found without a suitable Joystick component.");
  143.                     }
  144.                     joysticks.Add(newJoystick);
  145.                 }
  146.                 enumeratedJoysticks = true;
  147.             }
  148.             catch (Exception exp)
  149.             {
  150.                 Debug.LogError("Error collecting Joystick objects: " + exp.Message);
  151.                 throw;
  152.             }
  153.         }
  154.  
  155.         /* Store the default rect for the gui, so we can snap back to it */
  156.         defaultRect = gui.pixelInset;
  157.  
  158.         defaultRect.x += transform.position.x * Screen.width;// + gui.pixelInset.x; // -  Screen.width * 0.5f;
  159.         defaultRect.y += transform.position.y * Screen.height;// - Screen.height * 0.5f;
  160.  
  161.         transform.position = new Vector3(0, 0, transform.position.z);
  162.  
  163.         if (touchPad)
  164.         {
  165.             /* Use the rect from the gui as our touchZone */
  166.             touchZone = defaultRect;
  167.         }
  168.         else
  169.         {
  170.             /* This is an offset for touch input to match with the top left corner of the GUI */
  171.             guiTouchOffset.x = defaultRect.width * 0.5f;
  172.             guiTouchOffset.y = defaultRect.height * 0.5f;
  173.  
  174.             /* Cache the center of the GUI, since it doesn't change */
  175.             guiCenter.x = defaultRect.x + guiTouchOffset.x;
  176.             guiCenter.y = defaultRect.y + guiTouchOffset.y;
  177.  
  178.             /* Let's build the GUI boundary, so we can clamp joystick movement */
  179.             guiBoundary.min.x = defaultRect.x - guiTouchOffset.x;
  180.             guiBoundary.max.x = defaultRect.x + guiTouchOffset.x;
  181.             guiBoundary.min.y = defaultRect.y - guiTouchOffset.y;
  182.             guiBoundary.max.y = defaultRect.y + guiTouchOffset.y;
  183.         }
  184.  
  185.     }
  186.  
  187.  
  188.     public void Enable()
  189.     {
  190.         enabled = true;
  191.     }
  192.  
  193.  
  194.     public void Disable()
  195.     {
  196.         enabled = false;
  197.     }
  198.  
  199.  
  200.     public void Restart()
  201.     {
  202.         /* Release the finger control and set the joystick back to the default position */
  203.         gui.pixelInset = defaultRect;
  204.         lastFingerId = -1;
  205.         position = Vector2.zero;
  206.         fingerDownPos = Vector2.zero;
  207.  
  208.         if (touchPad && fadeGUI)
  209.         {
  210.             gui.color = new Color(gui.color.r, gui.color.g, gui.color.b, 0.025f);
  211.         }
  212.     }
  213.  
  214.  
  215.     private void Update()
  216.     {
  217.  
  218.         int count = Input.touchCount;
  219.  
  220.         /* Adjust the tap time window while it still available */
  221.         if (tapTimeWindow > 0)
  222.         {
  223.             tapTimeWindow -= Time.deltaTime;
  224.         }
  225.         else
  226.         {
  227.             tapCount = 0;
  228.         }
  229.  
  230.         if (count == 0)
  231.         {
  232.             Restart();
  233.         }
  234.         else
  235.         {
  236.             for (int i = 0; i < count; i++)
  237.             {
  238.                 Touch touch = Input.GetTouch(i);
  239.                 Vector2 guiTouchPos = touch.position - guiTouchOffset;
  240.  
  241.                 bool shouldLatchFinger = false;
  242.                 if (touchPad && touchZone.Contains(touch.position))
  243.                 {
  244.                     shouldLatchFinger = true;
  245.                 }
  246.                 else if (gui.HitTest(touch.position))
  247.                 {
  248.                     shouldLatchFinger = true;
  249.                 }
  250.  
  251.                 /* Latch the finger if this is a new touch */
  252.                 if (shouldLatchFinger && (lastFingerId == -1 || lastFingerId != touch.fingerId))
  253.                 {
  254.  
  255.                     if (touchPad)
  256.                     {
  257.                         if (fadeGUI)
  258.                         {
  259.                             gui.color = new Color(gui.color.r, gui.color.g, gui.color.b, 0.15f);
  260.                         }
  261.                         lastFingerId = touch.fingerId;
  262.                         fingerDownPos = touch.position;
  263.                         /*
  264.                          * Currently unused.
  265.                         fingerDownTime = Time.time;
  266.                         */
  267.                     }
  268.  
  269.                     lastFingerId = touch.fingerId;
  270.  
  271.                     /* Accumulate taps if it is within the time window */
  272.                     if (tapTimeWindow > 0)
  273.                     {
  274.                         tapCount++;
  275.                     }
  276.                     else
  277.                     {
  278.                         tapCount = 1;
  279.                         tapTimeWindow = tapTimeDelta;
  280.                     }
  281.  
  282.                     /* Tell other joysticks we've latched this finger */
  283.                     foreach (N_Joystick j in joysticks)
  284.                     {
  285.                         if (j == this)
  286.                         {
  287.                             continue;
  288.                         }
  289.                         j.latchedFinger = touch.fingerId;
  290.                     }
  291.                 }
  292.  
  293.                 if (lastFingerId == touch.fingerId)
  294.                 {
  295.                     /*
  296.                         Override the tap count with what the iOS SDK reports if it is greater.
  297.                         This is a workaround, since the iOS SDK does not currently track taps
  298.                         for multiple touches.
  299.                     */
  300.                     if (touch.tapCount > tapCount)
  301.                     {
  302.                         tapCount = touch.tapCount;
  303.                     }
  304.  
  305.                     if (touchPad)
  306.                     {
  307.                         /* For a touchpad, let's just set the position directly based on distance from initial touchdown */
  308.                         position = new Vector2
  309.                             (
  310.                               Mathf.Clamp((touch.position.x - fingerDownPos.x) / (touchZone.width / 2), -1, 1),
  311.                               Mathf.Clamp((touch.position.y - fingerDownPos.y) / (touchZone.height / 2), -1, 1)
  312.                             );
  313.                     }
  314.                     else
  315.                     {
  316.                         /* Change the location of the joystick graphic to match where the touch is */
  317.                         gui.pixelInset = new Rect
  318.                             (
  319.                               Mathf.Clamp(guiTouchPos.x, guiBoundary.min.x, guiBoundary.max.x),
  320.                               Mathf.Clamp(guiTouchPos.y, guiBoundary.min.y, guiBoundary.max.y),
  321.                               gui.pixelInset.width,
  322.                               gui.pixelInset.height
  323.                             );
  324.                     }
  325.  
  326.                     if (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled)
  327.                     {
  328.                         Restart();
  329.                     }
  330.                 }
  331.             }
  332.  
  333.         }
  334.  
  335.         if (!touchPad)
  336.         {
  337.             /* Get a value between -1 and 1 based on the joystick graphic location */
  338.             position = new Vector2
  339.                 (
  340.                   (gui.pixelInset.x + guiTouchOffset.x - guiCenter.x) / guiTouchOffset.x,
  341.                   (gui.pixelInset.y + guiTouchOffset.y - guiCenter.y) / guiTouchOffset.y
  342.                 );
  343.         }
  344.  
  345.         /* Adjust for dead zone */
  346.         float absoluteX = Mathf.Abs(position.x);
  347.         float absoluteY = Mathf.Abs(position.y);
  348.  
  349.         if (absoluteX < deadZone.x)
  350.         {
  351.             /* Report the joystick as being at the center if it is within the dead zone */
  352.             position = new Vector2(0, position.y);
  353.         }
  354.         else if (normalize)
  355.         {
  356.             /* Rescale the output after taking the dead zone into account */
  357.             position = new Vector2(Mathf.Sign(position.x) * (absoluteX - deadZone.x) / (1 - deadZone.x), position.y);
  358.         }
  359.  
  360.         if (absoluteY < deadZone.y)
  361.         {
  362.             /* Report the joystick as being at the center if it is within the dead zone */
  363.             position = new Vector2(position.x, 0);
  364.         }
  365.         else if (normalize)
  366.         {
  367.             /* Rescale the output after taking the dead zone into account */
  368.             position = new Vector2(position.x, Mathf.Sign(position.y) * (absoluteY - deadZone.y) / (1 - deadZone.y));
  369.         }
  370.     }
  371. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement