游戏开发常见功能

1.碰撞检测
(1)圆形和圆形的碰撞判断:计算两个圆心之间的距离是否小于两个圆的半径和
        假设圆形1的左上角坐标是(x1,y1),半径是r1;圆形2的左上角坐标是(x2,y2),半径是r2;
        用数学公式表达就是:(x1-x2)的平方+(y1-y2)的平方 < (r1+r2)的平方
//判断是否碰到道具
_proto.isHitProp = function (roleX, roleZ, roleSize) {
//吃道具
var dx = Math.abs(roleX - this.x);   //返回绝对值

var dy = Math.abs(roleZ - this.z);

var dis = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));   //pow(x,y) 方法可返回 x 的 y 次幂的值。//sqrt() 方法可返回一个数的平方根

var hitRadius = this.colliderSize + roleSize;
if (dis <= hitRadius) {
this.hitProp();
}
};

(2)应用碰撞检测,做吸收金币的功能:
第一步:获取角色的位置和角色的半径大小:
var roleX = gameManager.player.getPos().x;
var roleZ = gameManager.player.getPos().z;
var roleY = gameManager.player.getPos().y;
var roleSize = G.ROLE_SIZE;

第二步:计算角色距离金币的距离,以及计算角色和金币的半径之和:
var dx = Math.abs(roleX - this.x);
var dy = Math.abs(roleZ - this.z);
var dis = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));  //计算角色距离金币的距离
var hitRadius = G.GOLD_SIZE + roleSize;     //计算角色和金币的半径之和

第三步:做出碰撞检测的判断,移动金币到角色身上:
if (dis>hitRadius){
    if(roleZ<this.z){
       var disZ=this.z-roleZ;   //角色的位置在金币的前边
       var speed = (roleX - this.x) * G.PROP_GOLD_SPEED / disZ;
       this.x += speed;
       this.z -= G.PROP_GOLD_SPEED;   //金币向前移动到角色身上

}else{
    var disZ=roleZ-this.z;     //角色的位置在金币的后边
    var speed = (roleX - this.x) * G.PROP_GOLD_SPEED / disZ;
    this.x += speed;
    this.z += G.PROP_GOLD_SPEED;   //金币向后移动到角色身上
}

2.通过半径之和以及中心点距离进行碰撞检测:
(1)主要检测函数:
 
/**
* 检测碰撞
*/
_proto.checkCollider = function (pos) { //参数是:战斗中手臂(this.battleUI.mainUI.image_collider)的中心点的全局坐标
    if (this.isRemove) return;
    var dx = Math.abs(pos.x - this.mainUI.x);
    var dy = Math.abs(pos.y - this.mainUI.y);

    var hitRadius = this.radiuSize + this.handColliderSize;
    //this.radiuSize该物品的碰撞半径,物品的配表中获取该值
    //this.handColliderSize 手臂碰撞区域大小 battleMgr.battleUI.getHandColliderSize函数获取==this.mainUI.image_collider.width / 2;

    var dis = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)); //手臂中心点和掉落物品中心点之间的直线距离


    if (dis < hitRadius) { //距离小于半径之和就判断发生了碰撞
        if (this.money > 0 || this.goodItem.type == G.GOOD_TYPES.NEWJINZHIBI) { //吃到纸币手机发生震动
            if (this.goodItem.type == G.GOOD_TYPES.ZHIBI) {
                
                utils.vibration(); //调用手机震动
            } else if (this.goodItem.type == G.GOOD_TYPES.JINZHIBI) {
                utils.vibration();
            } else if (this.goodItem.type == G.GOOD_TYPES.NEWJINZHIBI) {
                this.money = battleMgr.getRedBagValue();
                utils.vibration();
            }
        }
        //吃到炸弹死亡
        if (this.goodItem.type == G.GOOD_TYPES.ZHADAN) {
            battleMgr.bombOver();
            eventDispatcher.dispatchEvent(cc.Event.ON_GAMEOVER_CLEAR);
        }
        var score = this.goodScore;
        //发生碰撞触发事件
        eventDispatcher.dispatchEvent(cc.Event.ON_EAT_GOOD, { score: score, money: this.money, itemType: this.goodItem.type, len:         this.mainUI.x - pos.x });
        // this.destroy();
        this.isRemove = true;
    }
};

