消消方块阵换皮表情
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

/**
* 泡泡持续攻击
*/
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);
}
}