using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using FDK.メディア; namespace SST.ステージ.演奏 { class コンボ : FDK.Activity { public FDK.同期.RWLock COMBO値 { get; } public コンボ() { this.スレッド間同期 = new ReaderWriterLockSlim( LockRecursionPolicy.SupportsRecursion ); this.COMBO値 = new FDK.同期.RWLock( this.スレッド間同期, 0 ); this.子リスト.Add( this._単位付き数値 = new コンボジャンプ() ); } protected override void On活性化( デバイスリソース dr ) { this._現在のモード = EMode.非表示中; this.COMBO値.Value = 0; this._前回のCOMBO値 = 0; this._コンボが切れたときのCOMBO値 = 0; this._コンボが切れた時刻 = FDK.カウンタ.QPCTimer.未使用; } protected override void On非活性化( デバイスリソース dr ) { } public void 進行描画する( デバイスリソース dr ) { int COMBO値 = this.COMBO値.Value; // 進行。 EEvent 今回の状態遷移イベント; #region " 前回と今回の COMBO 値から、今回の状態遷移イベントを決定する。" //----------------- int 前回の値 = this._前回のCOMBO値; int 今回の値 = COMBO値; if( 今回の値 < _表示可能な最小コンボ数 ) { 今回の状態遷移イベント = EEvent.非表示; } else if( 前回の値 == 今回の値 ) { 今回の状態遷移イベント = EEvent.同一数値; } else if( 前回の値 < 今回の値 ) { 今回の状態遷移イベント = EEvent.数値更新; } else { 今回の状態遷移イベント = EEvent.ミス; } //----------------- #endregion this._前回のCOMBO値 = COMBO値; Retry: // モードが変化した場合はここからリトライする。(次のターンに回すと、間にPresentを挟んで表示がチラつくから。) switch( this._現在のモード ) { case EMode.非表示中: #region " 数値が更新されたら 進行表示中モードへ。" //----------------- if( 今回の状態遷移イベント == EEvent.数値更新 ) { this._現在のモード = EMode.表示中; goto Retry; } this._単位付き数値.表示する.Value = false; //----------------- #endregion break; case EMode.表示中: #region " 遷移イベントが非表示・ミスのときは 残像表示中 モードへ。" //----------------- if( ( 今回の状態遷移イベント == EEvent.非表示 ) || ( 今回の状態遷移イベント == EEvent.ミス ) ) { this._現在のモード = EMode.残像表示中; this._コンボが切れたときのCOMBO値 = 前回の値; this._コンボが切れた時刻 = FDK.カウンタ.QPCTimer.生カウント; goto Retry; } this._単位付き数値.数値.Value = 今回の値; this._単位付き数値.表示する.Value = true; //----------------- #endregion break; case EMode.残像表示中: #region " 数値が更新された場合は 進行表示中 モードへ、残像表示時間が切れたときは 非表示 モードへ。" //----------------- if( 今回の状態遷移イベント == EEvent.数値更新 ) { this._現在のモード = EMode.表示中; goto Retry; } else if( FDK.カウンタ.QPCTimer.生カウント相対値を秒へ変換して返す( FDK.カウンタ.QPCTimer.生カウント - this._コンボが切れた時刻 ) > 1.0 ) // 1.0秒経った { this._現在のモード = EMode.非表示中; goto Retry; } this._単位付き数値.数値.Value = this._コンボが切れたときのCOMBO値; this._単位付き数値.表示する.Value = true; //----------------- #endregion break; } // 描画。 float 中央Xdpx = 1920f / 2f; //switch( Global.Users.Config.ComboPosition ) → コンボのX位置の調整はあとまわし。 //{ // case Eコンボ表示位置.LEFT: n中央X = 300; break; // case Eコンボ表示位置.CENTER: n中央X = 440; break; // case Eコンボ表示位置.RIGHT: n中央X = 680; break; //} float 下辺Ydpx = 130f; // Y座標は固定位置 this._単位付き数値.進行描画する( dr, 中央Xdpx, 下辺Ydpx, _ドラムコンボの文字間隔 ); } protected enum EEvent { 非表示, 数値更新, 同一数値, ミス } protected enum EMode { 非表示中, 表示中, 残像表示中 } private const float _ドラムコンボの文字間隔 = 2f; private const int _表示可能な最小コンボ数 = 11; private EMode _現在のモード; private int _前回のCOMBO値 = 0; private long _コンボが切れた時刻 = FDK.カウンタ.QPCTimer.未使用; private int _コンボが切れたときのCOMBO値 = 0; private コンボジャンプ _単位付き数値 = null; private ReaderWriterLockSlim スレッド間同期 = null; } }