using System; namespace Ichni.RhythmGame { public abstract class EffectBase : IBaseElement { #region [枚举定义] Enums public enum EffectState { Before = -1, Middle = 0, After = 1, Error = 100 } #endregion #region [核心属性] Properties public Beatmap.BaseElement_BM matchedBM { get; set; } public GameElement attachedGameElement; /// /// 效果的持续时间,如果为0则表示瞬间效果 /// public float effectTime; /// /// 是否是瞬间效果 /// public bool isInstantEffect => effectTime <= 0; /// /// 效果的进度百分比 /// public float effectProgressPercent; /// /// 效果当前的状态 /// public EffectState nowEffectState; #endregion #region [初始化] Initialization protected EffectBase() { this.effectTime = 0; this.nowEffectState = EffectState.Before; this.effectProgressPercent = 0; } protected EffectBase(float effectTime) { this.effectTime = effectTime; this.nowEffectState = EffectState.Before; this.effectProgressPercent = 0; } #endregion #region [基础逻辑] Main Update Logic public virtual void UpdateEffect(float judgeTime) { EffectState state = CheckEffectState(judgeTime); float songTime = CoreServices.TimeProvider.SongTime; if (state == EffectState.Before && nowEffectState != EffectState.Before) { nowEffectState = EffectState.Before; effectProgressPercent = 0; Recover(); } else if (state == EffectState.Middle) { if (nowEffectState == EffectState.Before) { PreExecute(); } nowEffectState = EffectState.Middle; effectProgressPercent = (songTime - judgeTime) / effectTime; Execute(); } else if (state == EffectState.After && nowEffectState != EffectState.After) { nowEffectState = EffectState.After; effectProgressPercent = 1; Adjust(); } } protected virtual EffectState CheckEffectState(float triggerTime) { float songTime = CoreServices.TimeProvider.SongTime; if (songTime < triggerTime) { return EffectState.Before; } if (songTime >= triggerTime && songTime <= triggerTime + effectTime) { return EffectState.Middle; } if (songTime > triggerTime + effectTime) { return EffectState.After; } return EffectState.Error; } #endregion #region [效果重写] Effect Overrides /// /// 当从Before状态进入Middle状态时,仅在效果的开始时触发一次方法 /// public virtual void PreExecute() { } /// /// 在效果的持续时间内,触发这个方法 /// public virtual void Execute() { } /// /// 如果是非瞬间效果,在效果完成后,触发这个方法; /// 如果是瞬间效果,则此方法即为Execute。原有的Execute方法不被调用。 /// public virtual void Adjust() { } /// /// 如果时间轴回退到效果的触发时间之前,则触发这个方法 /// public virtual void Recover() { } /// /// 如果效果被打断,则触发这个方法 /// public virtual void Disrupt() { } public void Refresh() { } #endregion } }