Unity3D 游戏引擎之IOS自定义游戏摇杆与飞机平滑的移动

http://blog.csdn.net/xys289187120/article/details/6941061

     移动开发游戏中使用到的触摸游戏摇杆在iPhone上是非常普遍的,毕竟是全触摸屏手机,今天MOMO 通过一个小例子和大家讨论Unity3D 中如何自定义一个漂亮的全触摸游戏摇杆。

 

       值得高兴的是,Unity3D 游戏引擎的标准资源中已经帮助我们封装了一个游戏摇杆脚本,所以实现部分的代码可以完全借助它的,具体调用需要我们自己来。

 

 Joystick.js是官方提供的脚本,具体代码如下,有兴趣的朋友可以仔细研究研究,MOMO就不多说啦。哇咔咔~

 

 

[javascript] view plaincopy
  1. //////////////////////////////////////////////////////////////  
  2. // Joystick.js  
  3. // Penelope iPhone Tutorial  
  4. //  
  5. // Joystick creates a movable joystick (via GUITexture) that   
  6. // handles touch input, taps, and phases. Dead zones can control  
  7. // where the joystick input gets picked up and can be normalized.  
  8. //  
  9. // Optionally, you can enable the touchPad property from the editor  
  10. // to treat this Joystick as a TouchPad. A TouchPad allows the finger  
  11. // to touch down at any point and it tracks the movement relatively   
  12. // without moving the graphic  
  13. //////////////////////////////////////////////////////////////  
  14.   
  15. @script RequireComponent( GUITexture )  
  16.   
  17. // A simple class for bounding how far the GUITexture will move  
  18. class Boundary   
  19. {  
  20.     var min : Vector2 = Vector2.zero;  
  21.     var max : Vector2 = Vector2.zero;  
  22. }  
  23.   
  24. static private var joysticks : Joystick[];                  // A static collection of all joysticks  
  25. static private var enumeratedJoysticks : boolean = false;  
  26. static private var tapTimeDelta : float = 0.3;              // Time allowed between taps  
  27.   
  28. var touchPad : boolean;                                     // Is this a TouchPad?  
  29. var touchZone : Rect;  
  30. var deadZone : Vector2 = Vector2.zero;                      // Control when position is output  
  31. var normalize : boolean = false;                            // Normalize output after the dead-zone?  
  32. var position : Vector2;                                     // [-1, 1] in x,y  
  33. var tapCount : int;                                         // Current tap count  
  34.   
  35. private var lastFingerId = -1;                              // Finger last used for this joystick  
  36. private var tapTimeWindow : float;                          // How much time there is left for a tap to occur  
  37. private var fingerDownPos : Vector2;  
  38. private var fingerDownTime : float;  
  39. private var firstDeltaTime : float = 0.5;  
  40.   
  41. private var gui : GUITexture;                               // Joystick graphic  
  42. private var defaultRect : Rect;                             // Default position / extents of the joystick graphic  
  43. private var guiBoundary : Boundary = Boundary();            // Boundary for joystick graphic  
  44. private var guiTouchOffset : Vector2;                       // Offset to apply to touch input  
  45. private var guiCenter : Vector2;                            // Center of joystick  
  46.   
  47. function Start()  
  48. {  
  49.     // Cache this component at startup instead of looking up every frame      
  50.     gui = GetComponent( GUITexture );  
  51.       
  52.     // Store the default rect for the gui, so we can snap back to it  
  53.     defaultRect = gui.pixelInset;     
  54.       
  55.     defaultRect.x += transform.position.x * Screen.width;// + gui.pixelInset.x; // -  Screen.width * 0.5;  
  56.     defaultRect.y += transform.position.y * Screen.height;// - Screen.height * 0.5;  
  57.       
  58.     transform.position.x = 0.0;  
  59.     transform.position.y = 0.0;  
  60.           
  61.     if ( touchPad )  
  62.     {  
  63.         // If a texture has been assigned, then use the rect ferom the gui as our touchZone  
  64.         if ( gui.texture )  
  65.             touchZone = defaultRect;  
  66.     }  
  67.     else  
  68.     {                 
  69.         // This is an offset for touch input to match with the top left  
  70.         // corner of the GUI  
  71.         guiTouchOffset.x = defaultRect.width * 0.5;  
  72.         guiTouchOffset.y = defaultRect.height * 0.5;  
  73.           
  74.         // Cache the center of the GUI, since it doesn't change  
  75.         guiCenter.x = defaultRect.x + guiTouchOffset.x;  
  76.         guiCenter.y = defaultRect.y + guiTouchOffset.y;  
  77.           
  78.         // Let's build the GUI boundary, so we can clamp joystick movement  
  79.         guiBoundary.min.x = defaultRect.x - guiTouchOffset.x;  
  80.         guiBoundary.max.x = defaultRect.x + guiTouchOffset.x;  
  81.         guiBoundary.min.y = defaultRect.y - guiTouchOffset.y;  
  82.         guiBoundary.max.y = defaultRect.y + guiTouchOffset.y;  
  83.     }  
  84. }  
  85.   
  86. function Disable()  
  87. {  
  88.     gameObject.active = false;  
  89.     enumeratedJoysticks = false;  
  90. }  
  91.   
  92. function ResetJoystick()  
  93. {  
  94.     // Release the finger control and set the joystick back to the default position  
  95.     gui.pixelInset = defaultRect;  
  96.     lastFingerId = -1;  
  97.     position = Vector2.zero;  
  98.     fingerDownPosition = Vector2.zero;  
  99.       
  100.     if ( touchPad )  
  101.         gui.color.a = 0.025;      
  102. }  
  103.   
  104. function IsFingerDown() : boolean  
  105. {  
  106.     return (lastFingerId != -1);  
  107. }  
  108.       
  109. function LatchedFinger( fingerId : int )  
  110. {  
  111.     // If another joystick has latched this finger, then we must release it  
  112.     if ( lastFingerId == fingerId )  
  113.         ResetJoystick();  
  114. }  
  115.   
  116. function Update()  
  117. {     
  118.     if ( !enumeratedJoysticks )  
  119.     {  
  120.         // Collect all joysticks in the game, so we can relay finger latching messages  
  121.         joysticks = FindObjectsOfType( Joystick );  
  122.         enumeratedJoysticks = true;  
  123.     }     
  124.           
  125.     var count = Input.touchCount;  
  126.       
  127.     // Adjust the tap time window while it still available  
  128.     if ( tapTimeWindow > 0 )  
  129.         tapTimeWindow -= Time.deltaTime;  
  130.     else  
  131.         tapCount = 0;  
  132.       
  133.     if ( count == 0 )  
  134.         ResetJoystick();  
  135.     else  
  136.     {  
  137.         for(var i : int = 0;i < count; i++)  
  138.         {  
  139.             var touch : Touch = Input.GetTouch(i);            
  140.             var guiTouchPos : Vector2 = touch.position - guiTouchOffset;  
  141.       
  142.             var shouldLatchFinger = false;  
  143.             if ( touchPad )  
  144.             {                 
  145.                 if ( touchZone.Contains( touch.position ) )  
  146.                     shouldLatchFinger = true;  
  147.             }  
  148.             else if ( gui.HitTest( touch.position ) )  
  149.             {  
  150.                 shouldLatchFinger = true;  
  151.             }         
  152.       
  153.             // Latch the finger if this is a new touch  
  154.             if ( shouldLatchFinger && ( lastFingerId == -1 || lastFingerId != touch.fingerId ) )  
  155.             {  
  156.                   
  157.                 if ( touchPad )  
  158.                 {  
  159.                     gui.color.a = 0.15;  
  160.                       
  161.                     lastFingerId = touch.fingerId;  
  162.                     fingerDownPos = touch.position;  
  163.                     fingerDownTime = Time.time;  
  164.                 }  
  165.                   
  166.                 lastFingerId = touch.fingerId;  
  167.                   
  168.                 // Accumulate taps if it is within the time window  
  169.                 if ( tapTimeWindow > 0 )  
  170.                     tapCount++;  
  171.                 else  
  172.                 {  
  173.                     tapCount = 1;  
  174.                     tapTimeWindow = tapTimeDelta;  
  175.                 }  
  176.                                               
  177.                 // Tell other joysticks we've latched this finger  
  178.                 for ( var j : Joystick in joysticks )  
  179.                 {  
  180.                     if ( j != this )  
  181.                         j.LatchedFinger( touch.fingerId );  
  182.                 }                         
  183.             }                 
  184.       
  185.             if ( lastFingerId == touch.fingerId )  
  186.             {     
  187.                 // Override the tap count with what the iPhone SDK reports if it is greater  
  188.                 // This is a workaround, since the iPhone SDK does not currently track taps  
  189.                 // for multiple touches  
  190.                 if ( touch.tapCount > tapCount )  
  191.                     tapCount = touch.tapCount;  
  192.                   
  193.                 if ( touchPad )  
  194.                 {     
  195.                     // For a touchpad, let's just set the position directly based on distance from initial touchdown  
  196.                     position.x = Mathf.Clamp( ( touch.position.x - fingerDownPos.x ) / ( touchZone.width / 2 ), -1, 1 );  
  197.                     position.y = Mathf.Clamp( ( touch.position.y - fingerDownPos.y ) / ( touchZone.height / 2 ), -1, 1 );  
  198.                 }  
  199.                 else  
  200.                 {                     
  201.                     // Change the location of the joystick graphic to match where the touch is  
  202.                     gui.pixelInset.x =  Mathf.Clamp( guiTouchPos.x, guiBoundary.min.x, guiBoundary.max.x );  
  203.                     gui.pixelInset.y =  Mathf.Clamp( guiTouchPos.y, guiBoundary.min.y, guiBoundary.max.y );       
  204.                 }  
  205.                   
  206.                 if ( touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled )  
  207.                     ResetJoystick();                      
  208.             }             
  209.         }  
  210.     }  
  211.       
  212.     if ( !touchPad )  
  213.     {  
  214.         // Get a value between -1 and 1 based on the joystick graphic location  
  215.         position.x = ( gui.pixelInset.x + guiTouchOffset.x - guiCenter.x ) / guiTouchOffset.x;  
  216.         position.y = ( gui.pixelInset.y + guiTouchOffset.y - guiCenter.y ) / guiTouchOffset.y;  
  217.     }  
  218.       
  219.     // Adjust for dead zone   
  220.     var absoluteX = Mathf.Abs( position.x );  
  221.     var absoluteY = Mathf.Abs( position.y );  
  222.       
  223.     if ( absoluteX < deadZone.x )  
  224.     {  
  225.         // Report the joystick as being at the center if it is within the dead zone  
  226.         position.x = 0;  
  227.     }  
  228.     else if ( normalize )  
  229.     {  
  230.         // Rescale the output after taking the dead zone into account  
  231.         position.x = Mathf.Sign( position.x ) * ( absoluteX - deadZone.x ) / ( 1 - deadZone.x );  
  232.     }  
  233.           
  234.     if ( absoluteY < deadZone.y )  
  235.     {  
  236.         // Report the joystick as being at the center if it is within the dead zone  
  237.         position.y = 0;  
  238.     }  
  239.     else if ( normalize )  
  240.     {  
  241.         // Rescale the output after taking the dead zone into account  
  242.         position.y = Mathf.Sign( position.y ) * ( absoluteY - deadZone.y ) / ( 1 - deadZone.y );  
  243.     }  
  244. }  

 

 

 

 

 

 

单击Create 创建一个GUI Texture,命名为Joy ,它用来显示游戏摇杆,如下图所示将摇杆的图片资源,与摇杆的脚本连线赋值给Joy.  Pixel Inset 中可以设置摇杆的显示位置与显示宽高。

 

 

 

 

 

到这一步 build and run 就可以在iPhone上看到这个游戏摇杆,并且可以通过触摸它,360度平滑过度。

 

 

在屏幕中绘制一个飞机,通过游戏摇杆去控制飞机的移动。

 

创建一个脚本,命名为Main.js 如下图所示  将 Main.js 、joy、plan 分别 绑定在Main Camera 上。

 

 


 

 

moveJoystick.position.x;

moveJoystick.position.y;

 

这两个值是非常重要的两个信息,它们的取值范围是 -1 到 +1 ,表示 用户触摸摇杆的位置, 上 下 左 右 的信息。

 

 

[javascript] view plaincopy
  1. //游戏摇杆对象  
  2. var moveJoystick : Joystick;  
  3.   
  4. //飞机的贴图  
  5. var plan : Texture;  
  6.   
  7. //飞机在屏幕中的坐标  
  8. var x = 0;  
  9. var y = 0;  
  10.   
  11. //避免飞机飞出屏幕,分别是X、Y最大坐标,最小坐标是0、0  
  12. var cross_x = 0;  
  13. var cross_y = 0;  
  14.   
  15. //飞机移动的速度  
  16. var planSpeed = 20;  
  17.   
  18. function Start() {  
  19.     //初始化赋值  
  20.     x = 100;  
  21.     y = 100;  
  22.     cross_x = Screen.width -  plan.width;  
  23.     cross_y = Screen.height -  plan.height;  
  24.       
  25. }  
  26.   
  27. function Update () {  
  28.     //得到游戏摇杆的反馈信息,得到的值是 -1 到 +1 之间  
  29.       
  30.     var touchKey_x =  moveJoystick.position.x;  
  31.     var touchKey_y =  moveJoystick.position.y;  
  32.       
  33.     //摇杆向左  
  34.     if(touchKey_x == -1){  
  35.         x -= planSpeed;  
  36.           
  37.     }  
  38.     //摇杆向右  
  39.     else if(touchKey_x == 1){  
  40.         x += planSpeed;  
  41.           
  42.     }  
  43.     //摇杆向上  
  44.     if(touchKey_y == -1){  
  45.         y += planSpeed;  
  46.           
  47.     }  
  48.     //摇杆向下  
  49.     else if(touchKey_y == 1){  
  50.         y -= planSpeed;  
  51.           
  52.     }  
  53.       
  54.     //防止飞机飞出屏幕,出界检测  
  55.     if(x < 0){  
  56.         x = 0;  
  57.     }else if(x > cross_x){  
  58.         x = cross_x;  
  59.     }  
  60.       
  61.     if(y < 0){  
  62.         y = 0;  
  63.     }else if(y > cross_y){  
  64.         y = cross_y;  
  65.     }  
  66. }  
  67.   
  68.   
  69.   
  70.   
  71. function OnGUI () {  
  72.   
  73.   
  74.   //将飞机绘制在屏幕中  
  75.   GUI.DrawTexture(Rect(x,y,128,128),plan);    
  76.   
  77. }  



 

导出 build and run  看看在iPhone 上的效果,通过触摸游戏摇杆可以控制飞机的移动啦,不错吧,哇咔咔~~

 

 

 

 

 

 

 

最后欢迎各位盆友可以和MOMO一起讨论Unity3D游戏开发,最近感冒的盆友越来越多,大家要多多注意身体健康噢。哇咔咔~~~ 附上Unity3D工程的下载地址,Xcode项目我就不上传了,须要的自己导出。

 

下载地址:http://www.xuanyusong.com/archives/526

posted @ 2013-04-09 10:51  songtzu  阅读(274)  评论(0编辑  收藏  举报