From 8b801b8df0cc5d767f334c6764e5d834dfee03fd Mon Sep 17 00:00:00 2001 From: wvellichor Date: Sun, 18 Jan 2026 02:22:38 +0800 Subject: [PATCH] =?UTF-8?q?feat(skill)=20=E6=B7=BB=E5=8A=A0=E5=82=80?= =?UTF-8?q?=E5=84=A13=E6=8A=80=E8=83=BD=E5=8F=8A=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E8=81=94=E5=8A=A8=E6=95=88=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- objects/Unit.js | 6 + scenes/testScenes/AttackSkillTestScene.js | 282 +++++++++++++++++++--- 2 files changed, 250 insertions(+), 38 deletions(-) diff --git a/objects/Unit.js b/objects/Unit.js index e97000d..6f9c0ba 100644 --- a/objects/Unit.js +++ b/objects/Unit.js @@ -159,6 +159,12 @@ export default class Unit extends Phaser.Physics.Arcade.Sprite { * @param {number} y - 垂直方向 (-1 到 1) */ moveRelative(x, y) { + // 检查是否可以移动 + if (this.canMove === false) { + this.setVelocity(0, 0); + return; + } + const speed = 150; // 单位:像素/秒 // 归一化方向向量 const magnitude = Math.sqrt(x * x + y * y); diff --git a/scenes/testScenes/AttackSkillTestScene.js b/scenes/testScenes/AttackSkillTestScene.js index d90c396..19c17a6 100644 --- a/scenes/testScenes/AttackSkillTestScene.js +++ b/scenes/testScenes/AttackSkillTestScene.js @@ -596,53 +596,108 @@ export default class AttackSkillTestScene extends Phaser.Scene { break; case 2: // 技能2:本体拉近并交换位置 if (this.puppet) { - // 记录傀儡当前位置 - const puppetX = this.puppet.x; - const puppetY = this.puppet.y; + // 检查是否处于3技能第二次按下后的控制期间 + const isInSkill3Control = this.puppetSkill3State && this.puppetSkill3State.hasSecondCast; - // 计算本体与傀儡之间的距离 - const dx = yuange.x - puppetX; - const dy = yuange.y - puppetY; - const distance = Math.sqrt(dx * dx + dy * dy); - - // 固定拉近距离阈值 - const fixedDistance = 200; - - if (distance <= fixedDistance) { - // 如果距离小于等于阈值,直接交换位置 - // 记录本体当前位置 - const yuangeX = yuange.x; - const yuangeY = yuange.y; + if (isInSkill3Control) { + // 处于3技能控制期间:只执行本体拉近,不执行位置互换,然后切换到本体控制 + const puppetX = this.puppet.x; + const puppetY = this.puppet.y; - // 傀儡移动到本体位置 - this.puppet.setPosition(yuangeX, yuangeY); - this.puppet.setVelocity(0, 0); - this.puppet.clearTarget(); + // 计算本体与傀儡之间的距离 + const dx = yuange.x - puppetX; + const dy = yuange.y - puppetY; - // 本体移动到傀儡原本位置 - yuange.setPosition(puppetX, puppetY); - yuange.setVelocity(0, 0); - } else { - // 如果距离大于阈值,执行拉近逻辑 // 计算归一化方向向量 - const normalizedX = dx / distance; - const normalizedY = dy / distance; + const distance = Math.sqrt(dx * dx + dy * dy); + let normalizedX = 0; + let normalizedY = 0; + if (distance > 0) { + normalizedX = dx / distance; + normalizedY = dy / distance; + } // 计算拉近后的位置(在本体到傀儡的直线上,距离傀儡fixedDistance的位置) + const fixedDistance = 200; const closeX = puppetX + normalizedX * fixedDistance; const closeY = puppetY + normalizedY * fixedDistance; - // 傀儡移动到拉近后的位置 - this.puppet.setPosition(closeX, closeY); - this.puppet.setVelocity(0, 0); - this.puppet.clearTarget(); - - // 直接设置本体位置到傀儡原本位置 - yuange.setPosition(puppetX, puppetY); + // 本体移动到拉近后的位置 + yuange.setPosition(closeX, closeY); yuange.setVelocity(0, 0); + + // 切换到本体控制(保持傀儡存在) + this.switchToYuange(false); + } else { + // 正常情况:执行完整的拉近和交换位置逻辑 + // 记录傀儡当前位置 + const puppetX = this.puppet.x; + const puppetY = this.puppet.y; + + // 计算本体与傀儡之间的距离 + const dx = yuange.x - puppetX; + const dy = yuange.y - puppetY; + const distance = Math.sqrt(dx * dx + dy * dy); + + // 固定拉近距离阈值 + const fixedDistance = 200; + + if (distance <= fixedDistance) { + // 如果距离小于等于阈值,直接交换位置 + // 记录本体当前位置 + const yuangeX = yuange.x; + const yuangeY = yuange.y; + + // 傀儡移动到本体位置 + this.puppet.setPosition(yuangeX, yuangeY); + this.puppet.setVelocity(0, 0); + this.puppet.clearTarget(); + + // 本体移动到傀儡原本位置 + yuange.setPosition(puppetX, puppetY); + yuange.setVelocity(0, 0); + } else { + // 如果距离大于阈值,执行拉近逻辑 + // 计算归一化方向向量 + const normalizedX = dx / distance; + const normalizedY = dy / distance; + + // 计算拉近后的位置(在本体到傀儡的直线上,距离傀儡fixedDistance的位置) + const closeX = puppetX + normalizedX * fixedDistance; + const closeY = puppetY + normalizedY * fixedDistance; + + // 傀儡移动到拉近后的位置 + this.puppet.setPosition(closeX, closeY); + this.puppet.setVelocity(0, 0); + this.puppet.clearTarget(); + + // 直接设置本体位置到傀儡原本位置 + yuange.setPosition(puppetX, puppetY); + yuange.setVelocity(0, 0); + } } } break; + case 3: // 技能3:控制特效 + // 检查是否已经初始化技能3的状态 + if (!this.puppetSkill3State) { + this.puppetSkill3State = { + hasFirstCast: false, + hasSecondCast: false, + firstCastTime: 0, + secondCastTime: 0 + }; + } + + if (!this.puppetSkill3State.hasFirstCast) { + // 第一次按下:减速周围敌人 + this.castPuppetSkill3First(); + } else if (!this.puppetSkill3State.hasSecondCast && + (Date.now() - this.puppetSkill3State.firstCastTime) < 5000) { // 5秒内第二次按下 + // 第二次按下:眩晕周围敌人,傀儡不可移动,一段时间后销毁 + this.castPuppetSkill3Second(); + } + break; case 4: // 技能4:傀儡快速移动并拉本体 if (this.puppet && this.isControllingPuppet) { // 使用轮盘相对方向计算目标位置 @@ -698,8 +753,12 @@ export default class AttackSkillTestScene extends Phaser.Scene { } else { // 控制本体时的技能 switch (skillIndex) { - case 1: // 技能1:扔出傀儡 - if (!this.puppet) { + case 1: // 技能1:扔出傀儡或收回傀儡 + if (this.puppet) { + // 有傀儡存在:立即收回并销毁傀儡 + this.switchToYuange(); + } else { + // 没有傀儡:创建新傀儡 // 使用轮盘相对方向计算目标位置 const maxDistance = 200; const distance = Math.sqrt(directionX * directionX + directionY * directionY); @@ -896,6 +955,129 @@ export default class AttackSkillTestScene extends Phaser.Scene { this.currentlyControlled.setVelocity(0, 0); } + /** + * 傀儡技能3第一次释放:减速周围敌人 + */ + castPuppetSkill3First() { + if (!this.puppet) return; + + const puppetX = this.puppet.x; + const puppetY = this.puppet.y; + const slowRadius = 150; + + // 记录第一次释放的时间 + this.puppetSkill3State.hasFirstCast = true; + this.puppetSkill3State.firstCastTime = Date.now(); + + // 创建减速特效(蓝色圆形) + const slowEffect = this.add.graphics(); + slowEffect.setScrollFactor(1); + slowEffect.setDepth(50); + + // 绘制减速范围 + slowEffect.lineStyle(2, 0x0000ff, 0.8); + slowEffect.beginPath(); + slowEffect.arc(puppetX, puppetY, slowRadius, 0, Math.PI * 2); + slowEffect.strokePath(); + + // 添加脉冲动画 + this.tweens.add({ + targets: slowEffect, + alpha: 0, + // 移除scale动画,避免特效移动 + // scale: 1.5, + duration: 1000, + ease: 'Power1', + onComplete: () => { + slowEffect.destroy(); + } + }); + + // 这里可以添加实际的敌人减速逻辑 + console.log('傀儡技能3第一次释放:减速周围敌人'); + } + + /** + * 傀儡技能3第二次释放:眩晕周围敌人 + */ + castPuppetSkill3Second() { + if (!this.puppet) return; + + const puppetX = this.puppet.x; + const puppetY = this.puppet.y; + const stunRadius = 150; + + // 记录第二次释放的时间 + this.puppetSkill3State.hasSecondCast = true; + this.puppetSkill3State.secondCastTime = Date.now(); + + // 创建眩晕特效(紫色圆形) + this.stunEffect = this.add.graphics(); + this.stunEffect.setScrollFactor(1); + this.stunEffect.setDepth(50); + + // 绘制眩晕范围 + this.stunEffect.lineStyle(2, 0xff00ff, 0.8); + this.stunEffect.beginPath(); + this.stunEffect.arc(puppetX, puppetY, stunRadius, 0, Math.PI * 2); + this.stunEffect.strokePath(); + + // 第二次释放后:傀儡不可移动 + this.puppet.canMove = false; + // 额外设置速度为0,确保傀儡不会移动 + this.puppet.setVelocity(0, 0); + this.puppet.clearTarget(); + + // 一段时间后自动销毁傀儡,切换到本体控制 + this.time.delayedCall(3000, () => { + if (this.puppet) { + // 销毁眩晕特效 + if (this.stunEffect) { + this.stunEffect.destroy(); + this.stunEffect = null; + } + + // 销毁傀儡 + this.puppet.destroy(); + this.puppet = null; + + // 切换到本体控制 + this.isControllingPuppet = false; + const yuange = this.characters.find(char => char.name === 'yuange'); + if (yuange) { + this.currentlyControlled = yuange; + yuange.setSelected(true); + + // 更新UI提示 + this.controlInfoText.setText('当前控制: 元歌'); + + // 更新技能轮盘显示为元歌本体的技能 + this.updateSkillWheelDisplay(); + + // 更新选择系统并锁定相机到本体 + import('../../systems/ControlMode.js').then(mod => { + mod.clearSelection(); + mod.addToSelection(yuange); + mod.setActiveUnit(yuange); + // 自动锁定相机到本体 + mod.setCameraLocked(true); + }); + } + + // 重置技能3状态 + this.puppetSkill3State = { + hasFirstCast: false, + hasSecondCast: false, + firstCastTime: 0, + secondCastTime: 0 + }; + } + }); + + // 这里可以添加实际的敌人眩晕逻辑 + console.log('傀儡技能3第二次释放:眩晕周围敌人'); + } + /** * 创建十字斩视觉效果 */ @@ -1068,6 +1250,15 @@ export default class AttackSkillTestScene extends Phaser.Scene { this.skillPreview.strokeCircle(targetX, targetY, 15); this.skillPreview.fillStyle(0xffff00, 0.2); this.skillPreview.fillCircle(targetX, targetY, 15); + } else if (this.skillWheel.activeSkill === 3 && this.isControllingPuppet) { + // 傀儡技能3预览:控制特效范围 + const effectRadius = 150; + + // 绘制技能范围 + this.skillPreview.lineStyle(2, 0xffff00, 0.5); + this.skillPreview.beginPath(); + this.skillPreview.arc(this.currentlyControlled.x, this.currentlyControlled.y, effectRadius, 0, Math.PI * 2); + this.skillPreview.strokePath(); } else if (this.skillWheel.activeSkill === 2 && !this.isControllingPuppet) { // 二技能:扇形飞镖攻击预览 // 扇形角度范围:45度(转换为弧度) @@ -1237,12 +1428,27 @@ export default class AttackSkillTestScene extends Phaser.Scene { /** * 切换回元歌本体 + * @param {boolean} destroyPuppet - 是否销毁傀儡,默认为true */ - switchToYuange() { - if (this.puppet) { + switchToYuange(destroyPuppet = true) { + if (destroyPuppet && this.puppet) { // 删除傀儡 this.puppet.destroy(); this.puppet = null; + + // 销毁控制特效 + if (this.stunEffect) { + this.stunEffect.destroy(); + this.stunEffect = null; + } + + // 重置技能3状态 + this.puppetSkill3State = { + hasFirstCast: false, + hasSecondCast: false, + firstCastTime: 0, + secondCastTime: 0 + }; } // 切换回元歌本体控制