feat: add builder configuration file

feat: add cocos-service configuration file
feat: add device configuration file
feat: add engine configuration file
feat: add information configuration file
feat: add program configuration file
feat: add project configuration file
feat: add TypeScript configuration file
This commit is contained in:
ZhouXiao
2025-12-22 11:42:51 +08:00
parent 66cfa73345
commit 487c68994d
202 changed files with 57615 additions and 0 deletions

View File

@@ -0,0 +1,427 @@
type index = {
x: number,
y: number
}
/**
* AStar类用于实现A*寻路算法。
*/
export class AStar {
private map: any[][] = []; // 地图数组
private weightMap: number[][] = null; // 权重地图数组
private openlist: index[] = []; // 开放列表,存储待评估的节点
private closelist: index[] = []; // 封闭列表,存储已评估的节点
private parentMap: Map<index, index>; // 父节点映射,用于回溯路径
private gcostMap: Map<index, number>; // g成本映射记录从起点到当前节点的成本
private hcostMap: Map<index, number>; // h成本映射记录从当前节点到终点的估算成本
private startValue: number = 0;
private endValue: number = 0;
private pathValue: number = 0;
private isEightDirections: boolean = false;
private neighborMap: Map<index, index[]>;
constructor() {
this.openlist = [];
this.closelist = [];
this.parentMap = new Map();
this.gcostMap = new Map();
this.hcostMap = new Map();
}
/**
* 设置地图。
* @param map 二维数组表示的地图
*/
setMap(map: number[][]) {
this.map = map;
}
/**
* 设置权重地图。
* @param weightMap 二维数组表示的权重地图
*/
setWeightMap(weightMap: number[][]) {
this.weightMap = weightMap;
}
setValue(startValue: number, endValue: number, pathValue: number) {
this.startValue = startValue;
this.endValue = endValue;
this.pathValue = pathValue;
}
setEightDirections(isEightDirections: boolean) {
this.isEightDirections = isEightDirections;
}
setNeighborMap(neighborMap: Map<index, index[]>) {
this.neighborMap = neighborMap;
}
/**
* 在给定范围内根据指定类型搜索从起点到终点的路径。
* @param start 起点索引
* @param end 终点索引
* @param type 搜索类型(可能影响启发式函数的选择)
* @returns 返回找到的路径数组,如果无路径则返回空数组
*/
search(start: index, end: index, type: number) {
this.init(); // 初始化搜索环境
if (this.map[start.y][start.x] !== this.startValue ||
this.map[end.y][end.x] !== this.endValue) {
console.log("Invalid start or end point");
return [];
}
// 初始化起点信息,并将其加入开放列表
this.openlist.push(start);
this.gcostMap.set(start, 0); // 起点到起点的距离为0
this.hcostMap.set(start, this.getHeuristicCost(start, end, type)); // 起点到终点的启发式成本
this.parentMap.set(start, null); // 起点的父节点设置为null
// 循环直到开放列表为空,即所有可能的路径都被考虑
while (this.openlist.length > 0) {
const current = this.getMinCostNode(this.openlist); // 从开放列表中选择成本最小的节点
if (!current) {
this.openlist.splice(this.openlist.indexOf(current), 1);
continue;
}
// 判断是否到达终点
if (this.isArrived(current, end)) {
return this.reconstructPath(end); // 如果到达终点,返回路径重构的结果
} else {
// 从开放列表移除当前节点,将其加入封闭列表
this.openlist.splice(this.openlist.indexOf(current), 1);
this.closelist.push(current);
// 遍历当前节点的所有邻居节点
const neighbors = this.getNeighbors(current);
for (const neighbor of neighbors) {
const hCost = this.getHeuristicCost(neighbor, end, type); // 计算邻居节点到终点的启发式成本
const gCost = this.gcostMap.get(current) + this.getGCost(current, neighbor, type); // 计算当前节点到邻居节点的实际成本
const totalCost = gCost + hCost; // 计算总成本
// 根据邻居节点的状态进行处理
if (!this.isInClosedList(neighbor)) {
if (!this.isInOpenList(neighbor)) {
this.openlist.push(neighbor); // 如果邻居未在开放列表中,将其加入
this.updateCost(neighbor, gCost, hCost); // 更新邻居节点的成本信息
this.updateParent(neighbor, current); // 更新邻居节点的父节点信息
} else {
// 如果邻居已在开放列表中,但通过当前节点发现更优路径
if (totalCost < this.getCost(neighbor)) {
this.updateCost(neighbor, gCost, hCost); // 更新成本信息
this.updateParent(neighbor, current); // 更新父节点信息
}
}
}
}
}
}
console.log("No path found.");
return []; // 如果无法找到路径,返回空数组
}
/**
* 初始化算法状态。
*/
private init() {
// 重置所有列表和映射
this.openlist = [];
this.closelist = [];
this.parentMap = new Map();
this.gcostMap = new Map();
this.hcostMap = new Map();
}
/**
* 获取当前节点的邻居。
* @param current 当前节点坐标
* @returns 邻居节点数组
*/
private getNeighbors(current: index) {
if (this.neighborMap.size === 0) {
const neighbors: index[] = [];
// 尝试获取四个方向的邻居节点
const upindex = { x: current.x, y: current.y + 1 };
const downindex = { x: current.x, y: current.y - 1 };
const leftindex = { x: current.x - 1, y: current.y };
const rightindex = { x: current.x + 1, y: current.y };
const upleftindex = { x: current.x - 1, y: current.y + 1 };
const uprightindex = { x: current.x + 1, y: current.y + 1 };
const downleftindex = { x: current.x - 1, y: current.y - 1 };
const downrightindex = { x: current.x + 1, y: current.y - 1 };
// 如果合法则加入邻居列表
if (this.isValidIndex(upindex) && (this.map[upindex.y][upindex.x] == this.pathValue ||
this.map[upindex.y][upindex.x] == this.endValue)) {
neighbors.push(upindex);
}
if (this.isValidIndex(downindex) && (this.map[downindex.y][downindex.x] == this.pathValue ||
this.map[downindex.y][downindex.x] == this.endValue)) {
neighbors.push(downindex);
}
if (this.isValidIndex(leftindex) && (this.map[leftindex.y][leftindex.x] == this.pathValue ||
this.map[leftindex.y][leftindex.x] == this.endValue)) {
neighbors.push(leftindex);
}
if (this.isValidIndex(rightindex) && (this.map[rightindex.y][rightindex.x] == this.pathValue ||
this.map[rightindex.y][rightindex.x] == this.endValue)) {
neighbors.push(rightindex);
}
if (this.isEightDirections) {
if (this.isValidIndex(upleftindex) && (this.map[upleftindex.y][upleftindex.x] == this.pathValue ||
this.map[upleftindex.y][upleftindex.x] == this.endValue)) {
neighbors.push(upleftindex);
}
if (this.isValidIndex(downleftindex) && (this.map[downleftindex.y][downleftindex.x] == this.pathValue ||
this.map[downleftindex.y][downleftindex.x] == this.endValue)) {
neighbors.push(downleftindex);
}
if (this.isValidIndex(downrightindex) && (this.map[downrightindex.y][downrightindex.x] == this.pathValue ||
this.map[downrightindex.y][downrightindex.x] == this.endValue)) {
neighbors.push(downrightindex);
}
if (this.isValidIndex(uprightindex) && (this.map[uprightindex.y][uprightindex.x] == this.pathValue ||
this.map[uprightindex.y][uprightindex.x] == this.endValue)) {
neighbors.push(uprightindex);
}
}
return neighbors;
} else {
const _neighbors = this.neighborMap.get(current);
const neighbors: index[] = [];
for (const neighbor of _neighbors) {
if (this.map[neighbor.y][neighbor.x] == this.pathValue ||
this.map[neighbor.y][neighbor.x] == this.endValue) {
neighbors.push(neighbor);
}
}
return neighbors;
}
}
/**
* 计算从当前节点到邻居节点的实际成本
* @param current 当前节点
* @param neighbor 邻居节点
* @param type 距离计算类型
* @returns 返回从当前节点到邻居节点的成本
*/
private getGCost(current: index, neighbor: index, type: number = 0) {
let baseCost = 0;
// 计算基础距离成本
switch (type) {
case 0: {
// 计算曼哈顿距离
baseCost = Math.abs(current.x - neighbor.x) + Math.abs(current.y - neighbor.y);
break;
}
case 1: {
// 计算欧几里得距离
baseCost = Math.sqrt(Math.pow(current.x - neighbor.x, 2) + Math.pow(current.y - neighbor.y, 2));
break;
}
case 2: {
// 计算切比雪夫距离
const x = Math.abs(current.x - neighbor.x);
const y = Math.abs(current.y - neighbor.y);
const minxy = Math.min(x, y);
baseCost = x + y + (Math.sqrt(2) - 2) * minxy;
break;
}
}
// 如果存在权重地图,应用权重
if (this.weightMap && this.isValidIndex(neighbor)) {
const weight = this.weightMap[neighbor.y][neighbor.x];
return baseCost * weight;
}
return baseCost;
}
/**
* 根据给定的起始点和目标点,以及类型参数,计算启发式成本。
* @param start 起始点的索引,包含 x 和 y 坐标。
* @param end 目标点的索引,包含 x 和 y 坐标。
* @param type 计算成本的类型0 表示曼哈顿距离1 表示欧几里得距离2 表示切比雪夫距离,默认为 0。
* @returns 返回根据指定类型计算出的启发式成本。
*/
private getHeuristicCost(start: index, end: index, type: number = 0) {
switch (type) {
case 0: {
// 计算曼哈顿距离
return Math.abs(start.x - end.x) + Math.abs(start.y - end.y);
}
case 1: {
// 计算欧几里得距离
return Math.sqrt(Math.pow(start.x - end.x, 2) + Math.pow(start.y - end.y, 2));
}
case 2: {
// 计算切比雪夫距离
const x = Math.abs(start.x - end.x);
const y = Math.abs(start.y - end.y);
const minxy = Math.min(x, y);
return x + y + (Math.sqrt(2) - 2) * minxy;
}
}
}
/**
* 检查节点是否在封闭列表中。
* @param node 节点坐标
* @returns {boolean} 如果节点在封闭列表中返回true否则返回false
*/
private isInClosedList(node: index): boolean {
// 遍历封闭列表查找节点
let _index = -1;
for (let i = 0; i < this.closelist.length; i++) {
if (this.closelist[i].x == node.x && this.closelist[i].y == node.y) {
_index = i;
break;
}
}
return _index != -1;
}
/**
* 检查节点是否在开放列表中。
* @param node 节点坐标
* @returns {boolean} 如果节点在开放列表中返回true否则返回false
*/
private isInOpenList(node: index): boolean {
// 遍历开放列表查找节点
let _index = -1;
for (let i = 0; i < this.openlist.length; i++) {
if (this.openlist[i].x == node.x && this.openlist[i].y == node.y) {
_index = i;
break;
}
}
return _index != -1;
}
/**
* 获取节点的成本。
* @param node 节点坐标
* @returns 节点的总成本
*/
private getCost(node: index): number {
let gcost = 0;
let hcost = 0;
this.gcostMap.forEach((value, key) => {
if (key.x == node.x && key.y == node.y) {
gcost = value;
}
});
this.hcostMap.forEach((value, key) => {
if (key.x == node.x && key.y == node.y) {
hcost = value;
}
});
return gcost + hcost;
}
/**
* 获取开放列表中成本最小的节点。
* @param list 开放列表
* @returns 成本最小的节点
*/
private getMinCostNode(list: index[]): index {
let _minindex = -1;
let _mincost = Number.MAX_SAFE_INTEGER;
// 寻找成本最小的节点
for (let i = 0; i < list.length; i++) {
const cost = this.getCost(list[i]);
if (cost < _mincost) {
_minindex = i;
_mincost = cost;
}
}
return list[_minindex];
}
/**
* 更新节点的成本和父节点信息。
* @param node 节点坐标
* @param gcost 从起点到当前节点的实际成本
* @param hcost 从当前节点到终点的估算成本
*/
private updateCost(node: index, gcost: number, hcost: number) {
this.gcostMap.set(node, gcost);
this.hcostMap.set(node, hcost);
}
/**
* 更新节点的父节点。
* @param node 节点坐标
* @param parent 父节点坐标
*/
private updateParent(node: index, parent: index) {
const existingparent = this.parentMap.get(node);
// 仅当新的父节点成本更低时更新
if (!existingparent || this.getCost(parent) < this.getCost(existingparent)) {
this.parentMap.set(node, parent);
}
}
/**
* 根据父节点映射重构路径。
* @param endPoint 终点坐标
* @returns 从起点到终点的路径
*/
private reconstructPath(endPoint: index) {
const path = [endPoint];
let currentnode = endPoint;
// 逆向回溯路径
while (currentnode) {
let parent = null;
this.parentMap.forEach((value, key) => {
if (currentnode.x == key.x && currentnode.y == key.y) {
parent = value;
}
})
if (parent) {
path.unshift(parent);
currentnode = parent;
} else {
currentnode = null;
}
}
return path;
}
/**
* 检查给定的索引是否为有效索引。
* @param index 一个包含x和y属性的对象代表要检查的索引位置。
* @returns 返回一个布尔值如果索引位置有效则为true否则为false。
*/
private isValidIndex(index: index): boolean {
return index.x >= 0 && index.x < this.map[0].length && index.y >= 0 && index.y < this.map.length;
}
/**
* 判断当前节点是否到达了目标节点。
* @param node 一个包含x和y属性的对象代表当前节点的位置。
* @param end 一个包含x和y属性的对象代表目标节点的位置。
* @returns 返回一个布尔值如果当前节点已到达目标节点则为true否则为false。
*/
private isArrived(node: index, end: index) {
// 比较当前节点和目标节点的坐标,判断是否已经到达目标位置
return node.x == end.x && node.y == end.y;
}
}