最近搜索

第9节 让小车实现拐弯运动,绕行运动

浏览:633
管理员 2021-10-21 16:02


设计路径  在最后添加转弯

image.png


我们可以把小车初始化到,最后一个点。来测试  转弯。







image.png



设置小车转弯的轴心 这是顺时针转弯,逆时针 原理一样。

image.png

添加变量

image.png


    private _originRotation = 0 ;//初始 旋转
    private _targetRotation = 0;//
    private _centerPoint  = new Vec3();//要绕的点
    private _rotMeasure = 0 ;



private _arrivalStation() {
        console.log("arrival....");
        this._pointA.set(this._pointB);

        //这个就是B上面的  RoadPoint   
        this._currentRoadPoint = this._currentRoadPoint?.nextStation?.getComponent(RoadPoint) as RoadPoint;
        if (this._currentRoadPoint?.nextStation) {
            this._pointB.set(this._currentRoadPoint.nextStation.worldPosition);

            //判断下一个点是不是 转弯
            if(this._currentRoadPoint.move_type==RoadPoint.RoadMoveType.BEND){
                if(this._currentRoadPoint.clockwise){
                    //顺时针   _conversion  正90  负90  统一弄成  正数。
                    this._originRotation = this._conversion(this.node.eulerAngles.y);//这段代码没有看太明白 。
                    this._targetRotation = this._originRotation - 90;
                    

                    //这是判断 转弯的中心轴
                    if((this._pointB.z<this._pointA.z&&this._pointB.x>this._pointA.x)||
                       (this._pointB.z>this._pointA.z&&this._pointB.x<this._pointA.x)){
                        //这是上下 转弯(其实就是2条路的左右转弯)
                        this._centerPoint.set(this._pointB.x,0,this._pointA.z);
                    }else{
                        //这是左右转弯(其实就是2条路的左右转弯)
                        this._centerPoint.set(this._pointA.x,0,this._pointB.z);
                    }

                }else{
                    //逆时针
                    this._originRotation = this._conversion(this.node.eulerAngles.y);//这段代码没有看太明白 。
                    this._targetRotation = this._originRotation + 90;

                     //这是判断 转弯的中心轴
                     if((this._pointB.z>this._pointA.z&&this._pointB.x>this._pointA.x)||
                     (this._pointB.z<this._pointA.z&&this._pointB.x<this._pointA.x)){
                      //这是上下 转弯(其实就是2条路的左右转弯)
                      this._centerPoint.set(this._pointB.x,0,this._pointA.z);
                  }else{
                      //这是左右转弯(其实就是2条路的左右转弯)
                      this._centerPoint.set(this._pointA.x,0,this._pointB.z);
                  }
                }

                //计算半径  之间的差就是半径。
                Vec3.subtract(this._tempVec,this._pointA,this._centerPoint);
                const r = this._tempVec.length();
            }


        } else {
            this._isMove = false;
            this._currentRoadPoint = null;
        }
    }
    private _conversion(value:number){
        let a = value;
        if(a<=0){
            a+=360;
        }
        return    a ;
    }

逆时针对代码如下。

image.png



添加计算半径代码


然后计算半径 

  //计算半径  之间的差就是半径。
                Vec3.subtract(this._tempVec,this._pointA,this._centerPoint);
                const r = this._tempVec.length();


添加计算 每度对应的弧度

  //计算的时候 速度跟弧度挂勾的,弧度如何换算成角度
                Vec3.subtract(this._tempVec, this._pointA, this._centerPoint);//计算半径  之间的差就是半径。
                const r = this._tempVec.length();
                console.log("半径是:" + r);
                //半径乘以圆周率结果是圆周长的一半。 周长一半除以2=90度的周长,,90除以它就是每度的弧度。
                this._rotMeasure = 90 / (Math.PI * r / 2);//得出一度是多少弧度
                console.log("_rotMeasure是:" + this._rotMeasure);
                /**
                 *  半径越大,每度对应的弧度越小。(_rotMeasure)
                 *  半径是:3       _rotMeasure是:19.098593171027442
                 *  半径是:4       _rotMeasure是:14.51612903225806
                 *  半径是:4.299   _rotMeasure是:13.327699351728848
                 */




然后修改update方法

image.png

 case RoadPoint.RoadMoveType.BEND:
                    //旋转的差值是多少, 开始旋转到目标旋转
                    const offsetRotation = this._targetRotation- this._originRotation
                    const currentRotation = this._conversion(this.node.eulerAngles.y);
                    //有了当前值,可以计算下一次的    currentRotation-this._originRotation当前的进度值。
                    //源是0  目标是-90  0向-90转。  三目这个地方是-1
                    let nextStation = (currentRotation-this._originRotation) + (this._speed * this._rotMeasure * (this._targetRotation>this._originRotation ? 1 : -1) );//计算这1帧旋转怕角度是多少。  再乘下顺时针还是逆时针
                    //0 - -90 = 90 
                    if(Math.abs(nextStation)>Math.abs(offsetRotation)){
                        nextStation = offsetRotation;
                    }

                    //计算 小车真正 旋转的角度是多少  整体旋转的角度是多少
                    const target = nextStation + this._originRotation;
                    this._tempVec.set(0,target,0);
                    this.node.eulerAngles = this._tempVec;

                    //旋转做完了。 运行轨迹没有做

                    



                    break;





旋转的公式。

