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

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

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

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

[代码]js代码:

001 ////////////////////////////////////////////////////////////// 
002 // Joystick.js 
003 // Penelope iPhone Tutorial 
004 // 
005 // Joystick creates a movable joystick (via GUITexture) that  
006 // handles touch input, taps, and phases. Dead zones can control 
007 // where the joystick input gets picked up and can be normalized. 
008 // 
009 // Optionally, you can enable the touchPad property from the editor 
010 // to treat this Joystick as a TouchPad. A TouchPad allows the finger 
011 // to touch down at any point and it tracks the movement relatively  
012 // without moving the graphic 
013 ////////////////////////////////////////////////////////////// 
014    
015 @script RequireComponent( GUITexture ) 
016    
017 // A simple class for bounding how far the GUITexture will move 
018 class Boundary  
019
020     var min : Vector2 = Vector2.zero; 
021     var max : Vector2 = Vector2.zero; 
022
023    
024 static private var joysticks : Joystick[];                  // A static collection of all joysticks 
025 static private var enumeratedJoysticks : boolean = false; 
026 static private var tapTimeDelta : float = 0.3;              // Time allowed between taps 
027    
028 var touchPad : boolean;                                     // Is this a TouchPad? 
029 var touchZone : Rect; 
030 var deadZone : Vector2 = Vector2.zero;                      // Control when position is output 
031 var normalize : boolean = false;                            // Normalize output after the dead-zone? 
032 var position : Vector2;                                     // [-1, 1] in x,y 
033 var tapCount : int;                                         // Current tap count 
034    
035 private var lastFingerId = -1;                              // Finger last used for this joystick 
036 private var tapTimeWindow : float;                          // How much time there is left for a tap to occur 
037 private var fingerDownPos : Vector2; 
038 private var fingerDownTime : float; 
039 private var firstDeltaTime : float = 0.5; 
040    
041 private var gui : GUITexture;                               // Joystick graphic 
042 private var defaultRect : Rect;                             // Default position / extents of the joystick graphic 
043 private var guiBoundary : Boundary = Boundary();            // Boundary for joystick graphic 
044 private var guiTouchOffset : Vector2;                       // Offset to apply to touch input 
045 private var guiCenter : Vector2;                            // Center of joystick 
046    
047 function Start() 
048
049     // Cache this component at startup instead of looking up every frame     
050     gui = GetComponent( GUITexture ); 
051        
052     // Store the default rect for the gui, so we can snap back to it 
053     defaultRect = gui.pixelInset;    
054        
055     defaultRect.x += transform.position.x * Screen.width;// + gui.pixelInset.x; // -  Screen.width * 0.5; 
056     defaultRect.y += transform.position.y * Screen.height;// - Screen.height * 0.5; 
057        
058     transform.position.x = 0.0; 
059     transform.position.y = 0.0; 
060            
061     if ( touchPad ) 
062     { 
063         // If a texture has been assigned, then use the rect ferom the gui as our touchZone 
064         if ( gui.texture ) 
065             touchZone = defaultRect; 
066     } 
067     else 
068     {                
069         // This is an offset for touch input to match with the top left 
070         // corner of the GUI 
071         guiTouchOffset.x = defaultRect.width * 0.5; 
072         guiTouchOffset.y = defaultRect.height * 0.5; 
073            
074         // Cache the center of the GUI, since it doesn't change 
075         guiCenter.x = defaultRect.x + guiTouchOffset.x; 
076         guiCenter.y = defaultRect.y + guiTouchOffset.y; 
077            
078         // Let's build the GUI boundary, so we can clamp joystick movement 
079         guiBoundary.min.x = defaultRect.x - guiTouchOffset.x; 
080         guiBoundary.max.x = defaultRect.x + guiTouchOffset.x; 
081         guiBoundary.min.y = defaultRect.y - guiTouchOffset.y; 
082         guiBoundary.max.y = defaultRect.y + guiTouchOffset.y; 
083     } 
084
085    
086 function Disable() 
087
088     gameObject.active = false; 
089     enumeratedJoysticks = false; 
090
091    
092 function ResetJoystick() 
093
094     // Release the finger control and set the joystick back to the default position 
095     gui.pixelInset = defaultRect; 
096     lastFingerId = -1; 
097     position = Vector2.zero; 
098     fingerDownPosition = Vector2.zero; 
099        
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 ,表示 用户触摸摇杆的位置, 上 下 左 右 的信息。

[代码]js代码:

01 //游戏摇杆对象 
02 var moveJoystick : Joystick; 
03    
04 //飞机的贴图 
05 var plan : Texture; 
06    
07 //飞机在屏幕中的坐标 
08 var x = 0; 
09 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 上的效果,通过触摸游戏摇杆可以控制飞机的移动啦,不错吧,哇咔咔~~

 

 

 

责任编辑:冰凝儿
相关推荐

2012-12-24 08:40:12

2012-12-24 08:52:44

iOSUnity3D

2012-12-24 08:46:50

iOSUnity3D

2012-12-24 08:57:35

iOSUnity3D

2012-12-24 09:04:04

iOSUnity3D

2012-12-24 08:50:21

iOSUnity3D

2012-12-24 08:48:25

iOSUnity3D

2012-12-24 08:56:15

iOSUnity3D

2012-12-24 09:07:09

iOSUnity3D

2012-12-24 09:01:41

iOSUnity3D

2012-12-24 08:51:23

iOSUnity3D

2012-12-24 08:54:47

iOSUnity3D

2012-12-24 09:06:14

iOSUnity3D

2012-12-24 09:02:48

iOSUnity3D

2012-12-24 08:45:19

iOSUnity3D

2012-12-24 09:11:58

iOSUnity3D

2012-12-24 09:00:31

iOSUnity3D

2012-12-24 09:17:12

iOSUnity3D

2012-12-24 09:15:57

iOSUnity3D

2013-04-25 00:06:06

unity3D手机游戏引擎
点赞
收藏

51CTO技术栈公众号