Egret社区

【咸鱼教程】虚拟摇杆

2017-5-4 17:02
19216473
本帖最后由 gamedaybyday 于 2017-5-28 10:20 编辑

教程目录
一 实际效果
二 实现原理
三 Demo下载

一 实际效果

在很多游戏中,都会用到虚拟摇杆
1.jpg


2.jpg

我这里抛砖引玉,做一个简单的Demo

jdfw.gif

二 实现原理

摇杆的实现关键技术点就是通过Math.atan2函数,用触摸位置和摇杆的位置来获取两者的角度(弧度...)

角度 = Math.atan2(触摸点Y - 摇杆Y,  触摸点X - 摇杆X)

3.jpg

再用钩股定理Math.cos和Math.sin计算得到物体的x,y轴上的分速度

x轴分速度 = Math.cos(角度)*物体移动速度
y轴分速度 = Math.sin(角度)*物体移动速度

4.jpg

之后我们根据得到的x,y轴速度,去移动物体就ok了。
物体.x += x轴分速度
物体.y += y轴分速度


虚拟摇杆代码
[mw_shl_code=actionscript3,true]
/**
* 虚拟摇杆
* @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);
        }


}[/mw_shl_code]


在某个场景中使用虚拟摇杆
[mw_shl_code=actionscript3,true]
/**
* 主页场景
* @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;
        }
}[/mw_shl_code]

三 Demo下载
游客,如果您要查看本帖隐藏内容请回复








分享到 :
16 人收藏

473 个回复

倒序浏览
metinyt  圆转纯熟 | 2017-5-4 17:05:08
23king  圆转纯熟 | 2017-5-4 17:28:02
赞,授人鱼不如授人渔, 2个都有!!!!!
一路漫漫  登堂入室 | 2017-5-4 18:24:14
66666666666666666666666666666666
q442816542  初窥堂奥 | 2017-5-4 22:32:01
学习学习
ziwn_vip  炉火纯青 | 2017-5-4 22:45:00
扎心了  老铁
Dante74  炉火纯青 | 2017-5-5 08:47:43
幸魂  初窥堂奥 | 2017-5-5 09:00:19
白蚂蚁  自成一派 | 2017-5-5 09:03:41
vpeeee  登堂入室 | 2017-5-5 09:16:02
厉害了
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|京网文[2014]0791-191号|京ICP证150115号|Egret社区 ( 京ICP备14025619号 )

Powered by Discuz! X3.4 © 2001-2019 Comsenz Inc.

返回顶部