From 5dec8202cd663b406d127c6d25ed51313519d29d Mon Sep 17 00:00:00 2001 From: panw Date: Mon, 30 Mar 2026 19:26:31 +0800 Subject: [PATCH] =?UTF-8?q?feat(map):=20=E5=AE=9E=E7=8E=B0=E8=8B=B1?= =?UTF-8?q?=E9=9B=84=E5=87=BA=E7=94=9F=E7=82=B9=E5=8A=A8=E6=80=81=E5=88=86?= =?UTF-8?q?=E9=85=8D=E9=81=BF=E5=85=8D=E9=87=8D=E5=8F=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增英雄出生位置动态分配逻辑,根据英雄类型(近战/远程)设置不同的起始X坐标,并检查已有英雄位置避免重叠。当目标位置被占用时,自动横向偏移寻找可用位置,确保英雄出生时不会相互遮挡。 --- assets/script/game/map/MissionHeroComp.ts | 55 ++++++++++++++++++++--- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/assets/script/game/map/MissionHeroComp.ts b/assets/script/game/map/MissionHeroComp.ts index e3505bb5..88000d8a 100644 --- a/assets/script/game/map/MissionHeroComp.ts +++ b/assets/script/game/map/MissionHeroComp.ts @@ -5,11 +5,12 @@ import { Hero } from "../hero/Hero"; import { smc } from "../common/SingletonModuleComp"; import { Timer } from "db://oops-framework/core/common/timer/Timer"; import { GameEvent } from "../common/config/GameEvent"; -import { HeroPos } from "../common/config/heroSet"; +import { HeroInfo, HeroPos, HType } from "../common/config/heroSet"; import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops"; import { HeroAttrsComp } from "../hero/HeroAttrsComp"; import { FacSet } from "../common/config/GameSet"; import { oneCom } from "../skill/oncend"; +import { HeroViewComp } from "../hero/HeroViewComp"; const { ccclass } = _decorator; /** 视图层对象 */ @@ -18,6 +19,14 @@ const { ccclass } = _decorator; export class MissionHeroCompComp extends CCComp { /** 英雄出生时的掉落高度,用于表现从空中落地 */ private static readonly HERO_DROP_HEIGHT = 260 + /** 出生点横向间隔 */ + private static readonly HERO_SPAWN_STEP_X = -60 + /** 近战起始出生 X */ + private static readonly HERO_SPAWN_START_MELEE_X = -50 + /** 远程(含中程)起始出生 X */ + private static readonly HERO_SPAWN_START_RANGED_X = -150 + /** 占位判断容差 */ + private static readonly HERO_SPAWN_OCCUPY_EPSILON_X = 10 /** 预留计时器 */ timer:Timer=new Timer(2) /** 预留状态:友方是否全部死亡 */ @@ -88,15 +97,52 @@ export class MissionHeroCompComp extends CCComp { /** 添加英雄:固定出生点上方生成,再落至落点 */ private addHero(uuid:number=1001,hero_lv:number=1) { console.log("addHero uuid:",uuid) - let hero_pos=0 let hero = ecs.getEntity(Hero); let scale = 1 - let landingPos:Vec3 = HeroPos[hero_pos].pos; + const landingPos = this.resolveHeroLandingPos(uuid); let spawnPos:Vec3 = v3(landingPos.x, landingPos.y + MissionHeroCompComp.HERO_DROP_HEIGHT, 0); hero.load(spawnPos,scale,uuid,landingPos.y,hero_lv); return hero; } + private resolveHeroLandingPos(uuid: number): Vec3 { + const hero_pos = 0; + const baseY = HeroPos[hero_pos].pos.y; + const startX = this.resolveSpawnStartX(uuid); + let candidateX = startX; + let guard = 0; + while (guard < 50) { + if (!this.isSpawnXOccupied(candidateX, baseY)) { + break; + } + candidateX += MissionHeroCompComp.HERO_SPAWN_STEP_X; + guard += 1; + } + return v3(candidateX, baseY, 0); + } + + private resolveSpawnStartX(uuid: number): number { + const heroType = HeroInfo[uuid]?.type; + return heroType === HType.Melee + ? MissionHeroCompComp.HERO_SPAWN_START_MELEE_X + : MissionHeroCompComp.HERO_SPAWN_START_RANGED_X; + } + + private isSpawnXOccupied(targetX: number, baseY: number): boolean { + const aliveHeroes = this.getAliveHeroes(); + for (let i = 0; i < aliveHeroes.length; i++) { + const view = aliveHeroes[i].get(HeroViewComp); + const node = view?.node; + if (!node || !node.isValid) continue; + const pos = node.getPosition(); + if (Math.abs(pos.y - baseY) > 80) continue; + if (Math.abs(pos.x - targetX) <= MissionHeroCompComp.HERO_SPAWN_OCCUPY_EPSILON_X) { + return true; + } + } + return false; + } + /** 添加合成后的新英雄,并覆盖为聚合后的属性 */ private addMergedHero(uuid:number, hero_lv:number, ap:number, hp_max:number): number { const hero = this.addHero(uuid, hero_lv); @@ -248,8 +294,7 @@ export class MissionHeroCompComp extends CCComp { sumAp += model.ap; sumHpMax += model.hp_max; } - let hero_pos = 0; - const landingPos:Vec3 = HeroPos[hero_pos].pos; + const landingPos = this.resolveHeroLandingPos(uuid); const spawnPos:Vec3 = v3(landingPos.x, landingPos.y + MissionHeroCompComp.HERO_DROP_HEIGHT, 0); await this.mergeDestroyAtBirth(mergeHeroes, spawnPos); await this.playMergeBoomFx(spawnPos);