You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
251 lines
9.9 KiB
251 lines
9.9 KiB
/**
|
|
* 泡泡持续攻击
|
|
*/
|
|
import { _decorator, Component, isValid, Node, random, sp, UITransform, Vec2, Vec3 } from 'cc';
|
|
import { BattleDataManager, IWeaponProperty } from '../BattleDataManager';
|
|
import { GEvent } from 'db://assets/mx/module/event/GEvent';
|
|
import { Skill } from './Skill';
|
|
const { ccclass, property } = _decorator;
|
|
|
|
@ccclass('BubbleSchedule')
|
|
export class BubbleSchedule extends Component {
|
|
_dt: number = 0;
|
|
_dtAll: number = 0; //累计时间
|
|
_weaponid: number = 0;
|
|
|
|
_weaponContinueTime: number = 0; //持续时间
|
|
isCanAtk: boolean = false; //是否可以攻击造成伤害
|
|
isStartGame: boolean = false; //是否开始游戏
|
|
_updatePosiTime: number = 0//0.05; //更新位置时间
|
|
_updatePosiInterval: number = 0.03; //更新位置间隔
|
|
_speed: number = 0; //速度
|
|
targetPosi: Vec2 = null; //目标位置
|
|
|
|
isCanAtkTime = 0
|
|
private _skillComp: any = null;
|
|
private _isDestroying: boolean = false;
|
|
protected onLoad(): void {
|
|
//console.log('手电筒激光武器持续攻击 onLoad')
|
|
this.isStartGame = false
|
|
this._skillComp = this.node.getComponent('Skill') as any;
|
|
|
|
}
|
|
start() {
|
|
//console.log('手电筒激光武器持续攻击 start')
|
|
//EVENT_UPDATE_BUBBLE
|
|
GEvent.Ins.on(GEvent.EVENT_UPDATE_BUBBLE, this.updateBubble, this)
|
|
|
|
}
|
|
updateBubble() {
|
|
//console.log('更新泡泡持续攻击时间和速度')
|
|
let weaponProperty = BattleDataManager.getWeaponAddProperty(this._weaponid)
|
|
if (this._speed !== weaponProperty.speed) {
|
|
this._speed = weaponProperty.speed
|
|
}
|
|
|
|
if (this._weaponContinueTime !== weaponProperty.weaponContinueTime) {
|
|
this._weaponContinueTime = weaponProperty.weaponContinueTime
|
|
}
|
|
|
|
|
|
}
|
|
|
|
update(deltaTime: number) {
|
|
const scaledDt = deltaTime * gg.game.CurentBattle.TimeScale;
|
|
if (!this.isCanAtk) {
|
|
this.isCanAtkTime += scaledDt
|
|
if (this.isCanAtkTime >= 0.05) {
|
|
this.isCanAtkTime = 0
|
|
this.isCanAtk = true
|
|
}
|
|
}
|
|
if (!this._skillComp) this._skillComp = this.node.getComponent('Skill') as any;
|
|
if (!this.isStartGame || !this.isCanAtk || this._skillComp.getIsDead()) {
|
|
//没有开始或者死亡
|
|
return
|
|
}
|
|
|
|
if (!gg.game.CurentBattle.canUpdateFrame()) return;
|
|
|
|
|
|
this._dtAll += scaledDt
|
|
this._dt += scaledDt
|
|
if (this._dtAll >= this._weaponContinueTime) {
|
|
this.isStartGame = false
|
|
this.destroyNode()
|
|
} else {
|
|
this._updatePosiTime += scaledDt
|
|
if (this._updatePosiTime >= this._updatePosiInterval) {
|
|
this._updatePosiTime = 0
|
|
//移到到目标位置, 到了targetPosi之后,更新下一个位置。(只有碰到怪物或者时间到了才会销毁)
|
|
//this._speed 移动this.targetPosi
|
|
|
|
// 检查是否已经有目标位置,如果没有则生成一个
|
|
if (!this.targetPosi || (this.targetPosi.x === 0 && this.targetPosi.y === 0)) {
|
|
this.targetPosi = this.getRundomPosi();
|
|
}
|
|
|
|
const currentPos = this.node.position;
|
|
const dx = this.targetPosi.x - currentPos.x;
|
|
const dy = this.targetPosi.y - currentPos.y;
|
|
|
|
// 增加目标点检测阈值,避免在小范围内频繁切换
|
|
const arrivalThreshold = Math.max(20, this._speed * this._updatePosiInterval * 2); // 动态阈值,与速度相关
|
|
const distSq = dx * dx + dy * dy;
|
|
const arrivalThresholdSq = arrivalThreshold * arrivalThreshold;
|
|
|
|
if (distSq < arrivalThresholdSq) { // 使用动态阈值
|
|
// 到达目标位置,生成新的随机目标位置(确保与当前位置有最小距离)
|
|
let newTarget = this.getRundomPosi();
|
|
const minDistance = Math.max(50, this._speed); // 最小距离不小于50,且与速度成正比
|
|
const minDistanceSq = minDistance * minDistance;
|
|
let dx2 = newTarget.x - currentPos.x;
|
|
let dy2 = newTarget.y - currentPos.y;
|
|
let newDistanceSq = dx2 * dx2 + dy2 * dy2;
|
|
|
|
let retryCount = 0;
|
|
while (newDistanceSq < minDistanceSq && retryCount < 10) {
|
|
newTarget = this.getRundomPosi();
|
|
dx2 = newTarget.x - currentPos.x;
|
|
dy2 = newTarget.y - currentPos.y;
|
|
newDistanceSq = dx2 * dx2 + dy2 * dy2;
|
|
retryCount++;
|
|
}
|
|
|
|
this.targetPosi = newTarget;
|
|
// 停留一秒
|
|
this.isCanAtkTime = 0
|
|
this.isCanAtk = false
|
|
|
|
|
|
} else {
|
|
const dist = Math.sqrt(distSq);
|
|
// 归一化后的方向向量
|
|
const dirX = dx / dist;
|
|
const dirY = dy / dist;
|
|
|
|
// 根据速度计算移动距离
|
|
const moveDistance = this._speed * this._updatePosiInterval;
|
|
|
|
// 计算新位置(避免超过目标点)
|
|
let newX = currentPos.x + dirX * moveDistance;
|
|
let newY = currentPos.y + dirY * moveDistance;
|
|
|
|
const targetX = this.targetPosi.x;
|
|
const targetY = this.targetPosi.y;
|
|
const ndx = targetX - newX;
|
|
const ndy = targetY - newY;
|
|
const newDistanceToTargetSq = ndx * ndx + ndy * ndy;
|
|
|
|
if (newDistanceToTargetSq < distSq) {
|
|
// 正常移动
|
|
this.node.setPosition(newX, newY, currentPos.z);
|
|
} else {
|
|
// 即将超过目标点,直接到达目标点
|
|
this.node.setPosition(this.targetPosi.x, this.targetPosi.y, currentPos.z);
|
|
|
|
// 立即生成新的目标点
|
|
let newTarget = this.getRundomPosi();
|
|
let dx2 = newTarget.x - this.targetPosi.x;
|
|
let dy2 = newTarget.y - this.targetPosi.y;
|
|
let newDistanceSq = dx2 * dx2 + dy2 * dy2;
|
|
|
|
const minDistance = Math.max(50, this._speed);
|
|
const minDistanceSq = minDistance * minDistance;
|
|
let retryCount = 0;
|
|
|
|
while (newDistanceSq < minDistanceSq && retryCount < 10) {
|
|
newTarget = this.getRundomPosi();
|
|
dx2 = newTarget.x - this.targetPosi.x;
|
|
dy2 = newTarget.y - this.targetPosi.y;
|
|
newDistanceSq = dx2 * dx2 + dy2 * dy2;
|
|
retryCount++;
|
|
}
|
|
|
|
this.targetPosi = newTarget;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
atkToMonster(weaponId: number, index: number, weaponProperty: IWeaponProperty) {
|
|
let playAnimStart = this.node.getChildByName('泡泡')
|
|
playAnimStart.getComponent(sp.Skeleton).setAnimation(0, '泡泡飞行', true)
|
|
this._weaponid = weaponId
|
|
this._speed = weaponProperty.speed
|
|
this._weaponContinueTime = weaponProperty.weaponContinueTime
|
|
this.targetPosi = this.getRundomPosi()
|
|
this._dtAll = 0
|
|
this._updatePosiTime = 0
|
|
this.isCanAtkTime = 0
|
|
this.isStartGame = true
|
|
this.isCanAtk = true
|
|
|
|
}
|
|
|
|
getRundomPosi() {
|
|
//从14*10的格子选取一个格子位置, 格子位置从(-237,-343)开始
|
|
//每一列14个,总共10列, y轴每个位置+53, x轴每个位置+51
|
|
//第一列第一个(-237,-343), (-237,-290),(-237,-238)以此类推
|
|
//第二列(-186,-343), (-186,-290),(-186,-238)以此类推
|
|
//划分的在细一点,100*140
|
|
let randY = Math.floor(random() * 120) // 0-10不包括10
|
|
let randX = Math.floor(random() * 140) // 0-14不包括14
|
|
//console.log('随机到的格子位置',randX,randY)
|
|
let y = -237 + randY * 7;
|
|
let x = -343 + randX * 5.5;
|
|
|
|
x = Math.random() * 700 - 350;
|
|
y = Math.random() * 400 - 200;
|
|
//console.log('随机到的格子位置',randX,randY, x,y)
|
|
let posi = new Vec2(x, y)
|
|
return posi
|
|
}
|
|
|
|
|
|
|
|
destroyNode() {
|
|
if (this._isDestroying) return;
|
|
this._isDestroying = true;
|
|
// 生成毒液区域:泡泡节点在 SkillController 下,需把世界坐标转为 Map 本地坐标
|
|
// (SkillBase.createBombComponent 是 setParent(Map.node) + setPosition(localPos))
|
|
const worldPos = this.node.worldPosition.clone();
|
|
const mapNode = gg.game.CurentBattle.Map.node;
|
|
const mapUi = mapNode.getComponent(UITransform);
|
|
const originPos = mapUi ? mapUi.convertToNodeSpaceAR(worldPos) : this.node.position.clone();
|
|
this.node.getComponent(Skill).playBubbleSanitizer(originPos)
|
|
|
|
this.node.getComponent(Skill).setIsDead(true)
|
|
// console.log('销毁泡泡武器')
|
|
//播放动效
|
|
let playAnimStart = this.node.getChildByName('泡泡')
|
|
const sk = playAnimStart?.getComponent(sp.Skeleton);
|
|
sk?.setAnimation(0, '泡泡炸裂', false)
|
|
this.scheduleOnce(() => {
|
|
//移除当前脚本
|
|
GEvent.Ins.off(GEvent.EVENT_UPDATE_BUBBLE, this.updateBubble, this)
|
|
this.removeSelf()
|
|
gg.res.putNode(this.node)
|
|
}, 0.4)
|
|
|
|
}
|
|
|
|
|
|
|
|
/**刷新激光武器ui */
|
|
removeSelf() {
|
|
this.destroy()
|
|
}
|
|
onDestroy() {
|
|
// 确保回收时不会残留事件订阅/定时回调
|
|
this.unscheduleAllCallbacks();
|
|
GEvent.Ins.off(GEvent.EVENT_UPDATE_BUBBLE, this.updateBubble, this);
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|