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;
            }
        }
    }
    

      

    演示效果

  • 相关阅读:
    (网页)中的简单的遮罩层
    (后端)shiro:Wildcard string cannot be null or empty. Make sure permission strings are properly formatted.
    (网页)jQuery的时间datetime控件在AngularJs中使用实例
    Maven Myeclipse 搭建项目
    MyBatis 环境搭建 (一)
    java 常用方法
    XML 基础
    JS BOM
    js 事件
    js 的使用原则
  • 原文地址:https://www.cnblogs.com/gamedaybyday/p/13061387.html
Copyright © 2011-2022 走看看