using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using SharpDX; using FDK; using FDK.メディア; using FDK.カウンタ; using SSTFormat.v3; namespace SST.ステージ.演奏 { class ヒットランク : Activity { public ヒットランク() { // すべてのヒットランク画像を子リストに追加。 foreach( var kvp in this._ヒットランク画像 ) this.子リスト.Add( kvp.Value ); } public void 表示開始( 表示レーン種別 laneType, ヒットランク種別 hitRankType ) { if( laneType == 表示レーン種別.Unknown ) return; // レーンに対応する進行描画コンテキストを更新し、表示を開始するためのパラメータを設定する。 if( this._表示レーンto進行描画コンテキスト.ContainsKey( laneType ) ) // すでにあったら、 this._表示レーンto進行描画コンテキスト.Remove( laneType ); // 削除してから、 this._表示レーンto進行描画コンテキスト.Add( // 追加。 laneType, new 進行描画コンテキスト() { ヒットランク種別 = hitRankType, 進行カウンタ = new FDK.カウンタ.Counter( 最初の値: 0, 最後の値: 300, 値をひとつ増加させるのにかける時間ms: 1 ), // カウント開始(=表示開始) X方向拡大率 = 1f, Y方向拡大率 = 1f, 相対X座標 = 0, 相対Y座標 = 0, 透明度0to1 = 1f, } ); } public void 表示開始( チップ種別 chipType, ヒットランク種別 hitRankType ) { var laneType = App.ユーザ管理.選択されているユーザ.オプション設定.ドラムとチップと入力の対応表[ chipType ].表示レーン種別; if( laneType != 表示レーン種別.Unknown ) this.表示開始( laneType, hitRankType ); } protected override void On活性化( グラフィックデバイス gd ) { // すべての表示レーンについて、進行描画コンテキストを生成する。 this._表示レーンto進行描画コンテキスト = new Dictionary<表示レーン種別, 進行描画コンテキスト>(); foreach( 表示レーン種別 laneType in Enum.GetValues(typeof( 表示レーン種別 ) ) ) this._表示レーンto進行描画コンテキスト.Add( laneType, new 進行描画コンテキスト() ); } protected override void On非活性化( グラフィックデバイス gd ) { this._表示レーンto進行描画コンテキスト.Clear(); } public void 進行描画する( グラフィックデバイス gd, float レーンフレームの左端 ) { #region " 進行 " //---------------- foreach( 表示レーン種別 lane in Enum.GetValues( typeof( 表示レーン種別 ) ) ) { var context = this._表示レーンto進行描画コンテキスト[ lane ]; if( context.進行カウンタ.停止中である ) continue; // カウンタが停止中 → このレーンについては何もしない。 if( context.進行カウンタ.終了値に達した ) { #region " 進行カウンタが終了値に達したら停止 → 表示完了。" //---------------- context.進行カウンタ.一時停止する(); continue; //---------------- #endregion } if( context.ヒットランク種別 != ヒットランク種別.MISS ) { #region " (A) Perfect, Great, Good, Poor, Auto のアニメーション進行。" //----------------- if( context.進行カウンタ.現在値 < 50 ) { // (B-a) 0~49 context.X方向拡大率 = 1.0f + ( 1.0f * ( 1.0f - ( context.進行カウンタ.現在値 / 50.0f ) ) ); context.Y方向拡大率 = context.進行カウンタ.現在値 / 50.0f; context.相対X座標 = 0; context.相対Y座標 = 0; context.透明度0to1 = 1.0f; } else if( context.進行カウンタ.現在値 < 130 ) { // (B-b) 50~129 context.X方向拡大率 = 1.0f; context.Y方向拡大率 = 1.0f; context.相対X座標 = 0; context.相対Y座標 = ( ( context.進行カウンタ.現在値 % 6 ) == 0 ) ? ( App.乱数.Next( 6 ) - 3 ) : context.相対Y座標; context.透明度0to1 = 1.0f; } else if( context.進行カウンタ.現在値 < 240 ) { // (B-c) 130~239 context.X方向拡大率 = 1.0f; context.Y方向拡大率 = 1.0f; context.相対X座標 = 0; context.相対Y座標 = 0; context.透明度0to1 = 1.0f; } else { // (B-d) 240~300 context.X方向拡大率 = 1.0f; context.Y方向拡大率 = 1.0f - ( ( 1.0f * ( context.進行カウンタ.現在値 - 240 ) ) / 60.0f ); context.相対X座標 = 0; context.相対Y座標 = 0; context.透明度0to1 = 1.0f; } //----------------- #endregion } else { #region " (B) Miss のアニメーション進行だけ他とは違ってたり。" //----------------- if( context.進行カウンタ.現在値 < 50 ) { // (A-a) 0~49 context.X方向拡大率 = 1.0f; context.Y方向拡大率 = context.進行カウンタ.現在値 / 50.0f; context.相対X座標 = 0; context.相対Y座標 = 0; context.透明度0to1 = 1.0f; } else if( context.進行カウンタ.現在値 < 200 ) { // (A-b) 50~199 context.X方向拡大率 = 1.0f; context.Y方向拡大率 = 1.0f; context.相対X座標 = 0; context.相対Y座標 = 0; context.透明度0to1 = 1.0f; } else { // (A-c) 200~300 context.X方向拡大率 = 1.0f - ( ( context.進行カウンタ.現在値 - 200 ) / 100.0f ); context.Y方向拡大率 = 1.0f - ( ( context.進行カウンタ.現在値 - 200 ) / 100.0f ); context.相対X座標 = 0; context.相対Y座標 = 0; context.透明度0to1 = 1.0f; } //----------------- #endregion } } //---------------- #endregion #region " 描画 " //---------------- foreach( 表示レーン種別 lane in Enum.GetValues( typeof( 表示レーン種別 ) ) ) { var context = this._表示レーンto進行描画コンテキスト[ lane ]; if( context.進行カウンタ.停止中である ) continue; // カウンタが停止中 → このレーンについては何もしない。 var 判定文字列の画像 = this._ヒットランク画像[ context.ヒットランク種別 ]; if( 判定文字列の画像.生成失敗 ) return; var 判定文字列の左上端位置 = new Vector2( context.相対X座標, context.相対Y座標 ) + new Vector2( レーンフレームの左端 + レーンフレーム.レーンto横中央相対位置[ lane ], this._表示レーンtoレーン表示縦中央位置[ lane ] ) + new Vector2( -( ( 判定文字列の画像.サイズ.Width * context.X方向拡大率 ) / 2f ), -( ( 判定文字列の画像.サイズ.Height * context.Y方向拡大率 ) / 2f ) ); 判定文字列の画像?.描画する( gd, 左位置: 判定文字列の左上端位置.X, 上位置: 判定文字列の左上端位置.Y, 不透明度0to1: context.透明度0to1, X方向拡大率: context.X方向拡大率, Y方向拡大率: context.Y方向拡大率 ); } //---------------- #endregion } /// /// ヒット判定レーンには、それぞれに1つずつの進行描画コンテキストを用意する。 /// private class 進行描画コンテキスト { /// /// ヒット判定文字列のアニメ進行用カウンタ。 /// このカウンタが動作中のときのみ、ヒット判定文字列が描画される。 /// public Counter 進行カウンタ; /// /// 現在表示中のヒット判定種別。 /// 進行カウンタが動作中のときのみ有効。 /// public ヒットランク種別 ヒットランク種別; public bool 判定対象である; public float 中央Y位置; public float X方向拡大率; public float Y方向拡大率; public float 相対X座標; public float 相対Y座標; public float 透明度0to1; public 進行描画コンテキスト() { this.初期化する(); } public void 初期化する() { this.進行カウンタ = new Counter(); this.ヒットランク種別 = ヒットランク種別.AUTO; this.判定対象である = true; this.中央Y位置 = 0.0f; this.X方向拡大率 = 1.0f; this.Y方向拡大率 = 1.0f; this.相対X座標 = 0.0f; this.相対Y座標 = 0.0f; this.透明度0to1 = 1.0f; } } private Dictionary<表示レーン種別, 進行描画コンテキスト> _表示レーンto進行描画コンテキスト = null; private readonly Dictionary<ヒットランク種別, 画像> _ヒットランク画像 = new Dictionary<ヒットランク種別, 画像>() { { ヒットランク種別.PERFECT, new 画像( @"$(System)images\Judge Perfect.png" ) }, { ヒットランク種別.GREAT, new 画像( @"$(System)images\Judge Great.png" ) }, { ヒットランク種別.GOOD, new 画像( @"$(System)images\Judge Good.png" ) }, { ヒットランク種別.POOR, new 画像( @"$(System)images\Judge Poor.png" ) }, { ヒットランク種別.MISS, new 画像( @"$(System)images\Judge Miss.png" ) }, { ヒットランク種別.AUTO, new 画像( @"$(System)images\Judge Auto.png" ) }, }; private readonly Dictionary<表示レーン種別, float> _表示レーンtoレーン表示縦中央位置 = new Dictionary<表示レーン種別, float>() { { 表示レーン種別.Unknown, 0f }, { 表示レーン種別.LeftCrash, 469f }, { 表示レーン種別.HiHat, 562f }, { 表示レーン種別.Snare, 641f }, { 表示レーン種別.Tom1, 495f }, { 表示レーン種別.Bass, 716f }, { 表示レーン種別.Tom2, 558f }, { 表示レーン種別.Tom3, 798f }, { 表示レーン種別.RightCrash, 633f }, }; } }