解决一些小问题

This commit is contained in:
2025-11-01 15:02:31 +08:00
parent d014e63d27
commit cb844cf65f
32 changed files with 368 additions and 505 deletions

View File

@@ -1,236 +0,0 @@
import { _decorator, Animation, CCBoolean, Collider2D, Contact2DType, Tween, UITransform, v3, Vec3 } from "cc";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
import { BezierMove } from "../BezierMove/BezierMove";
import { DTType, EType, SkillSet, SType } from "../common/config/SkillSet";
import { BoxSet, FacSet } from "../common/config/BoxSet";
import { HeroViewComp } from "../hero/HeroViewComp";
import { GameEvent } from "../common/config/GameEvent";
import { smc } from "../common/SingletonModuleComp";
import { Attrs } from "../common/config/HeroAttrs";
const { ccclass, property } = _decorator;
/** 视图层对象 */
@ccclass('AtkConCom')
@ecs.register('AtkCon', false)
export class AtkConCom extends CCComp {
@property
public anmEnd: boolean = false;
@property
public cbox: boolean = false;
// 核心标识和配置
s_uuid:number = 0;
// 运行时状态(必须缓存的)
is_destroy:boolean = false;
startPos: Vec3 = v3(); // 起始位置
targetPos: Vec3 = v3(); // 目标位置
group:number = 0; //阵营
fac:number=0; //阵营
run_time:number = 0;
// 战斗相关运行时数据
Attrs:any=null
hit_count:number = 0;
// 组件引用
anim:Animation=null;
tweenInstance:Tween<any> = null;
private moveDirection: Vec3 | null = null; // 添加一个属性来存储移动方向
// 缓存的配置对象(避免重复查找)
public Config: any = null;
private isInitialized: boolean = false;
private initializeConfig() {
if (this.isInitialized) return;
// 缓存技能配置,避免重复查找
this.Config = SkillSet[this.s_uuid];
if (!this.Config) {
// console.error("[SkillCom] 技能配置不存在:", this.s_uuid);
return;
}
this.isInitialized = true;
// console.log("[SkillCom] 技能配置初始化完成:", this.s_uuid, this.Config.name);
}
start() {
this.initializeConfig();
// var entity = this.ent as ecs.Entity; // ecs.Entity 可转为当前模块的具体实体对象
// this.on(ModuleEvent.Cmd, this.onHandler, this);
this.anim=this.node.getComponent(Animation)
this.on(GameEvent.MissionEnd, this.doDestroy, this);
this.node.active = true;
let collider = this.getComponent(Collider2D);
if(collider) {
collider.group = this.group;
collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
}
}
do_anim(){
if(this.node.getComponent(Animation)){
let anim = this.node.getComponent(Animation);
//console.log("[SkillCom]:has anim",anim)
anim.on(Animation.EventType.FINISHED, this.onAnimationFinished, this);
}
}
do_parabolic(){
let bm=this.node.getComponent(BezierMove)
this.node.angle +=10
// bm.speed=700
if(this.group==BoxSet.MONSTER) {bm.controlPointSide=-1 }
bm.rotationSmoothness=0.6
bm.moveTo(this.targetPos)
}
do_line(){
let bm=this.node.getComponent(BezierMove)
let s_x=this.startPos.x
let s_y=this.startPos.y
let t_x=this.targetPos.x
let t_y=this.targetPos.y
// 设定目标x
this.targetPos.x = 400;
if(this.group == BoxSet.MONSTER) {
bm.controlPointSide = -1;
this.targetPos.x = -400;
}
// 计算斜率
const k = (t_y - s_y) / (t_x - s_x);
// 按直线公式计算新的y
this.targetPos.y = k * (this.targetPos.x - s_x) + s_y;
bm.controlPointOffset=0
bm.rotationSmoothness=0.6
bm.moveTo(this.targetPos);
}
do_fixedEnd(){
this.node.setPosition(this.targetPos.x > 360?300:this.targetPos.x,this.node.position.y,0)
this.do_anim()
}
do_fixedStart(){
this.node.setPosition(this.startPos.x,this.node.position.y,0)
this.do_anim()
}
onAnimationFinished(){
// console.log("[SkillCom]:onAnimationFinished",this.s_uuid)
if (!this.Config) return;
if(this.Config.EType==EType.timeEnd) return
if(this.Config.SType!=SType.damage){
}
this.is_destroy=true
}
onBeginContact (seCol: Collider2D, oCol: Collider2D) {
// console.log(this.scale+"碰撞开始 ",seCol,oCol);
if(seCol.node.position.x-oCol.node.position.x > 100 ) return
let target = oCol.getComponent(HeroViewComp)
if(oCol.group!=this.group){
if(target == null) return;
if (!this.Config) return;
// console.log("[SkillCom]:onBeginContact oCol||seCol",oCol.node.position,seCol.node.position)
this.single_damage(target,this.Config.DTType==DTType.range?true:false)
// this.ent.destroy()
}
}
//单体伤害
single_damage(target:HeroViewComp,is_range:boolean=false){
// //console.log("[SkillCom]:onBeginContact hit_count:",this.hit_count,SkillSet[this.s_uuid].hit)
// if(this.hit_count > 0&&!is_range) this.ap=this.ap*(50+this.puncture_damage)/100 // 穿刺后 伤害减半,过滤范围伤害
if(target == null) return;
if (!this.Config) return;
let damage=Math.floor(this.Attrs[Attrs.AP]*(SkillSet[this.s_uuid].ap/100))
if(this.hit_count > 0 &&!is_range ){
let Percentage=Math.pow((50+this.Attrs[Attrs.PUNCTURE_DMG])/100, this.hit_count)
damage=damage*Percentage
}
target.do_atked(damage,this.Attrs,this.s_uuid) // ap 及暴击 属性已经在skill.ts 处理
// console.log("[SkillCom]:single_damage t:tp:rtp",this.node.position,this.targetPos,target.node.position)
this.hit_count++
// console.log("[SkillCom]:碰撞次数:技能次数:穿刺次数",this.hit_count,this.Config.hit,this.puncture)
if(this.hit_count>=(this.Config.hit+this.Attrs[Attrs.PUNCTURE])&&(this.Config.DTType!=DTType.range)&&(this.Config.EType!=EType.animationEnd)&&(this.Config.EType!=EType.timeEnd)) this.is_destroy=true // 技能命中次数
}
update(deltaTime: number) {
// 确保配置已初始化(处理 update 可能先于 start 执行的情况)
if (!this.isInitialized) {
this.initializeConfig();
if (!this.Config) return;
}
if(smc.mission.pause) {
if(this.anim) this.anim.pause()
return;
}
if(this.anim) this.anim.resume()
if (!this.node || !this.node.isValid) return;
if(this.Config.EType==EType.timeEnd){
this.run_time+=deltaTime
if(this.run_time>this.Config.in){
// //console.log("[SkillCom]: timeEnd destroy",this.s_uuid,this.run_time)
this.is_destroy=true
}
}
this.toDestroy();
}
public atk(args:any){
let dis=this.node.getComponent(UITransform).width/2
let targetsInRange: HeroViewComp[] = []
// 收集范围内所有敌方目标
ecs.query(ecs.allOf(HeroViewComp)).some(e => {
const view = e.get(HeroViewComp);
if(view.fac!=this.fac) {
const distance = Math.abs(this.node.position.x - view.node.position.x);
if(distance <= dis) {
targetsInRange.push(view);
}
}
});
// 根据配置的hit_num决定攻击模式
const hitNum = SkillSet[this.s_uuid].hit_num || 0;
if(hitNum > 0) {
// 限制目标数量按距离排序选择最近的N个目标
if(targetsInRange.length > 0) {
// 按距离排序(从近到远)
targetsInRange.sort((a, b) => {
const distanceA = Math.abs(this.node.position.x - a.node.position.x);
const distanceB = Math.abs(this.node.position.x - b.node.position.x);
return distanceA - distanceB;
});
// 限制目标数量
const maxTargets = Math.min(hitNum, targetsInRange.length);
const selectedTargets = targetsInRange.slice(0, maxTargets);
selectedTargets.forEach(target => {
this.single_damage(target, false);
});
}
} else {
// 范围伤害:对所有范围内目标造成伤害
if(targetsInRange.length > 0) {
targetsInRange.forEach(target => {
this.single_damage(target, false);
});
}
}
}
toDestroy() {
if(this.is_destroy){
if (this.ent) {
this.ent.destroy();
} else {
// 如果ent不存在直接销毁节点
if (this.node && this.node.isValid) {
this.node.destroy();
}
}
}
}
doDestroy(){
// //console.log("[SkillCom]:doDestroy")
this.is_destroy=true
}
reset() {
this.node.destroy();
}
}

