参考:
https://blog.csdn.net/Ctrls_/article/details/108731313
https://blog.csdn.net/qq_28299311/article/details/104009804
const { ccclass, property } = cc._decorator;
@ccclass
export default class mapPanel extends cc.Component {
@property(cc.Node)
player: cc.Node = null;
@property(cc.Node)
build: cc.Node = null;
@property(cc.Node)
point: cc.Node = null;
@property(cc.Node)
root: cc.Node = null;
start() {
this.init();
}
init(data?) {
data = {
mapData: [
{ id: 1, name: "1", pos: { x: 0, y: 100 } },
{ id: 2, name: "2", pos: { x: -100, y: -100 } },
{ id: 3, name: "3", pos: { x: 200, y: -80 } },
{ id: 4, name: "4", pos: { x: 180, y: 300 } },
{ id: 5, name: "5", pos: { x: 150, y: 50 } }
],
linkData: [[2, 1], [1, 4], [5, 1], [5, 3], [2, 5]],
startPosId: 2,
road: [2, 5, 1, 4]
}
data.mapData.forEach(element => {
this.creatOneBuild(element, data.startPosId)
});
this.player.position = data.mapData[data.startPosId - 1].pos
data.linkData.forEach(element => {
this.setPoint(cc.v2(data.mapData[element[0] - 1].pos), cc.v2(data.mapData[element[1] - 1].pos))
});
let roadArray = []
data.road.forEach((element) => {
roadArray.push(data.mapData[element - 1].pos);
})
this.playTween(roadArray);
}
playTween(roadArray, moveSpeed = 0.003, time = 1.5, delayTime = 0.3, cb?) {
let tween = cc.tween(this.player)
let nowPos = roadArray[0]
for (let i = 1; i < roadArray.length; i++) {
let nextPos = roadArray[i]
let pointArr = this.getOneroad(nowPos, nextPos, 1)
let speed = moveSpeed
if (pointArr.length * moveSpeed > time) speed = (time / pointArr.length)
// if (speed > moveSpeed) speed = moveSpeed
pointArr.forEach(element => {
tween.to(speed, { position: element })
});
tween.delay(delayTime)
nowPos = nextPos;
}
tween
.call(() => {
cb && cb()
})
.start();
}
creatOneBuild(data, nowId) {
let build = cc.instantiate(this.build);
build.parent = this.root;
build.position = cc.v3(data.pos);
build.getChildByName("name").getComponent(cc.Label).string = data.name;
build.active = true;
build.getChildByName("light").active = nowId == data.id;
}
creatOnePoint(pos: cc.Vec3) {
let build = cc.instantiate(this.point);
build.parent = this.root;
build.position = pos;
build.active = true;
}
/**
* 设置点
* @param startPoint 起点
* @param endPoint 终点
* @param pointDistance 小点间距
* @param angel 弧度
*/
setPoint(startPoint, endPoint, pointDistance = 30, angel = 60) {
let pointArr = this.getOneroad(startPoint, endPoint, pointDistance, angel)
pointArr.forEach(element => {
this.creatOnePoint(element)
console.log(element);//每个小圆点点坐标,这里进行处理
});
}
/**
* 获取n点之间路径
* @param startPoint 起点
* @param endPoint 终点
* @param pointDistance 小点间距
* @param angel 弧度
*/
getTotalRoad(arrList, pointDistance = 30, angel = 60) {
let pointArrTotal = []
let nowPos = pointArrTotal.shift()
let list = arrList;
while (1) {
let nextPos = list.shift()
if (nextPos) {
let pointArr = this.getOneroad(nowPos, nextPos, pointDistance, angel)
pointArrTotal = pointArrTotal.concat(pointArr)
nowPos = nextPos;
}
else {
break;
}
}
return pointArrTotal
}
/**
* 获取两点之间路径
* @param startPoint 起点
* @param endPoint 终点
* @param pointDistance 小点间距
* @param angel 弧度
*/
getOneroad(startPoint, endPoint, pointDistance = 30, angel = 60) {
startPoint = cc.v2(startPoint);
endPoint = cc.v2(endPoint);
let distance = startPoint.sub(endPoint).mag();
let middlePoint = cc.v2((startPoint.x + endPoint.x) / 2, (startPoint.y + endPoint.y) / 2)
let height = Math.sin(angel * (180 / Math.PI)) * (distance / 2) * 1.5;
cc.log(height)
let middlePoint2 = this.findPointCInRightTriangle(startPoint, middlePoint, height);
let number = Number((distance / pointDistance).toFixed(0));
let pointArr = this.getBezierPoints(number, startPoint, height ? middlePoint2 : middlePoint, endPoint)
return pointArr;
}
/**
* 获取两点之间垂直平分线线上的点
* @param startPoint
* @param endPoint
* @param bcLength
* @returns
*/
findPointCInRightTriangle(startPoint: cc.Vec2, endPoint: cc.Vec2, bcLength: number, isUP = true): cc.Vec2 | null {
let ax = endPoint.x;
let ay = endPoint.y;
let bx = startPoint.x;
let by = startPoint.y;
// 计算向量AB
const dx = bx - ax;
const dy = by - ay;
// 计算AB的长度
const abLength = Math.sqrt(dx * dx + dy * dy);
// 检查AB长度是否为零,以避免除以零的错误
if (abLength === 0) {
return null; // 无法确定C点位置,因为AB长度为0
}
// 计算AC的长度(利用勾股定理)
const acLength = Math.sqrt(bcLength * bcLength - abLength * abLength);
// 计算向量AB的单位向量
const abUnitX = dx / abLength;
const abUnitY = dy / abLength;
// 计算向量AC,它垂直于向量AB(因为ABC是直角三角形)
const acUnitX = -abUnitY; // 垂直向量的x分量是原向量y分量的相反数
const acUnitY = abUnitX; // 垂直向量的y分量是原向量x分量
// 计算点C的坐标
const cx = ax + acLength * acUnitX * (isUP ? -1 : 1);
const cy = ay + acLength * acUnitY * (isUP ? -1 : 1);
return cc.v2(cx, cy);
}
/**
* 获取贝塞尔曲线上的点
* @param {返回的点的数组长度} num
* @param {起点} startPoint
* @param {控制点} middlePoint
* @param {终点} endPoint
*/
getBezierPoints(num, startPoint, middlePoint, endPoint) {
let pointList = [];
let x1 = startPoint.x, y1 = startPoint.y;
let x2 = endPoint.x, y2 = endPoint.y;
let cx = middlePoint.x, cy = middlePoint.y;
let t = 0;
for (let i = 1; i < (num + 1); i++) {
//用i当作t,算出点坐标,放入数组
t = i / num;
let x = Math.pow(1 - t, 2) * x1 + 2 * t * (1 - t) * cx + Math.pow(t, 2) * x2;
let y = Math.pow(1 - t, 2) * y1 + 2 * t * (1 - t) * cy + Math.pow(t, 2) * y2;
pointList.push(cc.v2(x, y))
}
return pointList;
}
// update (dt) {}
}