(2)前提准备(对手臂进行全局坐标的转换):
//碰撞检测(主要在于battleGood的碰撞检测,这里只做坐标转化而已)
_prop.checkCollider = function () {
    var playerHand = battleMgr.getPlayerHand(); //获取手臂碰撞点ui元素img
    var point = Laya.Point.TEMP;
    point.setTo(0, 0);
    playerHand.localToGlobal(point); //point的值变为,手臂的本地坐标转成的全局坐标
    var pos = { x: point.x + playerHand.width / 2, y: point.y + playerHand.height / 2 }; //this.battleUI.mainUI.image_collider的中心点坐标
    //物件逻辑更新
    var count = this.allGoods.length;
    for (var i = 0; i < count; i++) {
        this.allGoods[i] && this.allGoods[i].checkCollider(pos); //掉落物品的碰撞检测,调用battleGood中定义的函数
    }
};

3.创建遮罩,屏蔽按钮事件:
(1)创建UI元素,平铺:
(2)如果是box组件,必须注册一个事件:
this.mainUI.box_wating.on(Laya.Event.MOUSE_DOWN,this,function(){});

(3)设置按钮点击后,打开遮罩:
//抽奖
_proto.onChouClick = function () {
    var totalScore = dataManager.getRoleScore();
    var spend = dataManager.getRoleSpendScore();
    if (spend > totalScore) {
        // utils.prompt("积分不足");
        this.mainUI.ani1.play(0, false);
        return;
    }
    protocolReq.reqLuckDraw();
    this.openWait();
};


_proto.monitorWaitTimeout = function(){
    Laya.timer.once(5000,this, this.onWaitTimeOut);   // 相当于注册了一个时间点事件(定时炸弹)
}


_proto.cancleWaitTimeOut = function(){
    Laya.timer.clear(this, this.onWaitTimeOut);  //取消定时事件的监听
};


_proto.openWait = function(){
    this.mainUI.box_wating.visible = true;
    this.monitorWaitTimeout();                 //注册定时事件的监听
}


_proto.closeWait = function(){
    this.cancleWaitTimeOut();
    this.mainUI.box_wating.visible = false;
};


_proto.onWaitTimeOut = function(){
    if(this.mainUI.box_wating.visible)
        this.closeWait();              //时间点到了,如果遮罩还在我们就执行这个函数
}

4.毫秒倒计时:
/**
* 倒计时刷新
*/
refreshCd = function () {
    let times = this.SecondCountDown * 100; //5秒倒计时

    this.countTime = window.setInterval(() => {
        times = --times < 0 ? 0 : times;
        var ms = Math.floor(times / 100).toString();
        if (ms.length <= 1) {
            ms = "0" + ms;
        }
        var hm = Math.floor(times % 100).toString();
        if (hm.length <= 1) {
            hm = "0" + hm;
        }
        if (times == 0) {
            // alert("游戏结束");
            this.ani3.play(0, true);
            window.clearInterval(this.countTime);
        }
        // 获取分钟、毫秒数
        this.ms_label.text = ms;
        this.hs_label.text = hm;
    }, 10);
};

5.3D游戏子弹发射:
*****基本原理:鼠标点击产生射线,射线与模型碰撞器相交,则获取碰撞点作为子弹发射方向;如果子弹未与3D模型相交,则直接使用射线作为发射方向
(1) 子弹获取和克隆
1. /**场景中的初始子弹**/
2. public bullet: Laya.MeshSprite3D;

加载资源结束之后,获取场景中的子弹用于克隆:

1. //获取场景中的子弹用于克隆
2. this.bullet = this.scene.getChildByName("bullet") as Laya.MeshSprite3D;
3. //未产生子弹时移除克隆参考用子弹
4. this.bullet.removeSelf();

(2) 鼠标点击屏幕的位置,生成射线,射线与3D模型中的碰撞器进行碰撞检测
1. public ray: Laya.Ray = new Laya.Ray(new Laya.Vector3(), new Laya.Vector3());
2. /**鼠标坐标**/
3. public mousePos: Laya.Vector2 = new Laya.Vector2();
4. /**碰撞信息**/
5. public rayCastHit: Laya.RaycastHit = new Laya.RaycastHit();  //不存在的接口
   public rayCastHit: Laya.HitResult = new Laya.HitResult();  //存在的接口


1. //鼠标点击屏幕的位置
2. this.mousePos = new Laya.Vector2(Laya.MouseManager.instance.mouseX, Laya.MouseManager.instance.mouseY);
3. //鼠标点击屏幕产生射线
4. this.camera.viewportPointToRay(this.mousePos, this.ray);
5. //射线与3D模型中的碰撞器进行碰撞检测
6. Laya.Physics.rayCast(this.ray, this.rayCastHit, 30, 0);  //不存在的接口

    this.scene.physicsSimulation.rayCast(this.ray, this.rayCastHit);   //存在的解决

