【工具類】Cocos 跟蹤導彈


cocos版本:2.4.4

 

Demo地址:跟蹤導彈Demo

 

效果圖:

 

實現原理:

需求是導彈飛到目的地

 

 

cocos坐標系中角度

 

 

通過Math.atan2可以獲得導彈和目的地之間的角度

let missile:cc.Node;      //導彈
let targetPos:cc.Vec2;   //目的地
let radian = Math.atan2(targetPos.y - missile.y, targetPos.x - missile.x);  //導彈和目的地之間弧度
let angle = radian*180/Math.PI;   //弧度轉換成角度

 

 

導彈每幀進行角度旋轉和移動

let moveAngle = 2;                                    //角速度(每幀角度變化)
let moveRadian = moveAngle*Math.PI/180;               //弧度(角速度轉成弧度)
let moveSpeed = 5;                                    //移動速度
missile.angle += moveAngle;                           //角度每幀變化
missile.x += Math.cos(moveRadian)*moveSpeed;          //x變化
missile.y += Math.sin(moveRadian)*moveSpeed;          //y變化

 

導彈位置都到達目的地,那么導彈的追蹤完成。

15是臨近值,如果直接判斷 導彈位置 = 目的地位置,那么導彈可能會在目的地附近不停的抖動。

//判斷導彈和目的地的距離,如果小於一定值(這里取15),則判定到達目的地。
if(cc.Vec2.distance(missile.position,  targetPosition) < 15){
     //導彈到達目的地
} 

  

跟蹤導彈效果就是追着一個位置變化的物體,所以只要不停的改變目的地targetPos,再進行計算就行了。

 

注意點:

由於Math.atan2在邊界值180和-180交接處,從-180瞬間變化到180,或者從180瞬間變化到-180,所以在計算時要處理這種情況,不然導彈會反復繞圈。

 

導彈的代碼:

 

const { ccclass, property } = cc._decorator;

@ccclass
export default class Missile extends cc.Component {

    /**目標地點 */
    public targetPos: cc.Vec2 = new cc.Vec2();
    /**角速度 */
    public angleSpeed: number = 5;
    /**移動速度 */
    public moveSpeed: number = 5;

    /**移動限制距離,相距目的地距離>moveLimit時才會移動,防止抖動 */
    private moveLimit: number = 20;
    /**每幀變化的角度 */
    private stepAngle: number = null;

    /**
     * 設置目標點
     * @param xPos x坐標
     * @param yPos y坐標
     */
    public setTargetPos(xPos: number, yPos: number) {
        this.targetPos.x = xPos;
        this.targetPos.y = yPos;
        this.stepAngle = null;
    }

    /**重置 */
    public reset() {
        this.stepAngle = null;
    }

    update() {
        //距離目的地一定距離才會移動,防止抖動
        if (Math.sqrt(Math.pow(this.node.x - this.targetPos.x, 2) + Math.pow(this.node.y - this.targetPos.y, 2)) > this.moveLimit) {
            //導彈和目標點之間弧度、角度  
            let targetRadian = Math.atan2(this.targetPos.y - this.node.y, this.targetPos.x - this.node.x);
            let targetAngle = targetRadian * 180 / Math.PI;
            //導彈當前角度
            let curAngle = this.node.angle;
            //導彈當前角度和導彈最終指向角度的差
            let distAngle = targetAngle - curAngle;
            //導彈轉動的角速度,根據角度差來判斷順時針或逆時針。( stepAngle=null時才會計算旋轉角度,為了防止導彈出現在邊界值附近左右搖擺的問題,一旦確定旋轉角度方向,則不再改變)
            if (this.stepAngle == null) {
                this.stepAngle = distAngle > 0 ? this.angleSpeed : -this.angleSpeed;
            }
            //臨界值判斷 (Math.atan2會在邊界值位置直接從180變成-180,或-180變成180,導致永遠到不了目標角度)
            if (Math.abs((curAngle + 360) % 360 - (targetAngle + 360) % 360) > (Math.abs(this.stepAngle) + 1)) {
                //角度未達到臨近值才會++,防止抖動
                if (Math.abs(this.node.angle - targetAngle) > (Math.abs(this.stepAngle) + 1)) {
                    this.node.angle += this.stepAngle;
                }
            }
            //移動
            let nextRadian = this.node.angle * Math.PI / 180;
            this.node.x += Math.cos(nextRadian) * this.moveSpeed;
            this.node.y += Math.sin(nextRadian) * this.moveSpeed;
        }
    }
}

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM