feat(map): 实现英雄出生点动态分配避免重叠
新增英雄出生位置动态分配逻辑,根据英雄类型(近战/远程)设置不同的起始X坐标,并检查已有英雄位置避免重叠。当目标位置被占用时,自动横向偏移寻找可用位置,确保英雄出生时不会相互遮挡。
This commit is contained in:
@@ -5,11 +5,12 @@ import { Hero } from "../hero/Hero";
|
|||||||
import { smc } from "../common/SingletonModuleComp";
|
import { smc } from "../common/SingletonModuleComp";
|
||||||
import { Timer } from "db://oops-framework/core/common/timer/Timer";
|
import { Timer } from "db://oops-framework/core/common/timer/Timer";
|
||||||
import { GameEvent } from "../common/config/GameEvent";
|
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 { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
|
||||||
import { HeroAttrsComp } from "../hero/HeroAttrsComp";
|
import { HeroAttrsComp } from "../hero/HeroAttrsComp";
|
||||||
import { FacSet } from "../common/config/GameSet";
|
import { FacSet } from "../common/config/GameSet";
|
||||||
import { oneCom } from "../skill/oncend";
|
import { oneCom } from "../skill/oncend";
|
||||||
|
import { HeroViewComp } from "../hero/HeroViewComp";
|
||||||
const { ccclass } = _decorator;
|
const { ccclass } = _decorator;
|
||||||
|
|
||||||
/** 视图层对象 */
|
/** 视图层对象 */
|
||||||
@@ -18,6 +19,14 @@ const { ccclass } = _decorator;
|
|||||||
export class MissionHeroCompComp extends CCComp {
|
export class MissionHeroCompComp extends CCComp {
|
||||||
/** 英雄出生时的掉落高度,用于表现从空中落地 */
|
/** 英雄出生时的掉落高度,用于表现从空中落地 */
|
||||||
private static readonly HERO_DROP_HEIGHT = 260
|
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)
|
timer:Timer=new Timer(2)
|
||||||
/** 预留状态:友方是否全部死亡 */
|
/** 预留状态:友方是否全部死亡 */
|
||||||
@@ -88,15 +97,52 @@ export class MissionHeroCompComp extends CCComp {
|
|||||||
/** 添加英雄:固定出生点上方生成,再落至落点 */
|
/** 添加英雄:固定出生点上方生成,再落至落点 */
|
||||||
private addHero(uuid:number=1001,hero_lv:number=1) {
|
private addHero(uuid:number=1001,hero_lv:number=1) {
|
||||||
console.log("addHero uuid:",uuid)
|
console.log("addHero uuid:",uuid)
|
||||||
let hero_pos=0
|
|
||||||
let hero = ecs.getEntity<Hero>(Hero);
|
let hero = ecs.getEntity<Hero>(Hero);
|
||||||
let scale = 1
|
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);
|
let spawnPos:Vec3 = v3(landingPos.x, landingPos.y + MissionHeroCompComp.HERO_DROP_HEIGHT, 0);
|
||||||
hero.load(spawnPos,scale,uuid,landingPos.y,hero_lv);
|
hero.load(spawnPos,scale,uuid,landingPos.y,hero_lv);
|
||||||
return hero;
|
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 {
|
private addMergedHero(uuid:number, hero_lv:number, ap:number, hp_max:number): number {
|
||||||
const hero = this.addHero(uuid, hero_lv);
|
const hero = this.addHero(uuid, hero_lv);
|
||||||
@@ -248,8 +294,7 @@ export class MissionHeroCompComp extends CCComp {
|
|||||||
sumAp += model.ap;
|
sumAp += model.ap;
|
||||||
sumHpMax += model.hp_max;
|
sumHpMax += model.hp_max;
|
||||||
}
|
}
|
||||||
let hero_pos = 0;
|
const landingPos = this.resolveHeroLandingPos(uuid);
|
||||||
const landingPos:Vec3 = HeroPos[hero_pos].pos;
|
|
||||||
const spawnPos:Vec3 = v3(landingPos.x, landingPos.y + MissionHeroCompComp.HERO_DROP_HEIGHT, 0);
|
const spawnPos:Vec3 = v3(landingPos.x, landingPos.y + MissionHeroCompComp.HERO_DROP_HEIGHT, 0);
|
||||||
await this.mergeDestroyAtBirth(mergeHeroes, spawnPos);
|
await this.mergeDestroyAtBirth(mergeHeroes, spawnPos);
|
||||||
await this.playMergeBoomFx(spawnPos);
|
await this.playMergeBoomFx(spawnPos);
|
||||||
|
|||||||
Reference in New Issue
Block a user