Beispiel #1
0
        /// <param name="全体の中央位置">
        ///		パネル(dc)の左上を原点とする座標。
        /// </param>
        public void 進行描画する(DeviceContext dc, アニメーション管理 am, Vector2 全体の中央位置, 成績 現在の成績)
        {
            // 追っかけ
            if (this._現在表示中のスコア < 現在の成績.Score)
            {
                int 増分    = 現在の成績.Score - this._現在表示中のスコア;
                int 追っかけ分 = Math.Max((int)(増分 * 0.75), 1);                      // VPS に依存するけどまあいい

                this._現在表示中のスコア = Math.Min(this._現在表示中のスコア + 追っかけ分, 現在の成績.Score);
            }

            int スコア値 = Math.Min(Math.Max(this._現在表示中のスコア, 0), 999999999); // プロパティには制限はないが、表示は999999999(9桁)でカンスト。

            string 数字     = スコア値.ToString().PadLeft(9);                   // 右詰め9桁、余白は ' '。
            var    全体のサイズ = new Vector2(62f * 9f, 99f);                   // 固定とする

            // 1桁ずつ表示。

            var 文字間隔補正 = -10f;
            var 文字の位置  = new Vector2(-(全体のサイズ.X / 2f), 0f);

            for (int i = 0; i < 数字.Length; i++)
            {
                // 前回の文字と違うなら、桁アニメーション開始。
                if (数字[i] != this._前回表示した数字[i])
                {
                    this._各桁のアニメ[i].跳ね開始(am, 0.0);
                }

                var 転送元矩形 = (RectangleF)this._スコア数字画像の矩形リスト[数字[i].ToString()];

                dc.Transform =
                    //Matrix3x2.Scaling( 画像矩形から表示矩形への拡大率 ) *
                    Matrix3x2.Translation(文字の位置.X, 文字の位置.Y + (float)(this._各桁のアニメ[i].Yオフセット?.Value ?? 0.0f)) *
                    //Matrix3x2.Scaling( 全体の拡大率.X, 全体の拡大率.Y, center: new Vector2( 0f, 全体のサイズ.Y / 2f ) ) *
                    Matrix3x2.Translation(全体の中央位置);

                dc.DrawBitmap(this._スコア数字画像.Bitmap, 1f, BitmapInterpolationMode.Linear, 転送元矩形);

                文字の位置.X += (転送元矩形.Width + 文字間隔補正) * 1f;                  // 画像矩形から表示矩形への拡大率.X;
            }

            // 更新。
            this._前回表示したスコア = this._現在表示中のスコア;
            this._前回表示した数字  = 数字;
        }
        public virtual void 描画する(DeviceContext dc, float x, float y, 成績 現在の成績)
        {
            var scaling = Matrix3x2.Scaling(1.0f, 1.4f);

            var 判定toヒット数 = 現在の成績.判定toヒット数;
            var 割合表      = 現在の成績.判定toヒット割合;
            int MaxCombo = 現在の成績.MaxCombo;
            int 合計       = 0;

            dc.Transform = scaling * Matrix3x2.Translation(x, y);
            this.パラメータを一行描画する(dc, 0f, 0f, 判定種別.PERFECT, 判定toヒット数[判定種別.PERFECT], 割合表[判定種別.PERFECT]);
            合計 += 判定toヒット数[判定種別.PERFECT];
            y  += _改行幅dpx;

            dc.Transform = scaling * Matrix3x2.Translation(x, y);
            this.パラメータを一行描画する(dc, 0f, 0f, 判定種別.GREAT, 判定toヒット数[判定種別.GREAT], 割合表[判定種別.GREAT]);
            合計 += 判定toヒット数[判定種別.GREAT];
            y  += _改行幅dpx;

            dc.Transform = scaling * Matrix3x2.Translation(x, y);
            this.パラメータを一行描画する(dc, 0f, 0f, 判定種別.GOOD, 判定toヒット数[判定種別.GOOD], 割合表[判定種別.GOOD]);
            合計 += 判定toヒット数[判定種別.GOOD];
            y  += _改行幅dpx;

            dc.Transform = scaling * Matrix3x2.Translation(x, y);
            this.パラメータを一行描画する(dc, 0f, 0f, 判定種別.OK, 判定toヒット数[判定種別.OK], 割合表[判定種別.OK]);
            合計 += 判定toヒット数[判定種別.OK];
            y  += _改行幅dpx;

            dc.Transform = scaling * Matrix3x2.Translation(x, y);
            this.パラメータを一行描画する(dc, 0f, 0f, 判定種別.MISS, 判定toヒット数[判定種別.MISS], 割合表[判定種別.MISS]);
            合計 += 判定toヒット数[判定種別.MISS];
            y  += _改行幅dpx;

            y += 3f;                // ちょっと間を開けて
            var 矩形 = (RectangleF)this._判定種別文字の矩形リスト["MaxCombo"];

            dc.Transform = scaling * Matrix3x2.Translation(x, y);
            this._判定種別文字.描画する(dc, 0f, 0f, 転送元矩形: 矩形);
            x           += 矩形.Width + 16f;
            dc.Transform = scaling * Matrix3x2.Translation(x, y);
            this.数値を描画する(dc, 0f, 0f, MaxCombo, 桁数: 4);
            this.数値を描画する(dc, _dr, 0f, (int)Math.Floor(100.0 * MaxCombo / 合計), 桁数: 3);                     // 切り捨てでいいやもう
            this._パラメータ文字.描画する(dc, _dp, 0f, "%");
        }