扫描二维码关注公众号,回复: 17165000 查看本文章
(3) 进行碰撞判定,进而,在子弹脚本中设置子弹发射的方向:
1. //射击的方向向量
2. var dirV3: Laya.Vector3 = new Laya.Vector3();
3. //如果鼠标点击到模型上(射线与碰撞器发生碰撞)

4. if (this.rayCastHit.distance !== -1) {

5.     //子弹射击方向向量 = 由鼠标点中的目标位置向量 —— 子弹起始位置向量
6.     Laya.Vector3.subtract(this.rayCastHit.position, this.bullet.transform.position, dirV3);
7.     //设置子弹控制脚本中发射方向
8.     script.setShootDirection(dirV3);

9. } else {

        //如果鼠标未点击到模型上
10.     /**
11.         *射线方向向量是归一化的单位向量,不能直接用于向量加减。需要根据射线产生的原理算
12.         *出相当于有长短距离的方向向量用于计算,可以通过向量缩放方法实现。
13.         *射线原理:原点是鼠标点击在近裁剪面上的点,方向是从摄像机位置到鼠标点击在远裁剪面
14.         *上的点产生的归一化方向。因此可以用摄像机到远裁面的距离模拟原始方向向量
15.     **/

16.     // console.log(Laya.Vector3.scalarLength(this.ray.direction));
17.     //摄像机到鼠标点击处的方向向量
18.     var aV3: Laya.Vector3 = new Laya.Vector3();
19.     //根据射线方向向量、摄像机远裁剪值缩放为射线方向原始向量(使用远裁距会有一点误差,但不影响效果)

20.     Laya.Vector3.scale(this.ray.direction, this.camera.farPlane, aV3);
21.     //根据摄像机与子弹的位置求出子弹到摄像机的方向向量
22.     var bV3: Laya.Vector3 = new Laya.Vector3();
23.     Laya.Vector3.subtract(this.camera.transform.position, this.bullet.transform.position, bV3);
24.     //射击的方向向量 = 摄像机到鼠标点击处的方向向量 +子弹到摄像机的方向向量
25.     Laya.Vector3.add(aV3, bV3, dirV3);

26.     //设置子弹控制脚本中发射方向
27.     script.setShootDirection(dirV3);
28. }

(4)  子弹控制脚本:
1. /**被绑定的子弹对象**/
2. private bullet: Laya.MeshSprite3D;
3. /**子弹生命周期**/
4. private life: number = 200;
5. /**子弹发射的速度(方向)**/
6. public speedV3: Laya.Vector3 = new Laya.Vector3();


1. /**
2. * 设置子弹射击方向并计算速度
3. * @param directionV3
4. */
5. public setShootDirection(directionV3: Laya.Vector3): void {
6.     /****
7.     * 注:
8.     * 三维向量即是位置、方向,也可以是速度,但速度需要一个统一的参考衡量标准,比如“N*标准速度值/帧”或
9.     * “N*标准速度值/毫秒”,它类似于“N*米/帧”。
10.     * 而我们得到的方向向量,它的大小不一,无法作为标准速度值使用,这个时候可用Vector3.normalize()方法
11.     * 把任一向量归一化,产生单位为一的向量作为标准速度值,再把它进行缩放作为不同物体的速度来使用,比如
12.     * 0.2倍标准速度值,1.5倍标准速度值等,可使用Vector3.scale()方法缩放。
13.     ****/
14.     //将方向向量归一成单位为一的方向速度向量(在LayaAir中相当于1米的长度)
15.     Laya.Vector3.normalize(directionV3, this.speedV3);
16.     console.log("\n子弹攻击速度(方向):", this.speedV3.elements)
17.     //用缩放方法去调整发射速度,0.2倍标准速度(注:子弹速度过快,可能会越过场景中物品,不发生碰撞!)
18.     // Vector3.scale(speedV3,0.2,speedV3);
19. }
20. /**
21. * 脚本帧循环更新
22. */
23. public _update(state: Laya.RenderState): void {
24.     //子弹位置更新
25.     this.bullet.transform.translate(this.speedV3, false);
26.     //生命周期递减
27.     this.life--;
28.     //生命周期结束后,一帧后销毁子弹(目前脚本中直接销毁绑定对象会报错,后期版本解决此问题)
29.     if (this.life < 0) {
30.         Laya.timer.frameOnce(3, this, function () { this.bullet.destroy(); });
31.     }
32. }

