Example #1
0
        public 譜面(メインフォーム form)
        {
            this.Form = form;

            // 初期化

            this.SSTFormatScore     = new スコア();
            this.譜面表示下辺の譜面内絶対位置grid = 0;
            foreach (var kvp in this.dicレーン番号)
            {
                this.dicレーン番号逆引き.Add(kvp.Value, kvp.Key);
            }

            #region " 最初は10小節ほど用意しておく → 10小節目の先頭に Unknown チップを置くことで実現。"
            //-----------------
            this.SSTFormatScore.チップリスト.Add(
                new 描画用チップ()
            {
                チップ種別       = チップ種別.Unknown,
                小節番号        = 9, // 0から数えて10番目の小節 = 009
                小節解像度       = 1,
                小節内位置       = 0,
                譜面内絶対位置grid = 9 * this.Form.GRID_PER_PART,          // 小節009の先頭位置
            });
            //-----------------
            #endregion
        }
Example #2
0
        internal static bool _行解析_オブジェクト記述(ref スコア スコア, ref C行解析時の状態変数 現在の, string コマンド, string パラメータ, string コメント)
        {
            if (!(_小節番号とチャンネル番号を取得する(コマンド, out 現在の.小節番号, out 現在の.チャンネル番号)))
            {
                return(false);
            }

            パラメータ = パラメータ.Replace("_", "");    // 見やすさのために '_' を区切り文字として使用できる(DTX仕様)
            パラメータ = パラメータ.ToLower();           // すべて小文字化(三十六進数変換表には大文字がないので)

            if (0x02 == 現在の.チャンネル番号)
            {
                #region " ch02 小節長倍率 "
                //----------------
                if (!(_DTX仕様の実数を取得する(パラメータ, out float 小節長倍率)))
                {
                    Debug.WriteLineIf(Verbose, $"{現在の.行番号}: ch02 のパラメータ(小節長倍率)に指定された実数の解析に失敗しました。");
                    return(false);
                }
                else if (0.0 >= 小節長倍率)
                {
                    Debug.WriteLineIf(Verbose, $"{現在の.行番号}: ch02 のパラメータ(小数長倍率)に 0 または負数を指定することはできません。");
                    return(false);
                }

                現在の.小節長倍率マップ.Remove(現在の.小節番号);              // 上書き可
                現在の.小節長倍率マップ[現在の.小節番号] = 小節長倍率;
                return(true);

                //----------------
                #endregion
            }
Example #3
0
        internal static bool _行解析_BPMzz(ref スコア スコア, ref C行解析時の状態変数 現在の, string コマンド, string パラメータ, string コメント)
        {
            if (!(コマンド.ToLower().StartsWith("bpm", ignoreCase: true, culture: null)) || (5 != コマンド.Length))
            {
                return(false);
            }

            int zz =
                _三十六進数変換表.IndexOf(コマンド[3]) * 36 +
                _三十六進数変換表.IndexOf(コマンド[4]);              // 36進数2桁表記

            if ((1 > zz) || (36 * 36 - 1 < zz))
            {
                return(false);                                                          // 有効範囲は 1~3599
            }
            if (float.TryParse(パラメータ, out float bpm値) && (0f < bpm値) && (1000f > bpm値)) // 値域制限はDTX仕様
            {
                // ※ 無限管理には非対応。
                現在の.BPM定義マップ.Remove(zz);     // 上書き可
                現在の.BPM定義マップ[zz] = bpm値;
                return(true);
            }
            else
            {
                return(false);
            }
        }
Example #4
0
        public void Dispose()
        {
            this.SSTFormatScore = null;

            this.小節番号文字フォント?.Dispose();
            this.小節番号文字フォント = null;

            this.小節番号文字ブラシ?.Dispose();
            this.小節番号文字ブラシ = null;

            this.小節番号文字フォーマット?.Dispose();
            this.小節番号文字フォーマット = null;

            this.ガイド線ペン?.Dispose();
            this.ガイド線ペン = null;

            this.小節線ペン?.Dispose();
            this.小節線ペン = null;

            this.拍線ペン?.Dispose();
            this.拍線ペン = null;

            this.レーン区分線ペン?.Dispose();
            this.レーン区分線ペン = null;

            this.レーン区分線太ペン?.Dispose();
            this.レーン区分線太ペン = null;

            this.カレントラインペン?.Dispose();
            this.カレントラインペン = null;

            this.レーン名文字フォント?.Dispose();
            this.レーン名文字フォント = null;

            this.レーン名文字ブラシ?.Dispose();
            this.レーン名文字ブラシ = null;

            this.レーン名文字影ブラシ?.Dispose();
            this.レーン名文字影ブラシ = null;

            this.レーン名文字フォーマット?.Dispose();
            this.レーン名文字フォーマット = null;

            this.チップの太枠ペン?.Dispose();
            this.チップの太枠ペン = null;

            this.チップ内文字列フォーマット?.Dispose();
            this.チップ内文字列フォーマット = null;

            this.チップ内文字列フォント?.Dispose();
            this.チップ内文字列フォント = null;

            this.白丸白バツペン?.Dispose();
            this.白丸白バツペン = null;

            this.Form = null;
        }
Example #5
0
        internal static bool _行解析_COMMENT(ref スコア スコア, ref C行解析時の状態変数 現在の, string コマンド, string パラメータ, string コメント)
        {
            if ("comment" != コマンド.ToLower())
            {
                return(false);
            }

            スコア.Header.説明文 = パラメータ;

            return(true);
        }
Example #6
0
        internal static bool _行解析_TITLE(ref スコア スコア, ref C行解析時の状態変数 現在の, string コマンド, string パラメータ, string コメント)
        {
            if ("title" != コマンド.ToLower())
            {
                return(false);
            }

            スコア.Header.曲名 = パラメータ;

            return(true);
        }
Example #7
0
        /// <summary>
        ///		行からDTXデータを読み込み、スコアを生成する。
        /// </summary>
        /// <returns>生成されたスコア。</returns>
        public static スコア ReadFromString(string 全入力文字列)
        {
            var スコア = new スコア();

            // 解析
            _行解析(ref スコア, ref 全入力文字列);

            // 後処理
            スコア.曲データファイルを読み込む_後処理だけ();

            return(スコア);
        }
Example #8
0
        public ゲームランナー(int 回数, bool サイレントモード = false)
        {
            var ゲーム = new ゲーム(サイレントモード);
            var スコア = new スコア();

            for (var index = 0; index < 回数; index++)
            {
                スコア.勝者登録(ゲーム.実行());
            }

            Console.WriteLine(スコア);
        }
Example #9
0
        internal static bool _行解析_BASEBPM(ref スコア スコア, ref C行解析時の状態変数 現在の, string コマンド, string パラメータ, string コメント)
        {
            if ("basebpm" != コマンド.ToLower())
            {
                return(false);
            }

            if (float.TryParse(パラメータ, out float bpm値))
            {
                現在の.BASEBPM = bpm値; // 上書き可
                return(true);
            }
            else
            {
                return(false);
            }
        }
Example #10
0
        internal static bool _行解析_BPM(ref スコア スコア, ref C行解析時の状態変数 現在の, string コマンド, string パラメータ, string コメント)
        {
            if ("bpm" != コマンド.ToLower())
            {
                return(false);
            }

            if (float.TryParse(パラメータ, out float bpm値))
            {
                // ※ 無限管理には非対応。

                //bpm値 += 現在の.BASEBPM;	--> #BPM: の値には #BASEBPM を加算しない。(DTX仕様)

                // "#BPM:" に対応するBPMチップは、常に、小節番号==0かつ小節内位置==0に置かれる。
                var bpmChip = スコア.チップリスト.FirstOrDefault((c) => (c.チップ種別 == チップ種別.BPM && c.小節番号 == 0 && c.小節内位置 == 0));
                if (null != bpmChip)
                {
                    // (A) すでに存在するなら上書き
                    bpmChip.BPM = bpm値;
                }
                else
                {
                    // (B) まだ存在していないなら新規追加
                    bpmChip = new チップ()
                    {
                        チップ種別 = チップ種別.BPM,
                        小節番号  = 0,
                        小節解像度 = 現在の.小節解像度,
                        小節内位置 = 0,
                        音量    = チップ.最大音量,
                        BPM   = bpm値,
                    };

                    スコア.チップリスト.Add(bpmChip);
                }

                return(true);
            }
            else
            {
                return(false);
            }
        }
Example #11
0
        // ローカル


        private Dictionary <演奏.表示レーン種別, int> _ノーツ数を算出して返す(スコア score, ユーザ設定 userConfig)
        {
            // ノーツ数マップを初期化。
            var ノーツ数マップ = new Dictionary <演奏.表示レーン種別, int>();

            foreach (演奏.表示レーン種別?lane in Enum.GetValues(typeof(演奏.表示レーン種別)))
            {
                if (lane.HasValue)
                {
                    ノーツ数マップ.Add(lane.Value, 0);
                }
            }

            // 譜面内のすべてのチップについて……
            foreach (var chip in score.チップリスト)
            {
                var ドラムチッププロパティ = userConfig.ドラムチッププロパティリスト[chip.チップ種別];

                // 1. AutoPlay ON のチップは、すべてが ON である場合を除いて、カウントしない。

                if (userConfig.AutoPlay[ドラムチッププロパティ.AutoPlay種別])
                {
                    if (!(userConfig.AutoPlayがすべてONである))
                    {
                        continue;
                    }
                }

                // 2. AutoPlay OFF 時でも、ユーザヒットの対象にならないチップはカウントしない。

                if (!(ドラムチッププロパティ.AutoPlayOFF_ユーザヒット))
                {
                    continue;
                }

                // カウント。

                ノーツ数マップ[ドラムチッププロパティ.表示レーン種別]++;
            }

            return(ノーツ数マップ);
        }
Example #12
0
        private static (double 最小BPM, double 最大BPM) _最小最大BPMを調べて返す(スコア score)
        {
            var result = (最小BPM : double.MaxValue, 最大BPM : double.MinValue);

            var BPMchips = score.チップリスト.Where((c) => (c.チップ種別 == チップ種別.BPM));

            foreach (var chip in BPMchips)
            {
                result.最小BPM = Math.Min(result.最小BPM, chip.BPM);
                result.最大BPM = Math.Max(result.最大BPM, chip.BPM);
            }

            if (result.最小BPM == double.MaxValue || result.最大BPM == double.MinValue)     // BPMチップがひとつもなかった
            {
                double 初期BPM = スコア.初期BPM;
                result = (初期BPM, 初期BPM);
            }

            return(result);
        }
Example #13
0
        public void 曲データファイルを読み込む(string ファイル名)
        {
            // 解放
            this.SSTFormatScore = null;

            // 読み込み
            this.SSTFormatScore = スコア.ファイルから生成する(ファイル名);

            // 後処理

            #region " 小節線・拍線チップをすべて削除する。"
            //-----------------
            this.SSTFormatScore.チップリスト.RemoveAll((chip) => (
                                                     chip.チップ種別 == チップ種別.小節線 ||
                                                     chip.チップ種別 == チップ種別.拍線 ||
                                                     chip.チップ種別 == チップ種別.Unknown));
            //-----------------
            #endregion
            #region " チップリストのすべてのチップを、描画用チップに変換する。"
            //----------------
            {
                // バックアップを取って、
                var 元のチップリスト = new チップ[this.SSTFormatScore.チップリスト.Count];
                for (int i = 0; i < this.SSTFormatScore.チップリスト.Count; i++)
                {
                    元のチップリスト[i] = this.SSTFormatScore.チップリスト[i];
                }

                // クリアして、
                this.SSTFormatScore.チップリスト.Clear();

                // 再構築。
                for (int i = 0; i < 元のチップリスト.Length; i++)
                {
                    this.SSTFormatScore.チップリスト.Add(new 描画用チップ(元のチップリスト[i]));
                }
            }
            //----------------
            #endregion
            #region " 全チップに対して「譜面内絶対位置grid」を設定する。"
            //-----------------
            {
                int チップが存在する小節の先頭grid = 0;
                int 現在の小節番号           = 0;

                foreach (描画用チップ chip in this.SSTFormatScore.チップリスト)
                {
                    // チップの小節番号が現在の小節番号よりも大きい場合、チップが存在する小節に至るまで、「nチップが存在する小節の先頭grid」を更新する。
                    while (現在の小節番号 < chip.小節番号)
                    {
                        double 現在の小節の小節長倍率 = this.SSTFormatScore.小節長倍率を取得する(現在の小節番号);
                        チップが存在する小節の先頭grid += (int)(this.Form.GRID_PER_PART * 現在の小節の小節長倍率);

                        現在の小節番号++;      // 現在の小節番号 が chip.小節番号 に追いつくまでループする。
                    }

                    chip.譜面内絶対位置grid =
                        チップが存在する小節の先頭grid +
                        (chip.小節内位置 * this.小節長をグリッドで返す(chip.小節番号)) / chip.小節解像度;
                }
            }
            //-----------------
            #endregion
        }
Example #14
0
        internal static void _行解析(ref スコア スコア, ref string 全入力文字列)
        {
            // 現在の状態の初期化。
            var 現在の = new C行解析時の状態変数()
            {
                小節番号     = 0,
                小節解像度    = 384, // DTX の小節解像度。
                チップ種別    = チップ種別.Unknown,
                小節長倍率マップ = new SortedDictionary <int, float>(),
                BPM定義マップ = new Dictionary <int, float>(),
                BPM参照マップ = new Dictionary <チップ, int>(),
            };

            Debug.WriteLineIf(Verbose, "行解析を開始します。");

            #region " 前処理(1) TAB は SPACE に置換しておく。"
            //----------------
            全入力文字列 = 全入力文字列.Replace('\t', ' ');
            //----------------
            #endregion

            #region " すべての行について解析。"
            //----------------
            using (var sr = new StringReader(全入力文字列))
            {
                string 行;

                // 1行ずつ処理。
                for (現在の.行番号 = 1; (行 = sr.ReadLine()) != null; 現在の.行番号++)
                {
                    // 行分解。
                    if (!(_行分解(行, out string コマンド, out string パラメータ, out string コメント)))
                    {
                        Debug.WriteLineIf(Verbose, $"{現在の.行番号}: 行分解に失敗しました。");
                        continue;
                    }
                    if (string.IsNullOrEmpty(コマンド))
                    {
                        continue;
                    }

                    // 行処理。
                    var done =
                        _行解析_TITLE(ref スコア, ref 現在の, コマンド, パラメータ, コメント) ||
                        _行解析_COMMENT(ref スコア, ref 現在の, コマンド, パラメータ, コメント) ||
                        _行解析_BASEBPM(ref スコア, ref 現在の, コマンド, パラメータ, コメント) ||
                        _行解析_BPM(ref スコア, ref 現在の, コマンド, パラメータ, コメント) ||
                        _行解析_BPMzz(ref スコア, ref 現在の, コマンド, パラメータ, コメント) ||
                        _行解析_オブジェクト記述(ref スコア, ref 現在の, コマンド, パラメータ, コメント);

                    // 行処理に失敗
                    //if( !( done ) )
                    //	Debug.WriteLineIf( Verbose, $"{現在の.行番号}: 未知のコマンドが使用されました。スキップします。[{コマンド}]" );
                }
            }
            //----------------
            #endregion

            #region " 後処理(1) BPMチップの値を引き当てる。"
            //----------------
            {
                foreach (var kvp in 現在の.BPM参照マップ)
                {
                    kvp.Key.BPM =
                        現在の.BPM定義マップ[kvp.Value] +
                        現在の.BASEBPM;        // 複数あるなら最後の値が入っている。
                }

                現在の.BPM参照マップ.Clear();   // 引き当てが終わったら、マップが持つチップへの参照を解放する。
            }
            //----------------
            #endregion
            #region " 後処理(2) 小節長倍率マップをもとに、スコアの小節長倍率リストを構築する。"
            //----------------
            {
                double 現在の倍率 = 1.0f;

                for (int i = 0; i <= スコア.最大小節番号; i++)       // すべての小節に対して設定。(SST仕様)
                {
                    if (現在の.小節長倍率マップ.ContainsKey(i))
                    {
                        現在の倍率 = (double)現在の.小節長倍率マップ[i];    // 指定された倍率は、それが指定された小節以降の小節にも適用する。(DTX仕様)
                    }
                    スコア.小節長倍率を設定する(i, 現在の倍率);
                }
            }
            //----------------
            #endregion

            // 解析終了。
            Debug.WriteLineIf(Verbose, "行解析を終了しました。");
        }