一 , 数学准备

    Ⅰ, 三角函数

        

ox1/ox = oy1/oy (相似三角形)

二 , 关于弧度 Math.atan2 在-PI (3,4象限)到 PI(1,2象限) 之间 . 如果要在3,4象限得到正值, 则需要使用 2PI - X的方式. 角度也是一样, 代码如下:

/** * 获取方向弧度 */public getRadian(): number {    if( this.dir.x == 0 && this.dir.y == 0){        return 0;    }    let radian: number =  Math.atan2( this.dir.y ,this.dir.x );    if( radian >= 0 ) return radian;    return 2*Math.PI + radian;}/** * 获取方向角度 */public getAngle(): number{    let angle: number = this.getRadian()/ Math.PI * 180;    if( angle >= 0 ) return angle;    return 360 + angle;}

三, 层级管理器如下

场景设计如下图, 可以看到要把stick限制在bg内需要用到相似三角形的原理, 部分代码如下:

let screenPos: Vec2 = e.getLocation();//获取屏幕坐标(stick所在的)let pos: Vec3 = (this.node.getComponent(UITransform) as UITransform).convertToNodeSpaceAR( v3( screenPos.x, screenPos.y, 0 ));//转joystick和bg一样let len: number = Vec2.len( v2(pos.x,pos.y) );//求模this.dir.x = pos.x / len;//cos xthis.dir.y = pos.y / len;//sin yif( len > this.maxR ){    pos.x = pos.x * this.maxR/len;    pos.y = pos.y * this.maxR/len;}else if( len < this.minR && this.minR > 0){    pos.x = pos.x * this.minR/len;    pos.y = pos.y * this.minR/len;}this.stick.setPosition( pos.x,pos.y);

 

四, 全部代码

import { _decorator, Component, Node, log, EventTouch, Vec2, UITransform, Vec3, v3, v2 } from 'cc';const { ccclass, property } = _decorator;@ccclass('JoyStickCtr')export class JoyStickCtr extends Component {    @property( { type: Node }  )    // @ts-ignore    private stick: Node;    @property    private maxR: number = 128;//最大移动半径    @property    private minR: number = 20;//最小移动半径    //@ts-ignore    private dir: Vec2;    onEnable(){        this.listener( true );    }    onDisable(){        this.listener( false );    }    private listener( isAdd: boolean ): void {        if( isAdd ) {            this.stick.on( Node.EventType.TOUCH_START, this.onTouchHandler, this);            this.stick.on( Node.EventType.TOUCH_MOVE, this.onTouchHandler, this);            this.stick.on( Node.EventType.TOUCH_END, this.onTouchHandler, this);            this.stick.on( Node.EventType.TOUCH_CANCEL, this.onTouchHandler, this);        }else{            this.stick.off( Node.EventType.TOUCH_START, this.onTouchHandler, this);            this.stick.off( Node.EventType.TOUCH_MOVE, this.onTouchHandler, this);            this.stick.off( Node.EventType.TOUCH_END, this.onTouchHandler, this);            this.stick.off( Node.EventType.TOUCH_CANCEL, this.onTouchHandler, this);        }    }    private onTouchHandler( e : EventTouch): void{        switch (e.type){            case Node.EventType.TOUCH_START:                break;            case Node.EventType.TOUCH_MOVE:                let screenPos: Vec2 = e.getLocation();//获取屏幕坐标(stick所在的)                let pos: Vec3 = (this.node.getComponent(UITransform) as UITransform).convertToNodeSpaceAR( v3( screenPos.x, screenPos.y, 0 ));//转joystick和bg一样                let len: number = Vec2.len( v2(pos.x,pos.y) );//求模                this.dir.x = pos.x / len;//cos x                this.dir.y = pos.y / len;//sin y                if( len > this.maxR ){                    pos.x = pos.x * this.maxR/len;                    pos.y = pos.y * this.maxR/len;                }else if( len < this.minR && this.minR > 0){                    pos.x = pos.x * this.minR/len;                    pos.y = pos.y * this.minR/len;                }                this.stick.setPosition( pos.x,pos.y);                break;            case Node.EventType.TOUCH_END:            case Node.EventType.TOUCH_CANCEL:                this.stick.setPosition(0,0);                this.dir.x = this.dir.y = 0;                break;        }    }    /**     * 获取方向向量     */    public getDir(): Vec2{        return this.dir;    }    /**     * 获取方向弧度(0~2PI)     */    public getRadian(): number {        if( this.dir.x == 0 && this.dir.y == 0){            return 0;        }        let radian: number =  Math.atan2( this.dir.y ,this.dir.x );        if( radian >= 0 ) return radian;        return 2*Math.PI + radian;    }    /**     * 获取方向角度(0~360)     */    public getAngle(): number{        let angle: number = this.getRadian()/ Math.PI * 180;        if( angle >= 0 ) return angle;        return 360 + angle;    }    start () {        this.dir = v2(0,0);        // this.listener( true );    }    // update (deltaTime: number) {    //     // [4]    // }}



注: 使用Cocos Creator 3.0.1 引擎

©著作权归作者所有:来自51CTO博客作者Aonaufly的原创作品,谢绝转载,否则将追究法律责任

你的鼓励让我更有动力

赞赏

0人进行了赞赏支持

更多相关文章

  1. 快递物流接口API如何获取第三方电商平台账号授权案例
  2. java中Locks的使用
  3. 初学Redis最清晰完整的教程
  4. Servlet系列教材 (二)- 基础 - 如何获取浏览器提交的参数
  5. SSM框架做前后端分离项目
  6. Springboot 如何做前后端分离?
  7. 配置Hibernate框架过程中遇到的问题及解决方法
  8. PHP获取访问URL指定参数值
  9. 【DB笔试面试739】在Oracle中,如何获取集群的名称(Cluster name)?

随机推荐

  1. android读取raw下面的文件
  2. Android(安卓)之 五大布局案例
  3. Android----Google code android开源项目
  4. Android 新浪微博代码
  5. Java.lang.ClassNotFound Instrumentatio
  6. android 判断service是否开启
  7. android 命令大全
  8. How to install Android SDK and play wi
  9. Android横竖屏切换时,不重新onCreate()的
  10. Android Studio V0.2.x For Windows下载