教程目录
一 实际效果
二 实现原理
三 Demo下载
一 实际效果
在很多游戏中,都会用到虚拟摇杆
我这里抛砖引玉,做一个简单的Demo
二 实现原理
摇杆的实现关键技术点就是通过Math.atan2函数,用触摸位置和摇杆的位置来获取两者的角度(弧度...)。
角度 = Math.atan2(触摸点Y - 摇杆Y, 触摸点X - 摇杆X)
再用钩股定理Math.cos和Math.sin计算得到物体的x,y轴上的分速度
x轴分速度 = Math.cos(角度)*物体移动速度
y轴分速度 = Math.sin(角度)*物体移动速度
之后我们根据得到的x,y轴速度,去移动物体就ok了。
物体.x += x轴分速度
物体.y += y轴分速度
虚拟摇杆代码
[Actionscript3] 纯文本查看 复制代码
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
|
/** * 虚拟摇杆 * @author chenkai * @since 2017/5/4 */ class VirtualJoystick extends eui.Component{ private ball:eui.Image; //圆环 private circle:eui.Image; //小球 private circleRadius:number = 0 ; //圆环半径 private ballRadius:number = 0 ; //小球半径 private centerX:number = 0 ; //中心点坐标 private centerY:number = 0 ; private touchID:number; //触摸ID public constructor() { super (); this .skinName = "VirtualJoystickSkin" ; } public childrenCreated(){ //获取圆环和小球半径 this .circleRadius = this .circle.height/ 2 ; this .ballRadius = this .ball.height/ 2 ; //获取中心点 this .centerX = this .circleRadius; this .centerY = this .circleRadius; //设置锚点 this .anchorOffsetX = this .circleRadius; this .anchorOffsetY = this .circleRadius; //设置小球初始位置 this .ball.x = this .centerX; this .ball.y = this .centerY; } //启动虚拟摇杆 (监听事件根据实际情况设置,不然点一下UI上的其他按钮,也会触发虚拟摇杆事件。这里只是做demo,就没那么讲究了 - -!) public start(){ GameConst.stage.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this .onTouchBegin, this ); GameConst.stage.addEventListener(egret.TouchEvent.TOUCH_END, this .onTouchEnd, this ); GameConst.stage.addEventListener(egret.TouchEvent.TOUCH_MOVE, this .onTouchMove, this ); } //停止虚拟摇杆 public stop(){ GameConst.stage.removeEventListener(egret.TouchEvent.TOUCH_BEGIN, this .onTouchBegin, this ); GameConst.stage.removeEventListener(egret.TouchEvent.TOUCH_END, this .onTouchEnd, this ); GameConst.stage.removeEventListener(egret.TouchEvent.TOUCH_MOVE, this .onTouchMove, this ); } //触摸开始,显示虚拟摇杆 private onTouchBegin(e:egret.TouchEvent){ if ( this .parent){ return ; } this .touchID = e.touchPointID; this .x = e.stageX; this .y = e.stageY; this .ball.x = this .centerX; this .ball.y = this .centerY; GameConst.stage.addChild( this ); this .dispatchEvent( new egret.Event( "vj_start" )); } //触摸结束,隐藏虚拟摇杆 private onTouchEnd(e:egret.TouchEvent){ if ( this .touchID != e.touchPointID){ return ; } this .hide(); this .dispatchEvent( new egret.Event( "vj_end" )); } //触摸移动,设置小球的位置 private p1:egret.Point = new egret.Point(); private p2:egret.Point = new egret.Point(); private onTouchMove(e:egret.TouchEvent){ if ( this .touchID != e.touchPointID){ return ; } //获取手指和虚拟摇杆的距离 this .p1.x = this .x; this .p1.y = this .y; this .p2.x = e.stageX; this .p2.y = e.stageY; var dist = egret.Point.distance( this .p1, this .p2); var angle:number = Math.atan2(e.stageY - this .y, e.stageX - this .x); //手指距离在圆环范围内 if (dist <= ( this .circleRadius - this .ballRadius)){ this .ball.x = this .centerX + e.stageX - this .x; this .ball.y = this .centerY + e.stageY - this .y; //手指距离在圆环范围外 } else { this .ball.x = Math.cos(angle)*( this .circleRadius - this .ballRadius) + this .centerX; this .ball.y = Math.sin(angle)*( this .circleRadius - this .ballRadius) + this .centerY; } //派发事件 this .dispatchEventWith( "vj_move" , false , angle); } private hide(){ this .parent && this .parent.removeChild( this ); } } |
在某个场景中使用虚拟摇杆
[Actionscript3] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
/** * 主页场景 * @author chenkai * @since 2017/5/4 */ class HomeScene extends eui.Component{ private vj:VirtualJoystick = new VirtualJoystick(); //虚拟摇杆 private player:eui.Rect; //人物 private speedX = 0 ; //人物移动速度 private speedY = 0 ; private speed = 10 ; public constructor() { super (); this .skinName = "HomeSceneSkin" ; } public childrenCreated(){ //开启虚拟摇杆 this .vj.start(); this .vj.addEventListener( "vj_start" , this .onStart, this ); this .vj.addEventListener( "vj_move" , this .onChange, this ); this .vj.addEventListener( "vj_end" , this .onEnd, this ); } //摇杆启动,人物开始根据摇杆移动 private onStart(){ this .addEventListener(egret.Event.ENTER_FRAME, this .onEnterFrame, this ); } //触摸摇杆的角度改变,人物的移动速度方向也随之改变 private onChange(e:egret.Event){ var angle = e.data; this .speedX = Math.cos(angle)* this .speed; this .speedY = Math.sin(angle)* this .speed; } //停止摇杆,人物停止移动 private onEnd(){ this .removeEventListener(egret.Event.ENTER_FRAME, this .onEnterFrame, this ); } //每帧更新,人物移动 private onEnterFrame(){ this .player.x += this .speedX; this .player.y += this .speedY; } } |