View File

@@ -1,9 +0,0 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "411a8c58-dab3-45d4-92d9-9fe420a9faa0",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -1,4 +1,5 @@
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { smc } from "../common/SingletonModuleComp";
/** 业务层对象 */
@ecs.register('EndAnmCom')
@@ -17,8 +18,7 @@ export class EndAnmComSystem extends ecs.ComblockSystem implements ecs.IEntityEn
entityEnter(e: ecs.Entity): void {
// 注:自定义业务逻辑
if(!smc.mission.play || smc.mission.pause) return;
e.remove(EndAnmComComp);
}
}

View File

@@ -3,6 +3,7 @@ import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ec
import { RType, EType, SkillSet } from "../common/config/SkillSet";
import { BoxSet } from "../common/config/BoxSet";
import { SkillView } from "./SkillView";
import { smc } from "../common/SingletonModuleComp";
/**
* ==================== 技能移动数据组件 ====================
@@ -283,6 +284,7 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
}
entityEnter(entity: ecs.Entity): void {
if(!smc.mission.play || smc.mission.pause) return;
const moveComp = entity.get(SMoveDataComp);
const skillView = entity.get(SkillView);
@@ -354,6 +356,7 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
}
update(entity: ecs.Entity): void {
if(!smc.mission.play || smc.mission.pause) return;
const moveComp = entity.get(SMoveDataComp);
const skillView = entity.get(SkillView);

View File

@@ -15,7 +15,7 @@ import { DamageQueueHelper } from "../hero/DamageQueueComp";
const { ccclass, property } = _decorator;
/** 视图层对象 */
@ccclass('SkillViewComp')
@ccclass('SkillView')
@ecs.register('SkillView', false)
export class SkillView extends CCComp {
/** 视图层逻辑代码分离演示 */
@@ -38,6 +38,7 @@ export class SkillView extends CCComp {
if(collider) {
collider.group = this.group;
collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
console.log(`[skillView] ${this.sData.caster.ent.get(HeroAttrsComp).hero_name}${this.SConf.name} 碰撞组 ${this.group}`)
}
if(this.node.getComponent(Animation)){
let anim = this.node.getComponent(Animation);
@@ -47,7 +48,7 @@ export class SkillView extends CCComp {
}
onBeginContact (seCol: Collider2D, oCol: Collider2D) {
// console.log(this.scale+"碰撞开始 ",seCol,oCol);
console.log(`[skillView] ${this.sData.caster.ent.get(HeroAttrsComp).hero_name}${this.SConf.name} 碰撞了 ${oCol.getComponent(HeroViewComp).ent.get(HeroAttrsComp).hero_name}`);
if(this.SConf.EType!=EType.collision) return
let target = oCol.getComponent(HeroViewComp)
let model=target.ent.get(HeroAttrsComp)

View File

@@ -1,156 +0,0 @@
import { _decorator, CCBoolean, CCFloat, CCInteger, instantiate, Node, Prefab, v3, Vec3 } from "cc";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
import { HeroViewComp } from "../hero/HeroViewComp";
import { RType, SkillSet } from "../common/config/SkillSet";
import { AtkConCom } from "./AtkConCom";
import { BoxSet } from "../common/config/BoxSet";
const { ccclass, property } = _decorator;
/** 视图层对象 */
@ccclass('SkillViewCom')
@ecs.register('SkillView', false)
export class SkillViewCom extends CCComp {
/** 视图层逻辑代码分离演示 */
@property({ type: Prefab })
atkPrefab: Prefab = null!
@property
hasReady: boolean = false
@property
withHero: boolean = true
@property
ReadyLoop: boolean = false // 预备是否循环
@property({ type: CCFloat })
SkillTime: number = 0 // 技能控制存续时间时间
@property({ type: CCFloat })
ReadyTime: number = 0 // 技能前摇时间
@property({ type: CCInteger })
runType: number = 0 //技能运行类型 0-线性 1-贝塞尔 2-开始位置固定 3-目标位置固定
@property({ type: CCInteger })
ready_y: number = 0
@property({ type: CCInteger })
atk_x: number = 0
@property({ type: CCInteger })
atk_y: number = 0
@property({ type: CCInteger })
s_count:number=1;
@property({ type: CCFloat })
s_interval:number=0.2;
endTime: number = 0;
readyFinish: boolean = false;
caster:HeroViewComp=null!;
s_uuid:number=0;
s_cd:number=0;
scale: number = 0;
cName:string="";
target:HeroViewComp=null;
parent:Node=null;
target_postions:any[]=null
group:number=0
fac:number=0
// 战斗相关运行时数据
Attrs:any=null
startPos:any=null
targetPos:any=null
start() {
// var entity = this.ent as ecs.Entity; // ecs.Entity 可转为当前模块的具体实体对象
this.node.getChildByName("ready").active = this.hasReady
this.node.setPosition(this.caster.node.position.x,this.caster.node.position.y+this.ready_y)
}
protected update(dt: number): void {
this.doTimer(dt)
this.move(dt)
this.doEnd(dt)
this.do_cd(dt)
if(this.readyFinish) this.doAtk(dt)
}
doEnd(dt: number) {
this.endTime += dt
if(this.endTime >= this.SkillTime) {
this.ent.destroy()
}
}
doTimer(dt: number){
if(this.ReadyTime > 0) this.ReadyTime -= dt
if(this.ReadyTime <=0) this.readyFinish=true
}
doAtk(dt:number): void {
if(this.s_cd <= 0&&this.s_count > 0) {
this.doSkill()
this.s_count--
this.s_cd = this.s_interval
}
}
do_cd(dt:number){
if(this.s_cd > 0) this.s_cd -= dt
}
doSkill(){
if(this.atkPrefab!=null){
let atkNode:Node = instantiate(this.atkPrefab)
atkNode.parent = this.node.parent
atkNode.setPosition(v3(this.node.position.x + this.atk_x*atkNode.scale.x, this.node.position.y + this.atk_y))
if(this.node.scale.x < 0){
atkNode.setScale(v3(atkNode.scale.x*-1,atkNode.scale.y,atkNode.scale.z))
}
let atkCom=atkNode.getComponent(AtkConCom)
// 计算延长后的目标点坐标
const originalStart = v3(this.node.position.x + this.atk_x, this.node.position.y + this.atk_y);
const originalTarget = v3(this.targetPos[0].x, this.targetPos[0].y + BoxSet.ATK_Y);
const direction = new Vec3();
Vec3.subtract(direction, originalTarget, originalStart);
const distance = direction.length();
direction.normalize();
const extendedTarget = new Vec3();
Vec3.scaleAndAdd(extendedTarget, originalTarget, direction, 720);
Object.assign(atkCom, {
// 核心标识
s_uuid: this.s_uuid,
// 位置和施法者信息
startPos: originalStart,
targetPos: extendedTarget,
group: this.group,
fac: this.fac,
// 技能数值
Attrs:this.Attrs
});
switch(this.runType){
case RType.linear:
this.do_linear(atkNode)
break
case RType.bezier:
this.do_bezier(atkNode)
break
case RType.fixed:
this.do_fixed(atkNode)
break
case RType.fixedEnd:
this.do_fixedEnd(atkNode)
break
}
}
}
do_linear(atkNode:any): void {
atkNode.getComponent(AtkConCom).do_line()
}
do_bezier(atkNode:any): void {
atkNode.getComponent(AtkConCom).do_parabolic()
}
do_fixed(atkNode:any): void {
atkNode.getComponent(AtkConCom).do_fixedStart()
}
do_fixedEnd(atkNode:any): void {
atkNode.getComponent(AtkConCom).do_fixedEnd()
}
move(dt: number): void {
// console.log(`${this.cName}_[SkillViewCom] move`)
if(this.caster != null&&this.caster.node!=null&&this.withHero) this.node.setPosition(this.caster.node.position.x,this.caster.node.position.y+this.ready_y)
// console.log(`${this.cName}_[skillview]move`,this.caster.node.position,this.node.position)
}
reset() {
this.node.destroy();
}
}

View File

@@ -1,9 +0,0 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "fa24efd6-db87-4a3a-957f-cde0cc3a4054",
"files": [],
"subMetas": {},
"userData": {}
}