feat(skill): add movement acceleration support for skills

1. 新增SMoveComp的isAccelerate字段控制加速逻辑
2. 添加技能配置is_accel字段启用加速效果
3. 实现二次方缓入加速曲线,兼顾起步速度与最终加速度
4. 为6001号技能默认开启加速效果并调整其移动类型为直线运动
This commit is contained in:
pan
2026-06-23 11:07:57 +08:00
parent 72cdf32a75
commit 46fa481607
3 changed files with 27 additions and 9 deletions

View File

@@ -155,6 +155,7 @@ export interface SkillConfig {
bck?: number, // 额外击退概率 bck?: number, // 额外击退概率
buff_type?: Attrs, // Buff 类型 (单一职责) buff_type?: Attrs, // Buff 类型 (单一职责)
call_hero?: number, // 召唤技能召唤英雄id(可选) call_hero?: number, // 召唤技能召唤英雄id(可选)
is_accel?: boolean, // 是否逐渐加速飞行
info: string, // 技能描述 info: string, // 技能描述
} }
@@ -170,6 +171,7 @@ export interface SkillOverrides {
bck?: number; bck?: number;
buff_type?: Attrs; buff_type?: Attrs;
call_hero?: number; call_hero?: number;
is_accel?: boolean;
} }
/** /**
@@ -209,18 +211,18 @@ export const SkillSet: Record<number, SkillConfig> = {
**/ **/
6001: { 6001: {
uuid: 6001, name: "火球", sp_name: "atk_1", icon: "Stat_Attack_01", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "atk", uuid: 6001, name: "火球", sp_name: "atk_1", icon: "Stat_Attack_01", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "atk",
DTType: DTType.single, ap: 100, hit_count: 1, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.Melee, DTType: DTType.single, ap: 100, hit_count: 1, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.Melee,is_accel:true,
RType: RType.bezier, EType: EType.collision, info: "造成攻击力100%的伤害", RType: RType.linear, EType: EType.collision, info: "造成攻击力100%的伤害",
}, },
6002: { 6002: {
uuid: 6002, name: "紫烟", sp_name: "atk_2", icon: "Stat_Attack_01", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "atk", uuid: 6002, name: "紫烟", sp_name: "atk_2", icon: "Stat_Attack_01", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "atk",
DTType: DTType.single, ap: 100, hit_count: 1, hitcd: 0.3, speed: 720, with: 90, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.remote, DTType: DTType.single, ap: 100, hit_count: 1, hitcd: 0.3, speed: 720, with: 90, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.remote,
RType: RType.bezier, EType: EType.collision, info: "近战普通攻击技能", RType: RType.linear, EType: EType.collision, info: "近战普通攻击技能",
}, },
6003: { 6003: {
uuid: 6003, name: "白球", sp_name: "atk_3", icon: "Stat_Attack_01", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "atk", uuid: 6003, name: "白球", sp_name: "atk_3", icon: "Stat_Attack_01", TGroup: TGroup.Enemy, readyAnm: "", endAnm: "", act: "atk",
DTType: DTType.single, ap: 100, hit_count: 1, hitcd: 0.3, speed: 720, with: 90, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.remote, DTType: DTType.single, ap: 100, hit_count: 1, hitcd: 0.3, speed: 720, with: 90, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.remote,
RType: RType.bezier, EType: EType.collision, info: "一定几率暴击", RType: RType.linear, EType: EType.collision, info: "一定几率暴击",
}, },
6008: { 6008: {

View File

@@ -69,6 +69,9 @@ export class SMoveDataComp extends ecs.Comp {
bezierMidHeight: number = 200; bezierMidHeight: number = 200;
bezierArc: number = 1; bezierArc: number = 1;
/** 是否逐渐加速 (ease-in) */
isAccelerate: boolean = false;
/** 是否自动销毁(到达目标后) */ /** 是否自动销毁(到达目标后) */
autoDestroy: boolean = true; autoDestroy: boolean = true;
@@ -80,6 +83,7 @@ export class SMoveDataComp extends ecs.Comp {
this.bezierStartHeight = 30; this.bezierStartHeight = 30;
this.bezierMidHeight = 200; this.bezierMidHeight = 200;
this.bezierArc = 1; this.bezierArc = 1;
this.isAccelerate = false;
this.speed = 500; this.speed = 500;
this.progress = 0; this.progress = 0;
this.scale = 1; this.scale = 1;
@@ -181,14 +185,20 @@ export class SMoveDataComp extends ecs.Comp {
* 根据移动类型计算当前位置 * 根据移动类型计算当前位置
*/ */
private calculateCurrentPosition() { private calculateCurrentPosition() {
// 如果开启了逐渐加速,混合线性与二次方曲线 (如 0.7 * t^2 + 0.3 * t)
// 这样起步拥有 30% 的基础速度,不会显得完全静止,随后逐渐加速
const t = this.isAccelerate ?
(this.progress * this.progress * 0.7 + this.progress * 0.3) :
this.progress;
switch (this.runType) { switch (this.runType) {
case RType.linear: case RType.linear:
// 直线运动 // 直线运动
Vec3.lerp(this.currentPos, this.startPos, this.targetPos, this.progress); Vec3.lerp(this.currentPos, this.startPos, this.targetPos, t);
break; break;
case RType.bezier: case RType.bezier:
this.calculateBezierPosition(this.progress); this.calculateBezierPosition(t);
break; break;
case RType.fixed: case RType.fixed:
@@ -198,7 +208,7 @@ export class SMoveDataComp extends ecs.Comp {
break; break;
default: default:
Vec3.lerp(this.currentPos, this.startPos, this.targetPos, this.progress); Vec3.lerp(this.currentPos, this.startPos, this.targetPos, t);
break; break;
} }
} }

View File

@@ -40,10 +40,13 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
return; return;
} }
// 根据配置设置移动速度 // 根据配置设置移动速度与加速度
if (skillConfig.speed > 0) { if (skillConfig.speed > 0) {
moveComp.speed = skillConfig.speed; moveComp.speed = skillConfig.speed;
} }
if (skillConfig.is_accel) {
moveComp.isAccelerate = true;
}
// 根据runType设置初始位置 // 根据runType设置初始位置
this.initializePosition(moveComp, skillView); this.initializePosition(moveComp, skillView);
@@ -190,10 +193,12 @@ export class SMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
if (moveComp.progress < 1) { if (moveComp.progress < 1) {
// 计算下一帧的位置来确定方向 // 计算下一帧的位置来确定方向
const nextProgress = Math.min(moveComp.progress + 0.01, 1); const nextProgress = Math.min(moveComp.progress + 0.01, 1);
const t = moveComp.isAccelerate ?
(nextProgress * nextProgress * 0.7 + nextProgress * 0.3) :
nextProgress;
const nextPos = v3(0, 0, 0); const nextPos = v3(0, 0, 0);
// 计算下一个位置 // 计算下一个位置
const t = nextProgress;
const oneMinusT = 1 - t; const oneMinusT = 1 - t;
const oneMinusTSquared = oneMinusT * oneMinusT; const oneMinusTSquared = oneMinusT * oneMinusT;
const tSquared = t * t; const tSquared = t * t;
@@ -245,6 +250,7 @@ export class SMoveHelper {
if (skillConfig) { if (skillConfig) {
moveComp.runType = skillConfig.RType || RType.linear; moveComp.runType = skillConfig.RType || RType.linear;
moveComp.speed = skillConfig.speed || 500; moveComp.speed = skillConfig.speed || 500;
if (skillConfig.is_accel) moveComp.isAccelerate = true;
} }
} }