image.png


360度  2*PI  6.28

160度   PI   3.14

90度  PI/2   1.57 

1度  1.57/90 0.017444


圆的周长 =  PI * R * 2

圆的面积 =  PI * R * R(R的平方)


半径乘以圆周率结果是圆周长的一半。


1rad=(/180)1°=1/180rad,其中rad是弧度的单位、通常可以省略不写。


公式为:

角度=180°×弧度÷π 

弧度=角度×π÷180


1度=π/180≈0.01745弧度

1弧度=180/π≈57.3度。




我们小车,轨迹运动的代码如下


image.png

                    //设置转向
                    this.node.eulerAngles = this._tempVec;

                    //旋转做完了。 运行轨迹运动
                    const sin = Math.sin(nextStation * Math.PI / 180);//nextStation是角度,通过角度求出弧度  弧度=角度×π÷180
                    const cos = Math.cos(nextStation * Math.PI / 180);//nextStation是角度,通过角度求出弧度
                    //求x轴的差值  z的差值。
                    const xLength = this._pointA.x - this._centerPoint.x;
                    const zlength = this._pointA.z - this._centerPoint.z;
                    //
                    const x__ = cos * xLength + sin * zlength + this._centerPoint.x;
                    const z__ = -sin * xLength + cos * zlength + this._centerPoint.z;
                    //设置运动轨迹 曲线
                    //this._offset.set(x__, 0, z__);
                    Vec3.rotateY(this._offset,this._pointA, this._centerPoint ,nextStation * Math.PI / 180 );

                    this._count++;
                    console.log("update运行的次数:" + this._count);


修改方向,修正方法

image.png

 if (this._tempVec.length() <= 1) {
                if(this._currentRoadPoint?.move_type==RoadPoint.RoadMoveType.BEND){
                    //车头校正
                    const offsetRotation = this._targetRotation - this._originRotation;//-90(顺时针转90度)
                    this._tempVec.set(0, offsetRotation, 0);
                    this.node.eulerAngles = this._tempVec;
                    //车头校正
                }
                this._arrivalStation();
            }











修改RoadPoint代码。添加提示。


import { _decorator, Component, Node, Vec3, Enum } from 'cc';
const { ccclass, property } = _decorator;


enum ROAD_POINT_TYPE {
    NORMAL = 1,
    START,
    GREETING,
    GOODBYE,
    END,
    AI_START
}
Enum(ROAD_POINT_TYPE);

enum ROAD_MOVE_TYPE {
    LINE = 1,
    BEND
}
Enum(ROAD_MOVE_TYPE);//序列化枚举

@ccclass('RoadPoint')
export class RoadPoint extends Component {

    public static RoadPointType = ROAD_POINT_TYPE;
    public static RoadMoveType = ROAD_MOVE_TYPE;

    @property({
        type: ROAD_POINT_TYPE,
        displayOrder: 1,
        tooltip:"点的类型,开始接客结束"
    })
    point_type = ROAD_POINT_TYPE.NORMAL;

    @property({
        type: Node,
        displayOrder:2 ,
        tooltip:"下一个节点?"
        // ,
        // visible: function (this: RoadPoint) {
        //     return this.type === ROAD_POINT_TYPE.END;
        // }
    })
    nextStation: Node | null = null;

    @property({
        type: ROAD_MOVE_TYPE,
        displayOrder: 3,
        tooltip:"移动类型,直线|转弯"
        // ,
        // visible: function (this: RoadPoint) {
        //     return this.type === ROAD_POINT_TYPE.END;
        // }
    })
    move_type = ROAD_MOVE_TYPE.LINE;

    @property({
        type: Vec3, displayOrder: 4,
        tooltip:"定义哪边开车门 拉客/送客"
        // ,
        // visible: function (this: RoadPoint) {
        //     return this.type === ROAD_POINT_TYPE.GREETING || this.type === ROAD_POINT_TYPE.GOODBYE;
        // }
    })
    direction = new Vec3(1, 0, 0);//定义哪边开车门 拉客/送客 左边1   右边-1

    @property({
        displayOrder: 5,
        tooltip:"间隔"
        // ,
        // visible: function (this: RoadPoint) {
        //     return this.type === ROAD_POINT_TYPE.AI_START;
        // }
    })
    interval = 3;

    @property({
        displayOrder: 6,
        tooltip:"延迟时间"
        // ,
        // visible: function (this: RoadPoint) {
        //     return this.type === ROAD_POINT_TYPE.AI_START;
        // }
    })
    delayTime = 0;

    @property({
        displayOrder: 7,
        tooltip:"速度"
        // ,
        // visible: function (this: RoadPoint) {
        //     return this.type === ROAD_POINT_TYPE.AI_START;
        // }
    })
    speed = 0.05;

    @property({
        displayOrder: 8,
        tooltip:"车的编号"
        // ,
        // visible: function (this: RoadPoint) {
        //     return this.type === ROAD_POINT_TYPE.AI_START;
        // }
    })
    cars = "201";

    @property({
        displayOrder: 9,
        tooltip:"clockwise"
        // ,
        // visible: function (this: RoadPoint) {
        //     return this.type !== ROAD_POINT_TYPE.END && this.move_type === ROAD_MOVE_TYPE.CURVE;
        // }
    })
    clockwise = true;
}



联系站长

站长微信:xiaomao0055

站长QQ:14496453