import { color, v3 } from "cc"; import { AsyncQueue } from "../../../../../extensions/oops-plugin-framework/assets/libs/collection/AsyncQueue"; import { ecs } from "../../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { Grid } from "../../grid/Grid"; import { Checkpoint } from "../Checkpoint"; import { CheckpointModelLevelComp } from "../model/CheckpointModelLevel"; import { CheckpointViewComp } from "../view/CheckpointViewComp"; import { CheckpointModelComp } from "../model/CheckpointModel"; import { Station } from "../../station/Station"; import { GridModelComp } from "../../grid/model/GridModelComp"; import { Obstacle } from "../../obstacle/Obstacle"; import { Puppet } from "../../puppet/puppet"; import { PuppetModelComp } from "../../puppet/model/PuppetModelComp"; import { ObstacleModelComp } from "../../obstacle/model/ObstacleModelComp"; import { PathFindComp } from "../../common/ecs/path/PathFind"; import { oops } from "../../../../../extensions/oops-plugin-framework/assets/core/Oops"; import { Vehicle } from "../../vehicle/Vehicle"; import { VehicleModelComp } from "../../vehicle/model/VehicleModelComp"; import { VehicleOperationComp } from "./VehicleOperation"; import { UIID } from "../../common/config/GameUIConfig"; import { CheckpointModelBaseComp } from "../model/CheckpointModelBase"; import { SingletonModuleComp, smc } from "../../common/SingletonModuleComp"; import { ECSEntity } from "../../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECSEntity"; import { Subway } from "../../subway/Subway"; import { SubwayModelComp } from "../../subway/model/SubwayModelComp"; import { SubwayEnum } from "../../subway/model/SubwayEnum"; import { CheckpointPathTriggerComp } from "./CheckpointPathTrigger"; import { ArrayUtil } from "../../../../../extensions/oops-plugin-framework/assets/core/utils/ArrayUtil"; /** 初始化游戏公共资源 */ @ecs.register('InitCheckpoint') export class InitCheckpointComp extends ecs.Comp { reset() { } } export class InitCheckpointSystem extends ecs.ComblockSystem implements ecs.IEntityEnterSystem { filter(): ecs.IMatcher { return ecs.allOf(InitCheckpointComp, CheckpointModelComp, CheckpointModelLevelComp, CheckpointModelBaseComp); } entityEnter(e: Checkpoint): void { const levelConfig = e.get(CheckpointModelLevelComp)?.rtluCurrent const { gridRowCount, gridColCount, levelColor, peopleCount, vehicleColor, vehicleType, obstaclePosition, stationCount, peopleColor, peoplePosition, subwayPosition, subwayDir, subwayInfo } = levelConfig this.resetCheckpoint(e) // 关卡数据 oops.audio.volumeMusic = 1 e.CheckpointModel.vmAdd(); e.CheckpointModelBase.vmAdd(); !e.CheckpointModelLevel && e.CheckpointModelLevel.vmAdd(); // 添加关卡到场景 e.load(oops.game.root, v3(0, 0, 0), () => { this.createGrid(e, gridRowCount, gridColCount) if (peopleCount) { // 自动生成 e.CheckpointModel.peopleCount = peopleCount const count = Math.ceil(peopleCount / 3) const colorCount = this.distributePeopleToColorsByArray(peopleCount, levelColor) const { gridPositions, gridColors, subwayPositions, subwayColors, subwayOrientations } = this.distributeToGridAndSubwayWithOptimizedPlacement(gridRowCount, gridColCount, colorCount, levelColor, 24) this.createMan(e, gridPositions, gridColors, levelColor) this.createSubway(e, subwayPositions, subwayOrientations, subwayColors, levelColor) this.createStation(e, stationCount) this.createVehicle(e, count, [], colorCount, levelColor) } else { // 依据配置生成 this.createObstacle(e, obstaclePosition) this.createSubway(e, subwayPosition, subwayDir, subwayInfo, levelColor) this.createStation(e, stationCount) let subwayPeople = 0 let flatSubwayArr = [] if (subwayInfo) { flatSubwayArr = subwayInfo.flat() subwayPeople = flatSubwayArr.length } const colorCount = {} const colorArr = levelColor as number[] let newPeoplePosition = [] if (peoplePosition&&peoplePosition.length>0) { newPeoplePosition = [...peoplePosition] } else { e.CheckpointModel.cells?.forEach((v, xIndex) => { v?.forEach((val, yIndex) => { if (val == null) newPeoplePosition.push([xIndex + 1, yIndex + 1]) }) }) } if (peopleColor) { e.CheckpointModel.peopleCount = peopleColor.length + subwayPeople const count = Math.ceil((peopleColor.length + subwayPeople) / 3) colorArr.forEach((val, index) => { if (colorCount[val] == null) { colorCount[val] = 0 } colorCount[val] = peopleColor.filter(v => v === index + 1).length + flatSubwayArr.filter(v => v === index + 1).length }) this.createMan(e, newPeoplePosition, peopleColor, levelColor) this.createVehicle(e, count, vehicleColor, colorCount, levelColor) } else { e.CheckpointModel.peopleCount = (newPeoplePosition.length + subwayPeople) - (newPeoplePosition.length + subwayPeople) % 3 const count = Math.ceil((e.CheckpointModel.peopleCount) / 3) colorArr.forEach((val, index) => { if (colorCount[val] == null) { colorCount[val] = 0 } colorCount[val] = flatSubwayArr.filter(v => v === index + 1).length }) Object.entries(colorCount).forEach(([color, count]) => { const remainCount = (count as number) % 3 if (remainCount !== 0) { const needCount = 3 - remainCount if (newPeoplePosition.length < needCount) { console.error('人物位置数量无法支撑地铁中人物颜色为3的倍数') } else { for (let index = 0; index < needCount; index++) { const randIdx = Math.floor(Math.random() * newPeoplePosition.length); const pos = newPeoplePosition[randIdx] this.createSingleMan(e, pos, color) colorCount[color] += 1 newPeoplePosition.splice(randIdx, 1) } } } // console.log(color, count); }); const newColorCount = this.distributePeopleToColorsByArray(newPeoplePosition.length, levelColor) this.distributeToGrid(e, newPeoplePosition, newColorCount, levelColor) // this.createMan(e, peoplePosition, peopleColor, levelColor) // 合并两个colorCount对象 let mergedColorCount = { ...colorCount }; Object.keys(newColorCount).forEach(color => { if (mergedColorCount[color]) { // 如果color在mergedColorCount中已存在,则累加其值 mergedColorCount[color] += newColorCount[color]; } else { // 如果color在mergedColorCount中不存在,则直接添加 mergedColorCount[color] = newColorCount[color]; } }); this.createVehicle(e, count, vehicleColor, mergedColorCount, levelColor) } this.fillEmptyMapInfo(e) } e.add(VehicleOperationComp) e.add(CheckpointPathTriggerComp) e.remove(InitCheckpointComp) // 关闭加载界面 oops.gui.remove(UIID.Loading); }); oops.gui.open(UIID.Game) if (e.CheckpointModelLevel.vm.lv === 1) { // 一级新手引导 oops.gui.open(UIID.Guide) } } resetCheckpoint(e: Checkpoint) { e.remove(CheckpointViewComp); e.add(CheckpointModelComp, true) e.add(CheckpointModelBaseComp, true) // e.add(CheckpointModelLevelComp, true) e.children.forEach(child => { e.removeChild(child); child.destroy(); }); } distributePeopleToColorsByArray(totalPeople: number, colors: string[]) { // 验证输入 if (totalPeople % 3 !== 0) { console.error('配置自动生成生成不是3的倍数,将去除余数') } const adapTotalPeople = totalPeople - totalPeople % 3 const colorCount = colors.length; let baseDistribution = Math.floor(adapTotalPeople / colorCount); let remainder = adapTotalPeople % colorCount; // 确保基础分配是3的倍数 if (baseDistribution % 3 !== 0) { baseDistribution -= baseDistribution % 3; remainder += adapTotalPeople - (baseDistribution * colorCount); } // 初始化颜色分配对象 const colorDistribution = colors.reduce((acc, color) => { acc[color] = baseDistribution; return acc; }, {}); // 处理余数,尽可能平均分配 let index = 0; while (remainder > 0) { colorDistribution[colors[index]] += 3; // 每次增加3人以保持总数为3的倍数 remainder -= 3; index = (index + 1) % colorCount; // 环形处理颜色索引 } return colorDistribution; } distributeToGrid(e: Checkpoint, position: [x: number, y: number][], colorDistribution: any, colors: string[]) { // 创建颜色池 let colorPool: number[] = []; colors.forEach((color, index) => { for (let i = 0; i < colorDistribution[color]; i++) { colorPool.push(index + 1); } }); const randColorPool = this.shuffleArray(colorPool) randColorPool.forEach((colorIndex) => { // let people = colorDistribution[colors[colorIndex-1]]; if (position.length > 0) { let randomIndex = Math.floor(Math.random() * position.length); const pos = position[randomIndex]; this.createSingleMan(e, pos, colors[colorIndex - 1]) position.splice(randomIndex, 1); } }) } distributeToGridAndSubwayWithOptimizedPlacement(row: number, col: number, colorDistribution: any, colors: string[], subwayCapacity = 24) { const grid = Array.from({ length: row }, () => Array(col).fill(null)); let freePositions = []; let freePositionsCopy = []; for (let i = 0; i < row; i++) { for (let j = 0; j < col; j++) { freePositions.push([i, j]); freePositionsCopy.push([i, j]); } } const gridColors: number[] = [] const gridPositions: [x: number, y: number][] = [] const subwayPositions: [x: number, y: number][] = []; const subwayColors: number[][] = []; const subwayOrientations: number[] = []; const cellCount = row * col // 创建颜色池 let colorPool: number[] = []; colors.forEach((color, index) => { for (let i = 0; i < colorDistribution[color]; i++) { colorPool.push(index + 1); } }); const getSubwayOrientation = () => Math.random() < 0.5 ? SubwayEnum.LEFT : SubwayEnum.RIGHT; // // 随机选择颜色函数 // const selectRandomColor = () => { // if (colorPool.length === 0) return null; // let index = Math.floor(Math.random() * colorPool.length); // return colorPool.splice(index, 1)[0] as number; // 从颜色池中移除并返回选中的颜色 // }; const randColorPool = this.shuffleArray(colorPool) randColorPool.forEach((colorIndex) => { // let people = colorDistribution[colors[colorIndex-1]]; if (freePositions.length > 0) { let randomIndex = Math.floor(Math.random() * freePositions.length); let [x, y] = freePositions[randomIndex]; grid[x][y] = colorIndex; gridColors.push(colorIndex) gridPositions.push([x, y]) freePositions.splice(randomIndex, 1); } else { if (!subwayColors[subwayColors.length - 1] || subwayColors[subwayColors.length - 1].length >= subwayCapacity) { const orientation = getSubwayOrientation(); const filteredPositions = freePositionsCopy.filter(([x, y]) => ((orientation === SubwayEnum.LEFT && y > 0) || (orientation === SubwayEnum.RIGHT && y < col - 1)) && grid[x][y] !== 'Subway' && ((orientation === SubwayEnum.RIGHT && grid[x][y + 1] !== 'Subway') || (orientation === SubwayEnum.LEFT && grid[x][y - 1] !== 'Subway'))); if (filteredPositions.length > 0) { const index = Math.floor(Math.random() * filteredPositions.length); const [subwayX, subwayY] = filteredPositions[index]; const gridColor = grid[subwayX][subwayY] subwayPositions.push([subwayX, subwayY]); const existIndex = gridPositions.findIndex(val => { const [x, y] = val return x === subwayX && y === subwayY }) if (existIndex > -1) { gridPositions.splice(existIndex, 1) gridColors.splice(existIndex, 1) } subwayColors.push([gridColor, colorIndex]); // 新地铁的颜色 subwayOrientations.push(orientation); grid[subwayX][subwayY] = 'Subway'; freePositionsCopy.splice(index, 1); } } else { subwayColors[subwayColors.length - 1].push(colorIndex); // 添加到最后一个地铁的颜色 } } }) return { gridPositions: gridPositions.map(([x, y]) => [x + 1, y + 1]) as [x: number, y: number][], gridColors, subwayPositions: subwayPositions.map(([x, y]) => [x + 1, y + 1]) as [x: number, y: number][], subwayColors, subwayOrientations }; } // 洗牌算法打乱颜色 shuffleArray(array) { for (let i = array.length - 1; i > 0; i--) { // 生成从 0 到 i 的随机数 const j = Math.floor(Math.random() * (i + 1)); // 交换元素 array[i] 和 array[j] [array[i], array[j]] = [array[j], array[i]]; } return array; } // 生成棋盘相关 createGrid(e: Checkpoint, row: number, col: number) { const checkpoint_root = e.get(CheckpointViewComp).node const checkpoint_model = e.get(CheckpointModelComp) checkpoint_model.grids = Array.from({ length: row }, () => new Array(col).fill(null)); checkpoint_model.cells = Array.from({ length: row }, () => new Array(col).fill(null)); checkpoint_model.path_grid = Array.from({ length: row }, () => new Array(col).fill(null)); const width = 0.442; const gap = 0.025; const start_point = row % 2 === 0 ? v3(-(row / 2 * (width + gap) - gap / 2)+0.08, 0, 2.7) : v3(-(Math.floor(row / 2) * (width+gap) + width / 2), 0, 2.7) for (let index = 0; index < row; index++) { for (let j = 0; j < col; j++) { const gridEnt = ecs.getEntity(Grid); // 添加关卡到场景 const pos = v3(start_point.x + j * (width+gap), 0, start_point.z + index * (width+gap)) gridEnt.load(checkpoint_root, pos); e.addChild(gridEnt) checkpoint_model.grids[index][j] = gridEnt // if (typeof grids[index][j] === 'number') { // 生成障碍物 // const obstacle = ecs.getEntity(Obstacle) // const obstacleModel = obstacle.get(ObstacleModelComp) // obstacleModel.type = fill // obstacle.load(checkpoint_root, pos); // checkpoint_model.cells[index][j] = obstacle // checkpoint_model.path_grid[index][j] = { // x: index, // y: j, // fill: fill, // pos: pos // } // } else if (typeof grids[index][j] === 'string') { // 生成人物 // const puppet = ecs.getEntity(Puppet) // const puppetModel = puppet.get(PuppetModelComp) // puppetModel.color = fill // puppetModel.x = index // puppetModel.y = j // puppet.load(checkpoint_root, fill, pos, smc.initialize.account.AccountModel.skin); // checkpoint_model.cells[index][j] = puppet // checkpoint_model.path_grid[index][j] = { // x: index, // y: j, // fill: fill, // pos: pos // } // const pathComp = puppet.add(PathFindComp) // pathComp.x = index // pathComp.y = j // } else { // 空格 // checkpoint_model.path_grid[index][j] = { // x: index, // y: j, // fill: null, // pos: pos // } // } } } } // 生成人物 createMan(e: Checkpoint, position: [x: number, y: number][], color: number[], colorArr: string[]) { const checkpoint_root = e.get(CheckpointViewComp).node const checkpoint_model = e.get(CheckpointModelComp) position && position.forEach((val, index) => { const [x, y] = val const xIndex = x - 1 const yIndex = y - 1 const puppet = ecs.getEntity(Puppet) const puppetModel = puppet.get(PuppetModelComp) const fillColor = colorArr[color[index] - 1] puppetModel.color = fillColor puppetModel.x = xIndex puppetModel.y = yIndex const pos = checkpoint_model.grids[xIndex][yIndex].GridView.node.position.clone() puppet.load(checkpoint_root, fillColor, pos, smc.initialize.account.AccountModel.skin); checkpoint_model.cells[xIndex][yIndex] = puppet checkpoint_model.path_grid[xIndex][yIndex] = { x: xIndex, y: yIndex, fill: fillColor, pos: pos } const pathComp = puppet.add(PathFindComp) pathComp.x = xIndex pathComp.y = yIndex }) } fillEmptyMapInfo(e: Checkpoint) { const checkpoint_model = e.CheckpointModel checkpoint_model.path_grid?.forEach((v, xIndex) => { v.forEach((val, yIndex) => { if (val == null) { const pos = checkpoint_model.grids[xIndex][yIndex].GridView.node.position.clone() checkpoint_model.path_grid[xIndex][yIndex] = { x: xIndex, y: yIndex, fill: null, pos: pos } } }) }) } // 生成单个人物 createSingleMan(e: Checkpoint, position: [x: number, y: number], color: string) { const checkpoint_root = e.get(CheckpointViewComp).node const checkpoint_model = e.get(CheckpointModelComp) const [x, y] = position const xIndex = x - 1 const yIndex = y - 1 const puppet = ecs.getEntity(Puppet) const puppetModel = puppet.get(PuppetModelComp) const fillColor = color puppetModel.color = fillColor puppetModel.x = xIndex puppetModel.y = yIndex const pos = checkpoint_model.grids[xIndex][yIndex].GridView.node.position.clone() puppet.load(checkpoint_root, fillColor, pos, smc.initialize.account.AccountModel.skin); checkpoint_model.cells[xIndex][yIndex] = puppet checkpoint_model.path_grid[xIndex][yIndex] = { x: xIndex, y: yIndex, fill: fillColor, pos: pos } const pathComp = puppet.add(PathFindComp) pathComp.x = xIndex pathComp.y = yIndex } // 生成障碍物 createObstacle(e: Checkpoint, position: [x: number, y: number][]) { const checkpoint_root = e.get(CheckpointViewComp).node const checkpoint_model = e.get(CheckpointModelComp) position && position.forEach((val, index) => { const obstacle = ecs.getEntity(Obstacle) const [x, y] = val const xIndex = x - 1 const yIndex = y - 1 const pos = checkpoint_model.grids[xIndex][yIndex].GridView.node.position.clone() obstacle.load(checkpoint_root, pos); checkpoint_model.cells[xIndex][yIndex] = obstacle checkpoint_model.path_grid[xIndex][yIndex] = { x: xIndex, y: yIndex, fill: 'obstacle', pos: pos } }) } // 生成地铁 createSubway(e: Checkpoint, position: [x: number, y: number][], dir: number[], info: number[][], colorArr: string[]) { const checkpoint_root = e.get(CheckpointViewComp).node const checkpoint_model = e.get(CheckpointModelComp) position && position.forEach((val, index) => { const [x, y] = val const xIndex = x - 1 const yIndex = y - 1 const pos = checkpoint_model.grids[xIndex][yIndex].GridView.node.position.clone() const d = dir[index] const subway = ecs.getEntity(Subway) const subwayModel = subway.SubwayModel subwayModel.colorArr = info[index].map(v => colorArr[v - 1]) subwayModel.type = d subwayModel.x = xIndex subwayModel.y = yIndex subway.load(checkpoint_root, pos, d); checkpoint_model.cells[xIndex][yIndex] = subway checkpoint_model.path_grid[xIndex][yIndex] = { x: xIndex, y: yIndex, fill: 'subway', pos: pos } }) } // 生成站台 createStation(e: Checkpoint, count: number) { const checkpoint_root = e.get(CheckpointViewComp).node const checkpoint_model = e.get(CheckpointModelComp) const start_point = v3(-1.2, 0, 1.2) for (let index = 0; index < count; index++) { const station = ecs.getEntity(Station); // 添加关卡到场景 const h_index = index % 5 // const v_index = Math.floor(index / 5) const v_index = checkpoint_model.stations.length >= 5 ? 1 : 0 station.load(checkpoint_root, v3(start_point.x + h_index * 0.5, 0, start_point.z + v_index * 0.5)); e.addChild(station) checkpoint_model.stations.push(station) } } // 生成交通工具 createVehicle(e: Checkpoint, count: number, pcolor: number[], colorCount: any, colors: string[]) { const copyColorCount = { ...colorCount } const checkpoint_root = e.CheckpointView.node const checkpoint_model = e.CheckpointModel const availablePositions = Array.from({ length: count }, (_, i) => i) checkpoint_model.vehicles = Array(count).fill(null) const start_point = v3(-6, 0, 0) pcolor?.forEach((v, i) => { const color = colors[pcolor[i] - 1] if (copyColorCount[color] > 0) { const vehicle = ecs.getEntity(Vehicle); availablePositions.shift() copyColorCount[color] -= 3; // 添加车到场景 vehicle.VehicleModel.color = color const vehicleType = e.CheckpointModelLevel.rtluCurrent.vehicleType vehicle.load(checkpoint_root, color, start_point, vehicleType); e.addChild(vehicle) checkpoint_model.vehicles[i] = vehicle } }) while (availablePositions.length > 0) { let randomIndex = Math.floor(Math.random() * availablePositions.length); let colorIndex = Math.floor(Math.random() * colors.length); let color = colors[colorIndex]; if (copyColorCount[color] > 0) { // if (randomIndex < pcolor.length) { // availablePositions.splice(randomIndex, 1); // } const vehicle = ecs.getEntity(Vehicle); let index = availablePositions.splice(randomIndex, 1)[0]; copyColorCount[color] -= 3; // 添加车到场景 vehicle.VehicleModel.color = color const vehicleType = e.CheckpointModelLevel.rtluCurrent.vehicleType vehicle.load(checkpoint_root, color, start_point, vehicleType); e.addChild(vehicle) checkpoint_model.vehicles[index] = vehicle } } // for (let index = 0; index < count; index++) { // const vehicle = ecs.getEntity(Vehicle); // const vehicleModel = vehicle.get(VehicleModelComp) // if (index < color.length) { // const v_color = colors[color[index] - 1] // vehicleModel.color = v_color // colorCount[v_color] = colorCount[v_color] - 1 // } else { // const v_color = colors[index % 3] // vehicleModel.color // } // // 添加车到场景 // const vehicleType = e.CheckpointModelLevel.rtluCurrent.vehicleType // vehicle.load(checkpoint_root, vehicleModel.color, start_point, vehicleType); // e.addChild(vehicle) // checkpoint_model.vehicles.push(vehicle) // } } // // 生成棋盘相关 // createGrid(e: Checkpoint, row: number, col: number, colors: string[], obstacles: number[], peopleCount: number, obstacleCount: number) { // const checkpoint_root = e.get(CheckpointViewComp).node // const checkpoint_model = e.get(CheckpointModelComp) // const grids = this.generateGridWithEmptySpaces(row, col, colors, obstacles, peopleCount, obstacleCount) // checkpoint_model.grids = Array.from({ length: row }, () => new Array(col).fill(null)); // checkpoint_model.cells = Array.from({ length: row }, () => new Array(col).fill(null)); // checkpoint_model.path_grid = Array.from({ length: row }, () => new Array(col).fill(null)); // const start_point = v3(-1.9, 0, 2.7) // for (let index = 0; index < grids.length; index++) { // for (let j = 0; j < grids[index].length; j++) { // const gridEnt = ecs.getEntity(Grid); // const gridModel = gridEnt.get(GridModelComp) // // 添加关卡到场景 // const fill = grids[index][j] // gridModel.color = fill // const pos = v3(start_point.x + j * 0.5, 0, start_point.z + index * 0.5) // gridEnt.load(checkpoint_root, pos); // e.addChild(gridEnt) // checkpoint_model.grids[index][j] = gridEnt // if (typeof grids[index][j] === 'number') { // 生成障碍物 // const obstacle = ecs.getEntity(Obstacle) // const obstacleModel = obstacle.get(ObstacleModelComp) // obstacleModel.type = fill // obstacle.load(checkpoint_root, pos); // checkpoint_model.cells[index][j] = obstacle // checkpoint_model.path_grid[index][j] = { // x: index, // y: j, // fill: fill, // pos: pos // } // } else if (typeof grids[index][j] === 'string') { // 生成人物 // const puppet = ecs.getEntity(Puppet) // const puppetModel = puppet.get(PuppetModelComp) // puppetModel.color = fill // puppetModel.x = index // puppetModel.y = j // puppet.load(checkpoint_root, fill, pos, smc.initialize.account.AccountModel.skin); // checkpoint_model.cells[index][j] = puppet // checkpoint_model.path_grid[index][j] = { // x: index, // y: j, // fill: fill, // pos: pos // } // const pathComp = puppet.add(PathFindComp) // pathComp.x = index // pathComp.y = j // } else { // 空格 // checkpoint_model.path_grid[index][j] = { // x: index, // y: j, // fill: null, // pos: pos // } // } // } // } // } // // 生成棋盘格 // createGrid(e: Checkpoint, row: number, col: number) { // const checkpoint_root = e.get(CheckpointViewComp).node // const checkpoint_model = e.get(CheckpointModelComp) // checkpoint_model.grids = Array.from({ length: row }, () => new Array(col).fill(null)); // const start_point = v3(-1.706, 0, -1.718) // for (let index = 0; index < row; index++) { // for (let j = 0; j < col; j++) { // const grid = ecs.getEntity(Grid); // // 添加关卡到场景 // grid.load(checkpoint_root, v3(start_point.x + index * 0.6, 0, start_point.z + j * 0.6)); // e.addChild(grid) // checkpoint_model.grids[index][j] = grid // } // } // } calcMaxCount(row: number, col: number, peopleCount: number) { const totalCells = row * col; let maxCount = Math.floor((totalCells - 1) / 3) * 3; // 最大可能的 3 的倍数 return Math.min(maxCount / 3, peopleCount * 3); // 分配三分之一 } generateGridWithEmptySpaces(row: number, col: number, colors: string[], obstacles: number[], peopleCount: number, obstacleCount: number) { let grid = Array.from({ length: row }, () => new Array(col).fill(null)); // 初始化颜色计数 let counts = {}; colors.forEach(color => { counts[color] = this.calcMaxCount(row, col, peopleCount); // 分配三分之一 }); // 创建所有可能的格子位置数组 let availablePositions = []; for (let i = 0; i < row; i++) { for (let j = 0; j < col; j++) { availablePositions.push([i, j]); } } let obstacleNum = obstacleCount // 随机分配颜色到网格中 while (availablePositions.length > 0) { let randomIndex = Math.floor(Math.random() * availablePositions.length); let position = availablePositions.splice(randomIndex, 1)[0]; let x = position[0]; let y = position[1]; let colorIndex = Math.floor(Math.random() * colors.length); let color = colors[colorIndex]; if (counts[color] > 0) { grid[x][y] = color; counts[color]--; } else if (obstacleNum > 0) { grid[x][y] = obstacles[Math.floor(Math.random() * obstacles.length)] obstacleNum-- } } return grid; } // generateOptimizedGrid(colors:string[]) { // const gridSize = 7; // const totalCells = gridSize * gridSize; // // const colors = ['红色', '蓝色', '绿色']; // let grid = Array(gridSize).fill().map(() => Array(gridSize).fill('')); // // 初始化每种颜色的人数 // let counts = { '红色': 0, '蓝色': 0, '绿色': 0 }; // // 首先分配每种颜色的人数,使其尽可能接近总数且是 3 的倍数 // for (let color of colors) { // let maxCount = Math.floor((totalCells - 1) / 3) * 3; // 最大可能的 3 的倍数 // counts[color] = maxCount / 3; // 分配三分之一 // } // // 在剩余的空格中随机分配颜色或保持为空 // let remainingCells = totalCells - 3 * Math.floor((totalCells - 1) / 3); // let colorIndices = colors.map((_, index) => index); // while (remainingCells > 0) { // let randomIndex = Math.floor(Math.random() * colorIndices.length); // let color = colors[colorIndices[randomIndex]]; // counts[color]++; // remainingCells--; // } // // 将颜色分配到网格中 // let flatGrid = grid.flat(); // colors.forEach(color => { // for (let i = 0; i < counts[color]; i++) { // let pos; // do { // pos = Math.floor(Math.random() * flatGrid.length); // } while (flatGrid[pos] !== ''); // flatGrid[pos] = color; // } // }); // // 重新构建二维网格 // for (let i = 0; i < flatGrid.length; i++) { // grid[Math.floor(i / gridSize)][i % gridSize] = flatGrid[i]; // } // return grid; // } }