(5) 被子弹攻击的盒子,产生击退效果,立方体控制脚本逻辑如下:
1. /**被绑定的立方体对象**/
2. public cube: Laya.MeshSprite3D;
3. /**是否被攻击**/
4. private isAttacked: Boolean = false;
5. /**盒子被击退的标准速度(方向)**/
6. public repelledV3: Laya.Vector3 = new Laya.Vector3();
7. /**盒子生命周期**/
8. public life: number = 60;


1. /**
2. * 当其他碰撞器进入绑定物体碰撞器时触发(子弹击中盒子时)
3. * 注:如相对移动速度过快,可能直接越过
4. */
5. public onTriggerEnter(other: Laya.Collider): void {
6.     //获取其他碰撞器绑定的模型
7.     var sp3D: Laya.MeshSprite3D = other.owner as Laya.MeshSprite3D;
8.     //获取子弹对象模型脚本
9.     var script: BulletScript = sp3D.getComponentByType(BulletScript) as BulletScript;
10.     //获取子弹速度为
11.     this.repelledV3 = script.speedV3.clone();
12.     //被攻击速度归一化成单位一向量
13.     Laya.Vector3.normalize(this.repelledV3, this.repelledV3);
14.     //设置为被攻击状态
15.     this.isAttacked = true;
16.     console.log("\n1 子弹碰撞时位置(方向):", sp3D.transform.position.elements);
17. }

 
1. /**
2. * 脚本的帧循环
3. */
4. public _update(state: Laya.RenderState): void {
5.     //被攻击状态下,盒子产生击退效果
6.     if (this.isAttacked) {
7.         //根据击退方向和速度移动
8.         this.cube.transform.translate(this.repelledV3, false);
9.         // console.log("击退位置变化:",(this.cube.transform.position.clone() as Laya.Vector3).elements);
10.         //击退速度逐步减小
11.         Laya.Vector3.scale(this.repelledV3, 0.3, this.repelledV3);
12.         //当后退各方向速度小于0.01时,击退状态停止
13.         if (Laya.Vector3.scalarLength(this.repelledV3) < 0.01) {
14.             this.isAttacked = false;
15.         }
16.     }
17. }

6.U3D 和 Laya配合做碰撞检测,切记几点:
(1)  主动体  :空节点作为父节点的,模型作为子节点, 模型身上必须绑定 刚体和网格碰撞器,父节点不加任何物理组件
(2)  被动体: 空节点作为父节点,模型作为子节点, 模型身上必须不能带刚体,只需要加碰撞器,父节点不加任何物理组件
7.2d精灵通过绳索骨骼链接起来,链接的部分需要依靠物理引擎来运动:
(1)创建 碰撞器:
    /** 创建身体的2d碰撞器 */
    createCollier2d$() {
        if (!this._headCtrl$) return;
        this._bodyCollider$ = new Laya.CircleCollider();
        this._bodyCollider$.label = "wormBody";
        this._bodyCollider$.radius = this._headCtrl$.headColliderRaduis$ * this._headCtrl$.lastBodyScale$;
        this._bodyCollider$.x = -this._bodyCollider$.radius + this.owner.x;
        this._bodyCollider$.y = -this._bodyCollider$.radius + this.owner.y;
        this.owner.addComponentIntance(this._bodyCollider$);
    }

(2)创建 刚体:
  
  /** 创建身体的2d刚体 */
    createRigidBody2d$() {
        this._bodyRigidBody$ = this.owner.addComponent(Laya.RigidBody);
        this._bodyRigidBody$.allowRotation = false;
        this._bodyRigidBody$.type = this.isSleep$ ? "static" : "dynamic";
        this._bodyRigidBody$.body.SetGravityScale(0);
    }

(3)创建 绳索骨骼:
    /** 创建骨骼点 */
    createRopeJoint$() {
        this._bodyJoint$ = new Laya.RopeJoint();
        this._bodyJoint$.otherBody = this._connectBody$;
        this._bodyJoint$.selfAnchor = [0, 0];
        this._bodyJoint$.otherAnchor = [0, 0];
        // this._bodyJoint$.maxLength = GameSetting$.BODY_MODEL_DIS$ * GameSetting$.UI_SCENE_RATE$;
        this._bodyJoint$.maxLength = GameSetting$.BODY_MODEL_DIS$;
        this.owner.addComponentIntance(this._bodyJoint$);
        this.updateConnectBody$();
    }

