import { _decorator, MeshRenderer, Node, SkeletalAnimation, UITransform, Vec3 } from 'cc'; import { BaseExp } from '../core/base/BaseExp'; import { autoBind } from '../extend/AutoBind'; import { Utils } from '../utils/Utils'; import { ResUtil } from '../utils/ResUtil'; import { EAnimType } from './Enemy'; const { ccclass, property } = _decorator; //埋伏点接口类 export class AmbushPoint { //埋伏点位置节点数组 public standPosArr: Vec3[] = []; //中间路径节点 public roadPosArr: Vec3[] = []; //掩体点位置节点 public ambushPosArr: Vec3[] = []; //逃跑点位置节点 public escapePosArr: Vec3[] = []; //是否已经有人在此站位了 public isVacancy: boolean = false; } @ccclass('GMap') export class GMap extends BaseExp { @autoBind({ type: Node, tooltip: "埋伏点配置节点" }) public ambush_points: Node = null; @autoBind({type:Node,tooltip:"敌人出生区域"}) public enemy_born_area: Node = null; @autoBind({type:Node,tooltip:"进门内线,用于敌人是否在门内"}) public miidle_inline: Node = null; @autoBind({type:Node,tooltip:"进门外线,用于敌人是否在门外"}) public miidle_outline: Node = null; @autoBind({type:Node,tooltip:"进去的大门"}) public doors: Node = null; //埋伏点配置数组 public ambushPoints: AmbushPoint[] = []; //游戏速度 public game_speed: number = 1; start() { /*测试时使用 玩家坐标转换 let n: Node = this.node.getChildByName('player_points'); let pwww:Vec3 = Utils.convertPosition(this.node.getChildByName("player"),n); console.log("GGGGGGG = " + pwww);*/ //区域隐藏 const nodes:Node[] = this.ambush_points.children.flatMap(child => child.children); [this.enemy_born_area] .concat(nodes).forEach(e => { let m: MeshRenderer = e.getComponent(MeshRenderer); if(m){m.enabled = false} }); } /** * 游戏速度 */ public multiplySpeed(): number{ return this.game_speed; } /** * 解析埋伏点 */ private parseAmbushPoints() { this.ambushPoints = this.ambush_points.children .filter(e=>e.active) .map(ambushNode => { const point = new AmbushPoint(); point.isVacancy = false; //从节点结构获取坐标配置 point.standPosArr = ambushNode.children .filter(e => e.name.startsWith('stand_')) .map(node => node.worldPosition.clone()); point.roadPosArr = ambushNode.children .filter(e => e.name.startsWith('road_')) .sort((a, b) => { //提取数字部分(兼容 road_1 / road_01 / road_001 等所有情况) const getNumber = (name: string) => { const numPart = name.split('_').pop(); // 取最后一段 return parseInt(numPart || '0', 10); // 自动忽略前导零 }; return getNumber(a.name) - getNumber(b.name); // 按数值升序 }) .map(node => node.worldPosition.clone()); point.ambushPosArr = ambushNode.children .filter(e => e.name.startsWith('bunker_')) .map(node => node.worldPosition.clone()); point.escapePosArr = ambushNode.children .filter(e => e.name.startsWith('escape_')) .map(node => node.worldPosition.clone()); return point; }); } /** * 根据敌人信息得到敌人行走路径 * @param eData 敌人数据 * @param size 预制体大小 * @returns */ public getPaths(eData: any){ let bornPos: Vec3 = this.getRandomBornPosition(); //进入外门时的坐标 const outerPos: Vec3 = this.getRandomPos(eData,this.miidle_outline); //进入内门时的坐标 const innerPos: Vec3 = this.getRandomPos(eData,this.miidle_inline); //行走路径 let paths: Array = [bornPos,outerPos,innerPos]; //最后一个点特殊处理 包含(站位点、埋伏点、逃跑点) 随机一个埋伏点 const ambush: AmbushPoint = this.getAmbushClas(); ambush.isVacancy = true; eData.ambush = ambush; //查找中间路径点 paths = paths.concat(ambush.roadPosArr); //随机一个站立点到最后坐标 const endPos:Vec3 = Utils.randomArray(ambush.standPosArr)[0]; endPos.x += Utils.getRandomFloat(1,0.2); paths.push(endPos); //测试时使用 /*paths.forEach(e => { console.log("FFFFFF = " + this.node.getComponent(UITransform).convertToNodeSpaceAR(e)); });*/ return paths; } /** * 得到一个站位点 */ private getAmbushClas(){ if(!this.ambushPoints || this.ambushPoints.length <= 0){ //埋伏点类解析 this.parseAmbushPoints(); } //获取所有可用的埋伏点(未被占用的) const availablePoints = this.ambushPoints.filter(p => !p.isVacancy); if (availablePoints.length > 0) { //随机返回一个可用埋伏点 return Utils.randomArray(availablePoints)[0]; } //当所有点位都被占用时,随机返回任意一个 if(this.ambushPoints.length > 0) { return Utils.randomArray(this.ambushPoints)[0]; } return null; } /** * 根据两个坐标点产生一个两个坐标点之前的随机点 */ public getRandomPos(eData:any,target: Node): Vec3 { //只有坦克走中间 const isTan: boolean = eData.id == 20003; if(isTan){ return target.worldPosition.clone(); } let basePos: Vec3 = target.children[0].worldPosition.clone(); if(target.children.length >= 2){ let pos1: Vec3 = target.children[0].worldPosition.clone(); let pos2: Vec3 = target.children[1].worldPosition.clone(); //生成0-1的随机比例因子 const ratio = Utils.getRandomFloat(0, 1); //分别在x和z轴进行线性插值 这儿为了看起来暂时保留x轴上的距离随机 basePos.x = pos1.x + (pos2.x - pos1.x) * ratio; //y轴就是左边的间隔的距离 basePos.z = pos1.z + (pos2.z - pos1.z) * ratio; } return basePos; } /** * 获取随机出生点位置 */ public getRandomBornPosition(): Vec3 { if (!this.enemy_born_area) return Vec3.ZERO; //获取3D节点的世界缩放 const worldScale = this.enemy_born_area.getWorldScale(); //使用X和Z轴缩放作为区域尺寸 const areaWidth = worldScale.x; const areaDepth = worldScale.z; //在XZ平面生成随机坐标(Y轴保持地面高度) const randomX = (Math.random() - 0.5) * areaWidth; const randomZ = (Math.random() - 0.5) * areaDepth; //基于节点原点位置生成世界坐标 保持与出生区域相同高度 const basePos = this.enemy_born_area.worldPosition; return new Vec3( basePos.x + randomX, basePos.y, basePos.z + randomZ ); } /** * 还原数据 */ public resetData(){ this.ambushPoints.forEach(e => { e.isVacancy = false; }); } }