Files
heros/assets/script/game/skills/SkillCom.ts
2025-06-20 10:26:28 +08:00

279 lines
11 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { _decorator,Collider2D ,Contact2DType,v3,IPhysics2DContact,Vec3, tween, math, RigidBody2D, Animation, sp} 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 { smc } from "../common/SingletonModuleComp";
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
import { GameEvent } from "../common/config/GameEvent";
import { AnimType, endType, RunType, SkillSet } from "../common/config/SkillSet";
import { BoxSet } from "../common/config/BoxSet";
import { HeroFac, HeroSet } from "../common/config/heroSet";
import { HeroViewComp } from "../hero/HeroViewComp";
import { BezierMove } from "../BezierMove/BezierMove";
import { FightConComp } from "../map/FightConComp";
import { MonModelComp } from "../hero/MonModelComp";
const { ccclass, property } = _decorator;
/** 视图层对象 */
@ccclass('SkillCom')
@ecs.register('SkillCom')
export class SkillCom extends CCComp {
s_uuid:number = 0;
s_name:string = "";
hero:number = 0;
speed:number = 200;
scale:number = 1;
angle:number = 0;
atk_count:number = 0;
is_destroy:boolean = false;
enemys:any = [];
animType: number = 0; // 运动类型
startPos: Vec3 = v3(); // 起始位置
targetPos: Vec3 = v3(); // 目标位置
duration: number = 0; // 技能持续时间
prefabName: string = ""; // 预制体名称
animName: string = "";
group:number = 0; //阵营
fac:number=0; //阵营
caster:any=null;
distance_x:number=0;
distance_y:number=0;
ap:number=0;
FIGHTCON:FightConComp=null;
private moveDirection: Vec3 | null = null; // 添加一个属性来存储移动方向
protected onLoad(): void {
this.FIGHTCON=this.node.parent.getComponent(FightConComp)
}
start() {
oops.message.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);
}
// console.log(this.group +"技能 collider ",collider);
switch(SkillSet[this.s_uuid].AnimType){
case AnimType.parabolic:
this.node.angle +=10
let bm=this.node.getComponent(BezierMove)
// bm.speed=700
if(this.group==BoxSet.MONSTER) bm.controlPointSide=-1
if(SkillSet[this.s_uuid].RunType==RunType.linear) bm.controlPointOffset=0
bm.moveTo(this.targetPos)
break;
case AnimType.linear:
let tx =400
if(this.group==BoxSet.MONSTER){
tx=-400
this.node.scale=v3(this.node.scale.x*-1,1,1)
}
tween(this.node).to(1, { position:v3(tx,this.node.position.y,0)},{
onComplete: (target?: object) => {
this.node.setPosition(tx,this.node.position.y-300,0)
}
}).start()
break;
case AnimType.fixedStart:
break;
case AnimType.fixedEnd:
this.node.setPosition(this.targetPos.x,this.targetPos.y,0)
if(this.node.getComponent(Animation)){
let anim = this.node.getComponent(Animation);
console.log("has anim",anim)
anim.on(Animation.EventType.FINISHED, this.onAnimationFinished, this);
}
if(this.node.getChildByName('anm')){
if(this.node.getChildByName('anm').getComponent('sp.Skeleton')){
var spine = this.node.getChildByName('anm').getComponent('sp.Skeleton') as sp.Skeleton;
console.log("has spine",spine)
spine.setCompleteListener((trackEntry) => {
this.onAnimationFinished()
console.log("[track %s][animation %s] complete: %s", trackEntry.trackIndex);
});
}
}
break;
}
// let dir_x = this.targetPos.x > this.node.position.x ? 1 : -1
// this.node.scale = v3(dir_x,1,1)
// 根据目标位置设置节点朝向
// if ( this.targetPos) {
// // 计算朝向
// let direction = this.targetPos.x > this.node.position.x ? 1 : -1;
// // 设置节点缩放来改变朝向
// this.node.scale = v3(direction * Math.abs(this.scale), this.scale, 1);
// }
// let dir_y = ( this.targetPos.y+BoxSet.ATK_Y) > this.node.position.y ? 1 : -1
// if( this.targetPos.y+BoxSet.ATK_Y==this.node.position.y){
// dir_y=0
// }
// // 计算这一帧的移动距离
// this.distance_x = SkillSet[this.s_uuid].speed*dir_x;
// this.distance_y = this.distance_x*Math.abs(this.targetPos.y-this.node.position.y)/Math.abs(this.targetPos.x-this.node.position.x)*dir_y;
// this.startMovement();
// // 计算目标角度
// if (this.targetPos) {
// const currentPos = this.node.position;
// // 计算角度(弧度)
// const dx = this.targetPos.x - currentPos.x;
// const dy = (this.targetPos.y + BoxSet.ATK_Y) - currentPos.y;
// const angle = Math.atan2(dy, dx);
// // 将弧度转换为角度并设置节点旋转
// this.angle = angle * 180 / Math.PI;
// this.node.angle = this.angle; // 移除负号,修正角度方向
// }
// // 计算速度分量
// const radians = this.angle * Math.PI / 180; // 移除负号,使用正确的角度
// this.distance_x = this.speed * Math.cos(radians);
// this.distance_y = this.speed * Math.sin(radians);
// this.startMovement();
// console.log("skill start",this.node.parent)
}
onAnimationFinished(){
let remainingDamage = this.ap;
remainingDamage=remainingDamage*(100-this.FIGHTCON.enemy_buff.DEF+this.FIGHTCON.enemy_debuff.BURN)/100
let enemys=ecs.query(ecs.allOf(MonModelComp))
console.log("onAnimationFinished",enemys)
enemys.forEach(entity => {
let view=entity.get(HeroViewComp)
if(view){
view.do_atked(remainingDamage)
}
});
this.is_destroy=true
}
onBeginContact (seCol: Collider2D, oCol: Collider2D) {
// console.log(this.scale+"碰撞开始 ",seCol,oCol);
let target = oCol.getComponent(HeroViewComp)
let caster = seCol.getComponent(HeroViewComp)
if(oCol.group!=this.group){
if(target == null) return;
let remainingDamage = this.ap;
if(target.fac == BoxSet.HERO ){
remainingDamage=remainingDamage*(100-this.FIGHTCON.hero_buff.DEF+this.FIGHTCON.hero_debuff.BURN)/100
}
if(target.fac == BoxSet.MONSTER){
remainingDamage=remainingDamage*(100-this.FIGHTCON.enemy_buff.DEF+this.FIGHTCON.enemy_debuff.BURN)/100
}
target.do_atked(remainingDamage)
this.ent.destroy()
}
}
private startLinearMove(dt: number) {
if (!this.speed || this.is_destroy) return;
// 使用角度方向移动
const newX = this.node.position.x + this.distance_x * dt;
const newY = this.node.position.y + this.distance_y * dt;
this.node.setPosition(newX, newY, this.node.position.z);
// 检查是否超出边界
if (newX < -400 || newX > 400) {
this.is_destroy = true;
}
}
private startBezierMove() {
// let s_pos = v3(this.startPos.x,this.startPos.y)
// let c_pos = v3((this.targetPos.x+this.startPos.x)/2,this.startPos.y+150)
// let e_pos = v3(this.targetPos.x,this.targetPos.y)
// let time =Math.abs(Math.abs(this.targetPos.x-this.startPos.x)/this.speed)
// // console.log("开始贝塞尔运动=>time:"+time,"s_pos:"+s_pos,"c_pos:"+c_pos,"e_pos:"+e_pos)
// SkillCom.bezierTo(this.node,time,s_pos,c_pos,e_pos,{
// onComplete: (target?: object) => {
// this.is_destroy=true
// },
// }).start();
}
public static bezierTo(target: any, duration: number, c1: Vec3, c2: Vec3, to: Vec3, opts: any) {
opts = opts || Object.create(null);
/*
* @desc 二阶贝塞尔
* @param {number} t 当前百分比
* @param {} p1 起点坐标
* @param {} cp 控制点
* @param {} p2 终点坐标
* @returns {any}
*/
let twoBezier = (t:number, p1: Vec3, cp: Vec3, p2: Vec3) => {
let x = (1 - t) * (1 - t) * p1.x + 2 * t * (1 - t) * cp.x + t * t * p2.x;
let y = (1 - t) * (1 - t) * p1.y + 2 * t * (1 - t) * cp.y + t * t * p2.y;
return v3(x, y, 0);
};
opts.onUpdate = (arg: Vec3, ratio: number) => {
target.position = twoBezier(ratio, c1, c2, to);
};
return tween(target).to(duration, {}, opts);
}
to_console(value:any,value2:any=null,value3:any=null){
console.log("["+this.s_name+this.s_uuid+"]:",value,value2,value3)
}
update(deltaTime: number) {
if(smc.mission.pause) return;
if (!this.node || !this.node.isValid) return;
if(this.animType == AnimType.linear) this.startLinearMove(deltaTime);
this.toDestroy();
}
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("doDestroy")
this.is_destroy=true
}
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
reset() {
this.is_destroy = false;
this.animType = 0;
this.speed = 0;
this.startPos.set();
this.targetPos.set();
this.moveDirection = null; // 重置移动方向
// 先移除所有碰撞回调
const collider = this.getComponent(Collider2D);
if (collider) {
collider.off(Contact2DType.BEGIN_CONTACT);
}
this.scheduleOnce(() => {
this.node.destroy();
}, 0);
}
}