(4)给链接的头部施加线速度或者方向力,只依靠移动 x,y  是没法真正实现物理上的移动的,只是UI表现上的瞬移罢了;


    _wormMove$() {
        if (!this.isNeedMoved$) return;
        let deltX = this.curSpeedX$ * this._deltaTime$;
        let deltY = this.curSpeedY$ * this._deltaTime$;
        // this._targetX$ = playerStagePos.x + deltX;
        // this._targetY$ = playerStagePos.y + deltY;
        let direction = new Laya.Vector2(deltX, deltY);
        Laya.Vector2.normalize(direction, direction)
        this.force$.x = direction.x * this.power$;
        this.force$.y = direction.y * this.power$;
        // playerStagePos.x = this._targetX$;
        // playerStagePos.y = this._targetY$;
        // this._wormX$ = playerStagePos.x;
        // this._wormY$ = playerStagePos.y;
        // this.owner.pos(-this._wormX$, this._wormY$);
        this.setVelocity$();
    }
(5)设置 物理线速度:
    setVelocity$() {
        let v = this.headRigidbody$.linearVelocity;
        v.x = this.force$.x;
        v.y = this.force$.y;
        this.headRigidbody$.linearVelocity = v;
        this.headRigidbody$.applyForceToCenter(this.force$);  //施加一个力到刚体上的质心上
    }

8.坐标位置,转化方向向量,计算角度:
 
        let otherPosX = this._bodyJoint$.otherBody.owner.x;  //坐标
        let otherPosY = this._bodyJoint$.otherBody.owner.y;
        let myPosX = this.owner.x;
        let myPosY = this.owner.y;
        let delX = (otherPosX - myPosX);
        let delY = (otherPosY - myPosY);
        let rad = Math.atan2(delY, delX);   //弧度
        this.owner.rotation = rad * GameSetting$.ANGLE_1_RAD$;   //弧度转化为角度 GameSetting$.ANGLE_1_RAD$ = 180 / Math.PI;


            let dx = lastButOneBody.x - lastBody.x;
            let dy = lastButOneBody.y - lastBody.y;
            let direction = new Laya.Vector2(dx, dy);
            Laya.Vector2.normalize(direction, direction)

9.设置物体角速度使之物理系统发生旋转:
前提条件:
this.sawRigidbody$.allowRotation = true;  //设置可旋转
this.sawRigidbody$.type = "dynamic";      //刚体类型动态

//旋转速度
this.rollSpeed$ = 2;

setRollVelocity$() {
    if (!this.woodenPlateRigidbody$ || !this.rollSpeed$) return;
    this.woodenPlateRigidbody$.angularVelocity = this.rollSpeed$;    rollSpeed$  负值:逆时针  正值:顺时针
}

10.即使是3D的也可以忽略Y轴,只考虑X轴和 Z轴上的碰撞检查:

(1)基本碰撞检测,用位置和半径判断:


    /**
     * 行车与黑洞是否碰撞
     * @param {} car
     * @param {*} dinosaur
     */
    _isCarAndDinoCollision$(car, dinosaur) {
        let hPos = car.owner.transform.position;
        let dPos = dinosaur.owner.transform.position;
        let x = hPos.x - dPos.x;
        let z = hPos.z - dPos.z;
        if (x * x + z * z <= Math.pow(dinosaur.collisionRadius + car.collisionRadius, 2)) return true;
        return false;
    }
(2)从数组中取出需要进行碰撞判断的 对象,嵌套for循环进行实时检测:
    /**
     * 检查车与黑洞碰撞
     */
    checkCarsAndDinoCollision$() {
        if (!this._init$()) return;
        if (!window.curScene || curScene.isPaused || !curScene._cars$ || !curScene.dinosaurs) return;
        let cars = curScene._cars$;
        let dinosaurs = curScene.dinosaurs;
        let car, dinosaur;
        for (let j = cars.length - 1; j >= 0; j--) {
            car = cars[j];
            for (let i = dinosaurs.length - 1; i >= 0; i--) {
                dinosaur = dinosaurs[i];
                if (this._isCarAndDinoCollision$(car, dinosaur)) {
                    dinosaur.onCollision$(null, car);   //触发碰撞结果
                    car.onKilled$(dinosaur);
                    break;//一辆车只能被一只恐龙吃
                }
            }
        }
    }

