zoukankan      html  css  js  c++  java
  • Cocos Creator 虚拟摇杆

    版本:2.3.4

    参考:

    【持续更新】Cocos Creator源码分享——针对游戏中的各种功能

    在cocos论坛找了一篇虚拟摇杆的制作文章。但是实际使用还要考虑多一些。这里在原来代码基础上做了一些改动。

    1. 监听事件不使用字符串。例如"touchstart",使用cc.Node.EventType.TOUCH_START。因为使用字符串容易拼错。

    2. 增加触摸响应区域。因为常规游戏中,虚拟摇杆可响应范围不仅仅是虚拟摇杆图片范围,而是一个可根据策划需求调整的范围,例如今天500x400,明天觉得600x400,只需要修改代码,不需要重新制作图片了。

    3. 防止多点触摸。增加了touchID的判断,防止多个手指触摸导致的问题。例如一个手指在操作摇杆,另一个手指不小心在触摸区域点击了一下,导致触发了touch_end,使摇杆失效。

    4. 增加了小圆移动范围设置。原来文章用大圆图片的高宽限制小圆的移动范围。但是大圆图片可能有透明区域,所以这里小圆的移动范围在代码里手动设置。

    5.增加了摇杆是否正在移动的标志位。因为摇杆没有在使用的时候,不需要去执行角色的移动计算。所以增加了moving来表示摇杆是否在运作中,减少摇杆空闲时对角色移动的计算量。

    6.增加了角度(弧度)计算。因为可能根据摇杆的角度,进行一些操作。例如人物如果是八方向或四方向,需要根据角度转向。如果不需要,可以自行屏蔽角度的代码。

    7.增加了enable开关。在虚拟摇杆没有操作的时候,不需要执行update,较少计算量。

    UI如下图,为了方便area用绿色显示,实际使用去掉就行了。

    虚拟摇杆代码

    // Learn TypeScript:
    //  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
    // Learn Attribute:
    //  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
    // Learn life-cycle callbacks:
    //  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html
    
    const {ccclass, property} = cc._decorator;
    
    @ccclass
    export default class JoyStick extends cc.Component {
    
        @property(cc.Node)
        panel:cc.Node = null;   //大圆
    
        @property(cc.Node)
        btn:cc.Node = null;     //小圆
    
        @property(cc.Integer)
        private panelWidth:number = 130;    //去掉透明区域的大圆宽度
    
        private panelInitPos:cc.Vec2; //大圆初始位置
        private touchID:number;    //触摸ID
    
    
        public dir:cc.Vec3 = new cc.Vec3(0,0,0);  //移动方向
        public angle:number = 0;   //弧度(角度)
        public moving:boolean = false; //是否正在移动
    
        onLoad(){
            this.panelInitPos =  new cc.Vec2(this.panel.x, this.panel.y);
            
        }
    
        start () {
            this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
            this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
            this.node.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);
            this.node.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchCancel, this);
        }
    
        public stop(){
            this.node.off(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
            this.node.off(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
            this.node.off(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);
            this.node.off(cc.Node.EventType.TOUCH_CANCEL, this.onTouchCancel, this);
    
            this.moving = false;
            this.enabled = false;
        }
    
        private onTouchStart(e:cc.Touch){
            console.log("start");
            //触摸点世界坐标转成局部坐标
            let pos = this.node.convertToNodeSpaceAR(e.getLocation());
            this.panel.setPosition(pos);
            this.btn.setPosition(0,0);
            this.touchID = e.getID();
    
            this.moving = false;
            this.enabled = true;
        }
    
        private onTouchMove(e:cc.Touch){
            console.log("move");
            if(this.touchID != e.getID()){
                return;
            }
            //小圆移动
            let posDelta = e.getDelta();
            this.btn.x += posDelta.x;
            this.btn.y += posDelta.y;
            //正在移动
            this.moving = true;
        }
    
        update(){
            console.log("update");
            if(this.moving){
                //将小圆限制大圆范围内
                let ratio = this.btn.position.mag() / this.panelWidth;
                if (ratio > 1) {
                    this.btn.setPosition(this.btn.position.div(ratio));
                }
                //获取向量归一化
                this.dir = this.btn.position.normalizeSelf();
                //获取弧度
                this.angle = Math.atan2(this.btn.y, this.btn.x);
            }
        }
    
        private onTouchEnd(e:cc.Touch){
            console.log("end");
            if(this.touchID != e.getID()){
                return;
            }
            this.panel.setPosition(this.panelInitPos);
            this.btn.setPosition(0,0);
            this.moving = false;
            this.enabled = false;
        }
    
        private onTouchCancel(e:cc.Touch){
            console.log("cancel");
            if(this.touchID != e.getID()){
                return;
            }
            this.panel.setPosition(this.panelInitPos);
            this.btn.setPosition(0,0);
            this.moving = false;
            this.enabled = false;
        }
    
        onDestroy(){
            this.stop();
        }
    
    }
    

      

    实际操作

    @ccclass
    export default class Helloworld extends cc.Component {
    
        //虚拟摇杆Area
        @property(cc.Node)
        joyStickArea:cc.Node = null;
        //虚拟摇杆代码
        joyStick:JoyStick;
        //角色
        @property(cc.Node)
        role:cc.Node = null;
        //速度
        speed:cc.Vec2 = new cc.Vec2(5,5);
    
        onLoad(){
            this.joyStick = this.joyStickArea.getComponent(JoyStick);
        }
    
        start() {
           
        }
    
        update(){
            if(this.joyStick.moving){
                //根据角度移动
                // this.role.x += Math.cos(this.joyStick.angle)*this.speed.x;
                // this.role.y += Math.sin(this.joyStick.angle)*this.speed.y;
                //根据向量移动
                this.role.x += this.joyStick.dir.x*this.speed.x;
                this.role.y += this.joyStick.dir.y*this.speed.y;
            }
        }
    }
    

      

    演示效果

  • 相关阅读:
    学会拒绝,把时间用在更重要的事情上
    5G即将到来!我们需要一部怎样的手机呢?
    互联网早期是如何发展起来的?
    程序员需要明白这九件事
    centos7安装出现license information(license not accepted)解决办法
    CentOS6.5下安装MySql5.7.17
    Linux操作系统下MySQL的安装 --转
    SecureCRT_教程--1(windows远程登录linux)
    CentOS-7中安装与配置Tomcat8.5
    CentOS7使用firewalld打开关闭防火墙与端口
  • 原文地址:https://www.cnblogs.com/gamedaybyday/p/13061387.html
Copyright © 2011-2022 走看看