Beispiel #3
0
        /// <param name="全体の中央位置">
        ///		パネル(dc)の左上を原点とする座標。
        /// </param>
        public void 進行描画する(DeviceContext dc, アニメーション管理 am, Vector2 全体の中央位置, 成績 現在の成績)
        {
            int Combo値 = Math.Min(Math.Max(現在の成績.Combo, 0), 9999);                  // 表示は9999でカンスト。

            if (Combo値 < 10)
            {
                return;                 // 10未満は表示しない。
            }
            // 100を超えるたびアニメ開始。
            if ((this._前回表示した値 % 100) > (Combo値 % 100))
            {
                this._百ごとのアニメ.開始(am);
            }

            var 数字 = Combo値.ToString().PadLeft(4).Replace(' ', 'o');                 // 右詰め4桁、余白は 'o'。

            var 画像矩形から表示矩形への拡大率 = new Vector2(264f / (142f * 4f), 140f / 188f);
            var 文字間隔補正          = -10f;

            var 全体の拡大率 = new Vector2((float)(this._百ごとのアニメ.拡大率?.Value ?? 1.0));

            // 全体のサイズを算出。
            var 全体のサイズ = new Vector2(0f, 0f);

            for (int i = 0; i < 数字.Length; i++)
            {
                var 矩形 = this._コンボ文字画像の矩形[数字[i].ToString()].Value;
                全体のサイズ.X += 矩形.Width + 文字間隔補正;                      // 合計
                全体のサイズ.Y  = Math.Max(全体のサイズ.Y, 矩形.Height);          // 最大値
            }
            全体のサイズ = 全体のサイズ * 画像矩形から表示矩形への拡大率;

            // 全体の位置を修正。
            全体の中央位置.Y -= 全体のサイズ.Y / 2f;
            var 振動幅 = (float)(this._百ごとのアニメ.振動幅?.Value ?? 0.0f);

            if (0.0f < 振動幅)
            {
                全体の中央位置.X += App.乱数.NextFloat(-振動幅, +振動幅);
                全体の中央位置.Y += App.乱数.NextFloat(-振動幅, +振動幅);
            }

            // 1桁ずつ表示。

            var 文字の位置 = new Vector2(-(全体のサイズ.X / 2f), 0f);

            for (int i = 0; i < 数字.Length; i++)
            {
                if (数字[i] != this._前回表示した数字[i])
                {
                    // 桁アニメーション開始
                    this._各桁のアニメ[i].落下開始(am);

                    // 1の位以外は、自分より上位の桁を順番に跳ねさせる。
                    if (3 > i)
                    {
                        for (int p = (i - 1); p >= 0; p--)
                        {
                            this._各桁のアニメ[p].跳ね開始(am, 0.05 * ((i - 1) - p + 1));
                        }
                    }
                }

                var 転送元矩形 = (RectangleF)this._コンボ文字画像の矩形[数字[i].ToString()];

                dc.Transform =
                    Matrix3x2.Scaling(画像矩形から表示矩形への拡大率) *
                    Matrix3x2.Translation(文字の位置.X, 文字の位置.Y + (float)(this._各桁のアニメ[i].Yオフセット?.Value ?? 0.0f)) *
                    Matrix3x2.Scaling(全体の拡大率.X, 全体の拡大率.Y, center: new Vector2(0f, 全体のサイズ.Y / 2f)) *
                    Matrix3x2.Translation(全体の中央位置);

                dc.DrawBitmap(this._コンボ文字画像.Bitmap, (float)(this._各桁のアニメ[i].透明度?.Value ?? 1.0f), BitmapInterpolationMode.Linear, 転送元矩形);

                文字の位置.X += (転送元矩形.Width + 文字間隔補正) * 画像矩形から表示矩形への拡大率.X;
            }

            // "Combo"
            {
                var 転送元矩形 = (RectangleF)this._コンボ文字画像の矩形["Combo"];
                文字の位置 = new Vector2(0f, 130f);

                dc.Transform =
                    Matrix3x2.Scaling(画像矩形から表示矩形への拡大率) *
                    Matrix3x2.Translation(文字の位置) *
                    Matrix3x2.Scaling(全体の拡大率) *
                    Matrix3x2.Translation(全体の中央位置);

                dc.DrawBitmap(this._コンボ文字画像.Bitmap, 1.0f, BitmapInterpolationMode.Linear, 転送元矩形);
            }

            // 保存
            this._前回表示した値  = 現在の成績.Combo;
            this._前回表示した数字 = 数字;
        }
        protected override void On活性化(グラフィックデバイス gd)
        {
            using (Log.Block(FDKUtilities.現在のメソッド名))
            {
                Debug.Assert(null != App.演奏スコア, "演奏スコアが指定されていません。");

                this.キャプチャ画面 = null;

                this.成績 = new 成績();
                this.成績.スコアと設定を反映する(App.演奏スコア, App.ユーザ管理.ログオン中のユーザ);

                this._描画開始チップ番号            = -1;
                this._小節線色                 = new SolidColorBrush(gd.D2DDeviceContext, Color.White);
                this._拍線色                  = new SolidColorBrush(gd.D2DDeviceContext, Color.LightGray);
                this._ドラムチップ画像の矩形リスト       = new 矩形リスト(@"$(System)images\ドラムチップ矩形.xml");                  // デバイスリソースは持たないので、子Activityではない。
                this._現在進行描画中の譜面スクロール速度の倍率 = App.ユーザ管理.ログオン中のユーザ.譜面スクロール速度;
                this._ドラムチップアニメ            = new LoopCounter(0, 200, 3);
                this._背景動画                 = null;
                this._BGM                  = null;
                this._背景動画開始済み             = false;
                this._BGM再生開始済み            = false;
                //this._デコード済みWaveSource = null;	--> キャッシュなので消さない。
                this._プレイヤー名表示.前 = App.ユーザ管理.ログオン中のユーザ.ユーザ名;

                this._チップの演奏状態 = new Dictionary <チップ, チップの演奏状態>();
                foreach (var chip in App.演奏スコア.チップリスト)
                {
                    this._チップの演奏状態.Add(chip, new チップの演奏状態(chip));
                }

                if (null != App.演奏スコア)
                {
                    #region " 背景動画とBGMを生成する。"
                    //----------------
                    if (App.演奏スコア.背景動画ファイル名.Nullでも空でもない())
                    {
                        #region " (A) SST準拠の動画とBGM "
                        //----------------
                        Log.Info("背景動画とBGMを読み込みます。");

                        // 動画を子リストに追加。
                        this.子リスト.Add(this._背景動画 = new 動画(App.演奏スコア.背景動画ファイル名));

                        // 動画から音声パートを抽出して BGM を作成。
                        try
                        {
                            this._デコード済みWaveSource?.Dispose();
                            this._デコード済みWaveSource = SampleSourceFactory.Create(App.サウンドデバイス, App.演奏スコア.背景動画ファイル名);

                            this._BGM?.Dispose();
                            this._BGM = new Sound(App.サウンドデバイス, this._デコード済みWaveSource);
                        }
                        catch (InvalidDataException)
                        {
                            // DTXの動画のようにサウンドを含まない動画の場合、この例外が発生するだろう。
                            Log.WARNING("背景動画ファイルからBGMを生成することに失敗しました。");
                            this._BGM = null;
                        }
                        //----------------
                        #endregion
                    }
                    else if (0 < App.演奏スコア.dicAVI.Count)
                    {
                        #region " (B) DTX準拠の動画 "
                        //----------------
                        Log.Info("背景動画を読み込みます。");

                        // #AVIzz がいくつ宣言されてても、最初のAVIだけを対象とする。
                        var path = Path.Combine(App.演奏スコア.PATH_WAV, App.演奏スコア.dicAVI.ElementAt(0).Value);

                        // 動画を子リストに追加。
                        this.子リスト.Add(this._背景動画 = new 動画(path));

                        // BGM パートは使わない。
                        this._BGM = null;
                        //----------------
                        #endregion
                    }
                    else
                    {
                        Log.Info("背景動画とBGMはありません。");
                    }
                    //----------------
                    #endregion

                    #region " WAVを生成する(ある場合)。"
                    //----------------
                    App.WAV管理 = new 曲.WAV管理();

                    foreach (var kvp in App.演奏スコア.dicWAV)
                    {
                        var path = Path.Combine(App.演奏スコア.PATH_WAV, kvp.Value.ファイルパス);
                        App.WAV管理.登録する(App.サウンドデバイス, kvp.Key, path.ToVariablePath(), kvp.Value.多重再生する);
                    }
                    //----------------
                    #endregion
                }

                this.現在のフェーズ   = フェーズ.フェードイン;
                this._初めての進行描画 = true;
            }
        }