(3)注册帧循环,实时检测碰撞:
Laya.timer.loop(100, this, this.checkCarsAndDinoCollision$);

11.计算移动到目标点,需要旋转的角度:
        /** 路段起始坐标 */
        this._startPos$ = new Laya.Vector3();
        /** 路段结束坐标 */
        this._endPos$ = new Laya.Vector3();
        /** 路线角度 */
        this._roadAngle$ = undefined;


        let deltaX = this._endPos$.x - this._startPos$.x;
        let deltaZ = this._endPos$.z - this._startPos$.z;
        this._roadAngle$ = (Math.atan2(deltaX, deltaZ) * GameSetting$.ANGLE_1_RAD$) % 360;

        /** 弧度转角度换算单位 */
        GameSetting$.ANGLE_1_RAD$ = 180 / Math.PI;

        发生旋转动画:

        _move$(){
            let rot = this.owner.transform.rotationEuler;
            let deltaAngle = (this._roadAngle$ - rot.y) % 360;
            if(deltaAngle > 180) {
                deltaAngle -= 360;
            }else if(deltaAngle < -180) {
                deltaAngle += 360;
            }
            rot.y += deltaAngle * Math.min(0.02 * deltaT, 1);
            this.owner.transform.rotationEuler = rot;
        }

        onUpdate(){
            this._move$();
        }

12.玩家交互区域判定

(1)工具函数


  /**
     * 获取二维距离平方 m^2
     * @param {*} x1
     * @param {*} y1
     * @param {*} x2
     * @param {*} y2
     * @returns
     */
  static getV2DisQ$(x1, y1, x2, y2) {
    return Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2);
  }
(2)玩家移动状态:
 
    /** 是否鼠标按下状态 */
    get isMouseDown$() {
        return this._isMouseDown$;
    }


    /** 是否移动中 */
    get isMoveing$() {
        return this._isMoveing$;
    }


    /** 获取上次移动时刻 ms */
    get lastMouseMoveT$() {
        return this._lastMouseMoveT$;
    }

    this.owner.on(Laya.Event.MOUSE_MOVE, this, (e: Laya.Event) => {
            if (!this.currentTouch) {
                this.currentTouch = e;
                stageX = e.stageX;
                stageY = e.stageY;
            } else {
                isMoved = true;
                this._lastMouseMoveT = Laya.timer.currTimer;
                this.angle = this.getAngle(new Laya.Vector2(stageX, stageY), new Laya.Vector2(e.stageX, e.stageY));
                this._isMoving = true;
            }
        })

    /** 是否等待交互 */
    isWaitInteract() {
        return Globals.moveCtr && !Globals.moveCtr.isMouseDown && Globals.moveCtr.lastMouseMoveT > 0 && Globals.moveCtr.lastMouseMoveT + 300 < Laya.timer.currTimer;
    }

(3)主逻辑代码
 
    //交互距离平方
    public interDisQ: number = 1.5 * 1.5;

onUpdate() {
        this.checkInteract();
    }


    checkInteract(): void {
        if (!this.playerMove) return;
        let playerPos = this.playerMove.position;
        let disQ = Utils.getV2DisQ$(playerPos.x, playerPos.z, this.boxAreaPos.x, this.boxAreaPos.z);
        (disQ > this.interDisQ || !this.playCtr.isWaitInteract()) ? this.onNoInter() : this.onInter();  //!this.playCtr.isWaitInteract()可注释
    }


    onInter(): void {
        if (this._isInter) return;
        this._isInter = true;
        console.log("tcy 进去食品交互区域")
    }


    onNoInter(): void {
        if (!this._isInter) return;
        this._isInter = false;
        console.log("tcy 离开食品交互区域")
    }

13.是否在交互矩形范围内


    /**
     * 点是否在矩形范围内(场景是平面(非球形),只取X和Z方向坐标)
     * @param {*} pV3  坐标点
     * @param {*} tV3  目标坐标点
     * @param {*} xR   目标x长度/2
     * @param {*} zR   目标z长度/2
     */
    static isInRect$(pV3, tV3, xR, zR) {
        if (pV3.x > tV3.x - xR && pV3.x < tV3.x + xR && pV3.z > tV3.z - zR && pV3.z < tV3.z + zR) return true;
        return false;
    }

猜你喜欢

转载自blog.csdn.net/woshiyuyanjia/article/details/134800946