public override void Render() { DeviceContext.Clear(Color.MediumPurple); DeviceContext.Transform = Matrix3x2.Rotation(position * 0.018f, new Vector2(position + 100, 200)); DeviceContext.DrawBitmap(Resource, "Image", new RawRectangleF(position, 100, position + 200, 300)); DeviceContext.Transform = Matrix3x2.Identity; }
// 進行と描画 /// <summary> /// 画像を描画する。 /// </summary> /// <param name="dc">描画に使うデバイスコンテキスト。</param> /// <param name="左位置">画像の描画先範囲の左上隅X座標。</param> /// <param name="上位置">画像の描画先範囲の左上隅Y座標。</param> /// <param name="不透明度0to1">不透明度。(0:透明~1:不透明)</param> /// <param name="X方向拡大率">画像の横方向の拡大率。</param> /// <param name="Y方向拡大率">画像の縦方向の拡大率。</param> /// <param name="転送元矩形">画像の転送元範囲。</param> /// <param name="描画先矩形を整数境界に合わせる">true なら、描画先の転送先矩形の座標を float から int に丸める。</param> /// <param name="変換行列3D">射影行列。</param> /// <param name="レイヤーパラメータ>レイヤーを使う場合は指定する。</param> /// <remarks> /// Direct2D の転送先矩形は float で指定できるが、非整数の値(=物理ピクセル単位じゃない座標)を渡すと、表示画像がプラスマイナス1pxの範囲で乱れる。 /// これにより、数px程度の大きさの画像を移動させるとチカチカする原因になる。 /// それが困る場合には、「描画先矩形を整数境界に合わせる」に true を指定すること。 /// ただし、これを true にした場合、タイルのように並べて描画した場合に1pxずれる場合がある。この場合は false にすること。 /// </remarks> public virtual void 描画する(DeviceContext dc, float 左位置, float 位置, float 透明度0to1 = 1.0f, float X方向拡大率 = 1.0f, float Y方向拡大率 = 1.0f, RectangleF?転送元矩形 = null, bool 描画先矩形を整数境界に合わせる = false, Matrix?換行列3D = null, LayerParameters1?レイヤーパラメータ = null) { if (this.Bitmap is null) { return; } var preBlend = dc.PrimitiveBlend; dc.PrimitiveBlend = (this.加算合成する) ? PrimitiveBlend.Add : PrimitiveBlend.SourceOver; // 転送元・転送先矩形を算出する。 転送元矩形 ??= new RectangleF(0f, 0f, this.サイズ.Width, this.サイズ.Height); var 転送先矩形 = new RectangleF( x: 左位置, y: 位置, width: 転送元矩形.Value.Width * X方向拡大率, height: 転送元矩形.Value.Height * Y方向拡大率); if (描画先矩形を整数境界に合わせる) { 転送先矩形.X = (float)Math.Round(転送先矩形.X); 転送先矩形.Y = (float)Math.Round(転送先矩形.Y); 転送先矩形.Width = (float)Math.Round(転送先矩形.Width); 転送先矩形.Height = (float)Math.Round(転送先矩形.Height); } // レイヤーパラメータの指定があれば、描画前に Layer を作成して、Push する。 var layer = (Layer?)null; if (レイヤーパラメータ.HasValue) { layer = new Layer(dc); // 因果関係は分からないが、同じBOX内の曲が増えるとこの行の負荷が増大するので、必要時にしか生成しないこと。 dc.PushLayer(レイヤーパラメータ.Value, layer); } // D2Dレンダーターゲットに Bitmap を描画する。 dc.DrawBitmap( bitmap: this.Bitmap, destinationRectangle: 転送先矩形, opacity: 透明度0to1, interpolationMode: InterpolationMode.Linear, sourceRectangle: 転送元矩形, erspectiveTransformRef: 換行列3D); // null 指定可。 // レイヤーパラメータの指定があれば、描画後に Pop する。 if (null != layer) { dc.PopLayer(); layer.Dispose(); } dc.PrimitiveBlend = preBlend; }
// 進行と描画 /// <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); グラフィックデバイス.Instance.D2DBatchDraw(dc, () => { var pretrans = dc.Transform; dc.PrimitiveBlend = PrimitiveBlend.SourceOver; for (int i = 0; i < 数字.Length; i++) { // 前回の文字と違うなら、桁アニメーション開始。 if (数字[i] != this._前回表示した数字[i]) { this._各桁のアニメ[i].跳ね開始(am, 0.0); } var 転送元矩形 = 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(全体の中央位置) * pretrans; dc.DrawBitmap(this._スコア数字画像.Bitmap, 1f, BitmapInterpolationMode.Linear, 転送元矩形); 文字の位置.X += (転送元矩形.Width + 文字間隔補正) * 1f; // 画像矩形から表示矩形への拡大率.X; } }); // 更新。 this._前回表示したスコア = this._現在表示中のスコア; this._前回表示した数字 = 数字; }
// 進行と描画 /// <param name="全体の中央位置"> /// パネル(dc)の左上を原点とする座標。 /// </param> public void 進行描画する(DeviceContext d2ddc, Animation am, Vector2 全体の中央位置, 成績 現在の成績) { // 進行。 if (this._現在表示中のスコア < 現在の成績.Score) { int 増分 = 現在の成績.Score - this._現在表示中のスコア; int 追っかけ分 = Math.Max((int)(増分 * 0.75), 1); // VPS に依存するけどまあいい this._現在表示中のスコア = Math.Min(this._現在表示中のスコア + 追っかけ分, 現在の成績.Score); } int スコア値 = Math.Clamp(this._現在表示中のスコア, min: 0, max: 999999999); // プロパティには制限はないが、表示は999999999(9桁)でカンスト。 string 数字 = スコア値.ToString().PadLeft(9); // 右詰め9桁、余白は ' '。 var 全体のサイズ = new Vector2(62f * 9f, 99f); // 固定とする // 1桁ずつ描画。 var 文字間隔補正 = -10f; var 文字の位置 = new Vector2(-(全体のサイズ.X / 2f), 0f); var preTrans = d2ddc.Transform; for (int i = 0; i < 数字.Length; i++) { // 前回の文字と違うなら、桁アニメーション開始。 if (数字[i] != this._前回表示した数字[i]) { this._各桁のアニメ[i].跳ね開始(am, 0.0); } var 転送元矩形 = this._スコア数字の矩形リスト[数字[i].ToString()] !; d2ddc.Transform = Matrix3x2.Translation(文字の位置.X, 文字の位置.Y + (float)(this._各桁のアニメ[i].Yオフセット?.Value ?? 0.0f)) * Matrix3x2.Translation(全体の中央位置) * preTrans; // todo: フォント画像D2D に置き換える? d2ddc.DrawBitmap(this._スコア数字画像.Bitmap, 1f, BitmapInterpolationMode.Linear, 転送元矩形.Value); 文字の位置.X += (転送元矩形.Value.Width + 文字間隔補正) * 1f; // 画像矩形から表示矩形への拡大率.X; } d2ddc.Transform = preTrans; // 更新。 this._前回表示した数字 = 数字; }
private void _フレームを描画する(DeviceContext dc, Matrix3x2 換行列2D, float 透明度0to1, VideoFrame 描画するフレーム) { if (null == 描画するフレーム) { return; } グラフィックデバイス.Instance.D2DBatchDraw(dc, () => { dc.Transform = (換行列2D) * dc.Transform; dc.PrimitiveBlend = (this.加算合成) ? PrimitiveBlend.Add : PrimitiveBlend.SourceOver; dc.DrawBitmap(描画するフレーム.Bitmap, 透明度0to1, InterpolationMode.NearestNeighbor); }); }
/// <summary> /// Draws a bitmap image. /// </summary> /// <param name="source">The bitmap image.</param> /// <param name="opacity">The opacity to draw with.</param> /// <param name="sourceRect">The rect in the image to draw.</param> /// <param name="destRect">The rect in the output to draw to.</param> /// <param name="bitmapInterpolationMode">The bitmap interpolation mode.</param> public void DrawImage(IRef <IBitmapImpl> source, double opacity, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode) { using (var d2d = ((BitmapImpl)source.Item).GetDirect2DBitmap(_deviceContext)) { var interpolationMode = GetInterpolationMode(bitmapInterpolationMode); _deviceContext.DrawBitmap( d2d.Value, destRect.ToSharpDX(), (float)opacity, interpolationMode, sourceRect.ToSharpDX(), null); } }
public override void Render() { DeviceContext.Clear(Color.CornflowerBlue); DeviceContext.Transform = Matrix3x2.Rotation(position * 0.018f, new Vector2(position + 50, position + 150)); DeviceContext.DrawBitmap(Resource, "Image", new RawRectangleF(position, position + 100, position + 100, position + 200)); DeviceContext.Transform = Matrix3x2.Transformation(1, 1, 0, 10, 10); DeviceContext.DrawSprite(Resource, "Sprite"); DeviceContext.Transform = Matrix3x2.Identity; SpriteBatch.Begin(); SpriteBatch.Draw(Resource.Get <SpriteResource>("Saikoro"), new Vector2(position + 100, 150), position * 0.018f); SpriteBatch.End(); }
private void _フレームを描画する(DeviceContext dc, Matrix3x2 換行列2D, float 透明度0to1, VideoFrame 描画するフレーム) { if (描画するフレーム is null) { return; } var preTrans = dc.Transform; var preBlend = dc.PrimitiveBlend; dc.Transform = (換行列2D) * preTrans; dc.PrimitiveBlend = (this.加算合成) ? PrimitiveBlend.Add : PrimitiveBlend.SourceOver; dc.DrawBitmap(描画するフレーム.Bitmap, 透明度0to1, InterpolationMode.NearestNeighbor); dc.PrimitiveBlend = preBlend; dc.Transform = preTrans; }
protected override void OnDxPaint(Dx11Component resource) { DeviceContext context = resource.D2D.Context; Size clientSize = GetClientSize(); if (frames % framesPerTick == 0) { for (int i = 0; i < ticksPerFrame; i++) { update |= circuitBoard.Update(); performanceMonitor.IncrementTicks(); } if (update) { circuitBoard.Image.CopyToBitmap(bitmap); update = false; } frames = 0; } frames++; context.BeginDraw(); context.Clear(clearColor); context.Transform = transformationMatrix; context.DrawBitmap(bitmap, CreateImageRect(bitmap.PixelSize, clientSize), 1f, BitmapInterpolationMode.NearestNeighbor); context.Transform = identityMatrix; if (performanceMonitor.TryCalculate()) { performaceText = $"{performanceMonitor.FramesPerSecond:F0} FPS | {performanceMonitor.TicksPerSecond:F0} TPS"; } context.DrawText(performaceText, textFormat, new RawRectangleF(0f, 0f, clientSize.Width, clientSize.Height), textBrush); context.EndDraw(); performanceMonitor.IncermentFrames(); }
public void Render(DeviceContext context) { if (_bitmap == null) { _bitmap = new Bitmap1(context, Size, new BitmapProperties1(context.PixelFormat, context.DotsPerInch.Width, context.DotsPerInch.Height)); UpdateBitmap(); } lock (_renderSync) { if (_isDirty) { UpdateBitmap(); } } context.DrawBitmap(_bitmap, _bounds, 1.0f, BitmapInterpolationMode.NearestNeighbor); //context.D2Context.DrawBitmap(_bitmap, _bounds, 1.0f); }
/// <summary> /// 画像を描画する。 /// </summary> /// <param name="変換行列2D">Transform に適用する行列。</param> /// <param name="変換行列3D">射影行列。</param> /// <param name="不透明度0to1">不透明度。(0:透明~1:不透明)</param> /// <param name="転送元矩形">描画する画像範囲。</param> public virtual void 描画する(DeviceContext dc, Matrix3x2?換行列2D = null, Matrix?換行列3D = null, float 透明度0to1 = 1.0f, RectangleF?転送元矩形 = null, LayerParameters1?レイヤーパラメータ = null) { if (this.Bitmap is null) { return; // 画像の生成に失敗していたら何も描画しない。 } var preBlend = dc.PrimitiveBlend; var preTrans = dc.Transform; dc.PrimitiveBlend = (this.加算合成する) ? PrimitiveBlend.Add : PrimitiveBlend.SourceOver; dc.Transform = (換行列2D ?? Matrix3x2.Identity) * preTrans; // レイヤーパラメータの指定があれば、描画前に Layer を作成して、Push する。 var layer = (Layer?)null; if (レイヤーパラメータ.HasValue) { layer = new Layer(dc); // 因果関係は分からないが、同じBOX内の曲が増えるとこの行の負荷が増大するので、必要時にしか生成しないこと。 dc.PushLayer((LayerParameters1)レイヤーパラメータ, layer); } // D2Dレンダーターゲットに this.Bitmap を描画する。 dc.DrawBitmap( bitmap: this.Bitmap, destinationRectangle: null, opacity: 透明度0to1, interpolationMode: InterpolationMode.Linear, sourceRectangle: 転送元矩形, erspectiveTransformRef: 換行列3D); // null 指定可。 // layer を作成したなら、描画後に Pop する。 if (null != layer) { dc.PopLayer(); layer.Dispose(); } dc.PrimitiveBlend = preBlend; dc.Transform = preTrans; }
/// <summary> /// 画像を描画する。 /// </summary> /// <param name="変換行列2D">Transform に適用する行列。</param> /// <param name="変換行列3D">射影行列。</param> /// <param name="不透明度0to1">不透明度。(0:透明~1:不透明)</param> /// <param name="転送元矩形">描画する画像範囲。</param> public virtual void 描画する(DeviceContext dc, Matrix3x2?換行列2D = null, Matrix?換行列3D = null, float 透明度0to1 = 1.0f, RectangleF?転送元矩形 = null, LayerParameters1?レイヤーパラメータ = null) { if (null == this.Bitmap) { return; } グラフィックデバイス.Instance.D2DBatchDraw(dc, () => { var pretrans = dc.Transform; dc.Transform = (換行列2D ?? Matrix3x2.Identity) * pretrans; dc.PrimitiveBlend = (this.加算合成) ? PrimitiveBlend.Add : PrimitiveBlend.SourceOver; using (var layer = new Layer(dc)) { // レイヤーパラメータの指定があれば、描画前に Push する。 if (null != レイヤーパラメータ) { dc.PushLayer((LayerParameters1)レイヤーパラメータ, layer); } // D2Dレンダーターゲットに this.Bitmap を描画する。 dc.DrawBitmap( bitmap: this.Bitmap, destinationRectangle: null, opacity: 透明度0to1, interpolationMode: this.補正モード, sourceRectangle: 転送元矩形, erspectiveTransformRef: 換行列3D); // null 指定可。 // レイヤーパラメータの指定があれば、描画後に Pop する。 if (null != レイヤーパラメータ) { dc.PopLayer(); } } dc.Transform = pretrans; }); }
// 進行と描画 /// <summary> /// アイキャッチのアニメーションを進行し、アイキャッチ画像を描画する。 /// </summary> protected override void 進行描画する(DeviceContext dc, StoryboardStatus 描画しないStatus) { bool すべて完了 = true; switch (this.現在のフェーズ) { case フェーズ.クローズ: #region " *** " //---------------- if (this._アニメーション.ストーリーボード.Status != StoryboardStatus.Ready) { すべて完了 = false; } if (this._アニメーション.ストーリーボード.Status != 描画しないStatus) { DXResources.Instance.D2DBatchDraw(dc, () => { var pretrans = dc.Transform; #region " 背景マスク " //---------------- using (var ブラシ = new SolidColorBrush(dc, new Color4(Color3.Black, (float)this._アニメーション.背景_不透明度.Value))) { dc.FillRectangle(new RectangleF(0f, 0f, DXResources.Instance.設計画面サイズ.Width, DXResources.Instance.設計画面サイズ.Width), ブラシ); } //---------------- #endregion #region " (2) 黒幕1(左下)" //---------------- { float w = DXResources.Instance.設計画面サイズ.Width * 1.5f; float h = DXResources.Instance.設計画面サイズ.Height; var rc = new RectangleF(-w / 2f, -h / 2f, w, h); dc.Transform = Matrix3x2.Rotation( // 上辺中央を中心として回転 angle: (float)this._アニメーション.黒幕1左下_回転角rad.Value, center: new Vector2(0f, -rc.Height / 2f)) * Matrix3x2.Translation( // (基点X, H×3/4) へ移動 x: (float)this._アニメーション.黒幕1左下_基点位置X.Value, y: DXResources.Instance.設計画面サイズ.Height) * pretrans; dc.FillRectangle(rc, this._黒ブラシ); } //---------------- #endregion #region " (3) 黒幕2(右上)" //---------------- { float w = DXResources.Instance.設計画面サイズ.Width * 1.5f; float h = DXResources.Instance.設計画面サイズ.Height; var rc = new RectangleF(-w / 2f, -h / 2f, w, h); dc.Transform = Matrix3x2.Rotation( // 下辺中央を中心として回転 angle: (float)this._アニメーション.黒幕2右上_回転角rad.Value, center: new Vector2(0f, rc.Height / 2f)) * Matrix3x2.Translation( // (基点X, H×1/4) へ移動 x: (float)this._アニメーション.黒幕2右上_基点位置X.Value, y: 0f) * pretrans; dc.FillRectangle(rc, this._黒ブラシ); } //---------------- #endregion #region " (4) ロゴ " //---------------- dc.Transform = Matrix3x2.Scaling(639f / this._ロゴ画像.サイズ.Width, 262f / this._ロゴ画像.サイズ.Height) * Matrix3x2.Translation((float)this._アニメーション.ロゴ_位置X.Value, 771f) * pretrans; dc.DrawBitmap(this._ロゴ画像.Bitmap, (float)this._アニメーション.ロゴ_不透明度.Value, BitmapInterpolationMode.Linear); //---------------- #endregion }); } //---------------- #endregion break; case フェーズ.クローズ完了: break; case フェーズ.オープン: #region " *** " //---------------- if (this._アニメーション.ストーリーボード.Status != StoryboardStatus.Ready) { すべて完了 = false; } if (this._アニメーション.ストーリーボード.Status != 描画しないStatus) { DXResources.Instance.D2DBatchDraw(dc, () => { var pretrans = dc.Transform; #region " (1) 背景マスク " //---------------- using (var ブラシ = new SolidColorBrush(dc, new Color4(Color3.Black, (float)this._アニメーション.背景_不透明度.Value))) { dc.FillRectangle(new RectangleF(0f, 0f, DXResources.Instance.設計画面サイズ.Width, DXResources.Instance.設計画面サイズ.Width), ブラシ); } //---------------- #endregion #region " (2) 黒幕1(左下)" //---------------- { float w = DXResources.Instance.設計画面サイズ.Width * 1.5f; float h = DXResources.Instance.設計画面サイズ.Height; var rc = new RectangleF(-w / 2f, -h / 2f, w, h); dc.Transform = Matrix3x2.Rotation( // 上辺中央を中心として回転 angle: (float)this._アニメーション.黒幕1左下_回転角rad.Value, center: new Vector2(0f, -rc.Height / 2f)) * Matrix3x2.Translation( // (基点X, H×3/4) へ移動 x: (float)this._アニメーション.黒幕1左下_基点位置X.Value, y: DXResources.Instance.設計画面サイズ.Height) * pretrans; dc.FillRectangle(rc, this._黒ブラシ); } //---------------- #endregion #region " (3) 黒幕2(右上)" //---------------- { float w = DXResources.Instance.設計画面サイズ.Width * 1.5f; float h = DXResources.Instance.設計画面サイズ.Height; var rc = new RectangleF(-w / 2f, -h / 2f, w, h); dc.Transform = Matrix3x2.Rotation( // 下辺中央を中心として回転 angle: (float)this._アニメーション.黒幕2右上_回転角rad.Value, center: new Vector2(0f, rc.Height / 2f)) * Matrix3x2.Translation( // (基点X, H×1/4) へ移動 x: (float)this._アニメーション.黒幕2右上_基点位置X.Value, y: 0f) * pretrans; dc.FillRectangle(rc, this._黒ブラシ); } //---------------- #endregion #region " (4) ロゴ " //---------------- dc.Transform = Matrix3x2.Scaling(639f / this._ロゴ画像.サイズ.Width, 262f / this._ロゴ画像.サイズ.Height) * Matrix3x2.Translation((float)this._アニメーション.ロゴ_位置X.Value, 771f) * pretrans; dc.DrawBitmap(this._ロゴ画像.Bitmap, (float)this._アニメーション.ロゴ_不透明度.Value, BitmapInterpolationMode.Linear); //---------------- #endregion }); } //---------------- #endregion break; case フェーズ.オープン完了: break; } if (すべて完了) { if (this.現在のフェーズ == フェーズ.クローズ) { this.現在のフェーズ = フェーズ.クローズ完了; } else if (this.現在のフェーズ == フェーズ.オープン) { this.現在のフェーズ = フェーズ.オープン完了; } } }
/// <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._前回表示した数字 = 数字; }
// 進行と描画 /// <param name="全体の中央位置"> /// パネル(dc)の左上を原点とする座標。 /// </param> public void 進行描画する(DeviceContext d2ddc, Vector2 全体の中央位置, 成績 現在の成績) { int Combo値 = Math.Clamp(現在の成績.Combo, min: 0, max: 9999); // 表示は9999でカンスト。 if (Combo値 < 10) { return; // 10未満は表示しない。 } if ((this._前回表示した値 % 100) > (Combo値 % 100)) { // 100を超えるたびアニメ開始。 this._百ごとのアニメ.開始(Global.Animation); } 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()] !; 全体のサイズ.X += 矩形.Value.Width + 文字間隔補正; // 合計 全体のサイズ.Y = Math.Max(全体のサイズ.Y, 矩形.Value.Height); // 最大値 } 全体のサイズ *= 画像矩形から表示矩形への拡大率; // 全体の位置を修正。 全体の中央位置.Y -= 全体のサイズ.Y / 2f; var 振動幅 = (float)(this._百ごとのアニメ.振動幅?.Value ?? 0.0f); if (0.0f < 振動幅) { 全体の中央位置.X += Global.App.乱数.NextFloat(-振動幅, +振動幅); 全体の中央位置.Y += Global.App.乱数.NextFloat(-振動幅, +振動幅); } // 1桁ずつ描画。 var preTrans = d2ddc.Transform; #region " 数字を描画。" //---------------- { var 文字の位置 = new Vector2(-(全体のサイズ.X / 2f), 0f); for (int i = 0; i < 数字.Length; i++) { if (数字[i] != this._前回表示した数字[i]) { // 桁アニメーション開始 this._各桁のアニメ[i].落下開始(Global.Animation); // 1の位以外は、自分より上位の桁を順番に跳ねさせる。 if (3 > i) { for (int p = (i - 1); p >= 0; p--) { this._各桁のアニメ[p].跳ね開始(Global.Animation, 0.05 * ((i - 1) - p + 1)); } } } var 転送元矩形 = (this._コンボ文字の矩形リスト[数字[i].ToString()]) !; d2ddc.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(全体の中央位置) * preTrans; d2ddc.DrawBitmap( this._コンボ文字画像.Bitmap, (float)(this._各桁のアニメ[i].透明度?.Value ?? 1.0f), BitmapInterpolationMode.Linear, 転送元矩形.Value); 文字の位置.X += (転送元矩形.Value.Width + 文字間隔補正) * 画像矩形から表示矩形への拡大率.X; } d2ddc.Transform = preTrans; } //---------------- #endregion #region " Combo を描画。" //---------------- { var 転送元矩形 = this._コンボ文字の矩形リスト["Combo"] !; var 文字の位置 = new Vector2(0f, 130f); d2ddc.Transform = Matrix3x2.Scaling(画像矩形から表示矩形への拡大率) * Matrix3x2.Translation(文字の位置) * Matrix3x2.Scaling(全体の拡大率) * Matrix3x2.Translation(全体の中央位置) * preTrans; d2ddc.DrawBitmap( this._コンボ文字画像.Bitmap, 1.0f, BitmapInterpolationMode.Linear, 転送元矩形.Value); d2ddc.Transform = preTrans; } //---------------- #endregion // 保存 this._前回表示した値 = 現在の成績.Combo; this._前回表示した数字 = 数字; }
internal override void DoWork(DeviceContext context) { context.DrawBitmap(bitmap1, this.destination, 1.0f, BitmapInterpolationMode.NearestNeighbor); }