C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[18]: PictureBox で画像を動かす


(過去ログ 171 を表示中)

[トピック内 25 記事 (1 - 20 表示)]  << 0 | 1 >>

■98442 / inTopicNo.1)  PictureBox で画像を動かす
  
□投稿者/ 星は昴 (18回)-(2021/11/17(Wed) 00:34:34)

分類:[C#] 

Form で画像を動かすときは
  DoubleBuffered = true;
で画像のちらつきが抑えられるのですが PictureBox では DoubleBuffered はプロテクトにでもなっているのか、DoubleBuffered は設定できません。やはり裏画像を用意する必要があるのでしょうか?

引用返信 編集キー/
■98443 / inTopicNo.2)  Re[1]: PictureBox で画像を動かす
□投稿者/ 星は昴 (19回)-(2021/11/17(Wed) 08:15:27)
自己解決いたしました。
解決済み
引用返信 編集キー/
■98444 / inTopicNo.3)  Re[1]: PictureBox で画像を動かす
□投稿者/ KOZ (168回)-(2021/11/17(Wed) 08:31:16)
2021/11/17(Wed) 08:31:53 編集(投稿者)

No98442 (星は昴 さん) に返信
> で画像のちらつきが抑えられるのですが PictureBox では DoubleBuffered はプロテクトにでもなっているのか、DoubleBuffered は設定できません。

DoubleBuffered プロパティは、proteced なので派生クラスからしか参照/設定できません。

「Control.DoubleBuffered プロパティ」
https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.forms.control.doublebuffered?view=netframework-4.8

PictureBox は既定で True になっています。
解決済み
引用返信 編集キー/
■98448 / inTopicNo.4)  Re[2]: PictureBox で画像を動かす
□投稿者/ 星は昴 (20回)-(2021/11/17(Wed) 14:03:17)
 回答ありがとうございます。自己解決もしていませんでした(笑)。
 PictureBox(Pb) を貼り付けて画像を動かそうとしているのですが、以下のコードではチラツキが目立ちます。背景が黒でballが白だとよけいに際立ちます。何かいい方法はないでしょうか?

namespace SimpleAnimationBasic
{
  public partial class Form1 : Form
  {
    int NBallTop;
    int NBallLeft;
    int Nmag = 7;
    int Nx1 = 1;
    int Ny1 = 1;
    Bitmap NBackBmp;
    Bitmap NBallBmp;
    Bitmap NCanvas;

    public Form1()
    {
      InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
      //背景画像(1280×880)
      NBackBmp = new Bitmap(@"C:\Visual Studio 2019 Source\images\Messier51.png");
      //ボール画像
      NBallBmp = new Bitmap(@"C:\Visual Studio 2019 Source\images\whiteball.png");
      //ボール画像の透明色を黒にする
      NBallBmp.MakeTransparent(Color.Black);
      //合成するキャンバスを用意する
      NCanvas = new Bitmap(NBackBmp.Width, NBackBmp.Height);

      Timer1.Interval = 50;
      Timer1.Enabled = true;
    }

    private void Timer1_Tick(object sender, EventArgs e)
    {
      NBallLeft = NBallLeft + Nmag * Nx1;
      NBallTop = NBallTop + (int)(Nmag * Nmag * 0.1) * Ny1;

      if (NBallLeft+ NBallBmp.Width > 1280)
      {
        Nx1 = -1;
        NBallLeft = NBallLeft + Nmag * Nx1;
      }

      if (NBallLeft < 0)
      {
        Nx1 = 1;
        NBallLeft = NBallLeft + Nmag * Nx1;
      }

      if (NBallTop+ NBallBmp.Height > 880)
      {
        Ny1 = -1;
        NBallTop = NBallTop + (int)(Nmag * Nmag * 0.1) * Ny1;
      }

      if (NBallTop < 0)
      {
        Ny1 = 1;
        NBallTop = NBallTop + (int)(Nmag * Nmag * 0.1) * Ny1;
      }

      Graphics g = Graphics.FromImage(NCanvas);
      //背景画像を canvas に描画
      g.DrawImage(NBackBmp, 0, 0, NBackBmp.Width, NBackBmp.Height);
      //ボール画像を canvas に描画
      g.DrawImage(NBallBmp, NBallLeft, NBallTop, NBallBmp.Width, NBallBmp.Height);
      g.Dispose();
      Pb.Image = NCanvas;
    }
  }
}

引用返信 編集キー/
■98452 / inTopicNo.5)  Re[3]: PictureBox で画像を動かす
□投稿者/ PATIO (18回)-(2021/11/17(Wed) 15:00:36)
No98448 (星は昴 さん) に返信
>  回答ありがとうございます。自己解決もしていませんでした(笑)。
>  PictureBox(Pb) を貼り付けて画像を動かそうとしているのですが、以下のコードではチラツキが目立ちます。背景が黒でballが白だとよけいに際立ちます。何かいい方法はないでしょうか?

画面がちらつく原因は描画途中の状態が見えてしまうからです。
以前に高速描画をする為にフレームワークが行っている背景描画を止めて描画する方法を取った事があります。
今回のように背景を別の画像で塗りつぶしてしまうのであれば、コントロールの背景描画は不要になるので
これを止める事で少しは変わると思います。
つまり現状は、コントロールの背景描画、背景用の画像描画、前景用の画像描画となっていて
コントロールの背景描画が無駄に動いているのではないかという話です。
これをやっていた時はC#ではなくてC++でやっていたので今は状況が変わっている可能性がありますが、
高速化の基本は無駄な動作をしない事なので理屈にはあっていると思います。
あと、PictureBoxのダブルバッファリングが利いているのかどうかが良くわからないのですが、
結果的に背景画像の描画と前景画像の描画を画面に対して行っているので描画を行っている時に
同時に表示用の処理も動いてしまっているのではないかという気がします。
オフスクリーンのビットマップを用意してビットマップ上で描画を完結させてから
PictureBoxに描画するようにすれば、少しは違うかもしれません。

この掲示板の過去ログにおそらく似たようなやり取りがあったと思うので探してみても良いかもしれません。
引用返信 編集キー/
■98458 / inTopicNo.6)  Re[3]: PictureBox で画像を動かす
□投稿者/ 魔界の仮面弁士 (3219回)-(2021/11/17(Wed) 18:22:28)
No98448 (星は昴 さん) に返信
> 以下のコードではチラツキが目立ちます。背景が黒でballが白だとよけいに際立ちます。

PictureBox のダブルバッファリングを活かすのであれば、
Timer1 の Tick イベントでは、Pb.Invalidate(); を呼ぶだけにして、
実際の描画処理は、Pb の Paint イベントで、e.Graphics に対して行ってみてください。

現状のコードは NCanvas に対して描画していますが、
これは常時、Pb.Image によって参照されている状態なので、
オフスクリーンなしで直接描画すると、描画途中の状況が
表示されてしまい、ちらつきの要因となるのではないでしょうか。


もし、CreateGraphics や Graphics.FromImage を使いつつも、
バッファリングされたグラフィックスを手動で描画したいのであれば、
BufferedGraphics クラスを通じて描画処理を記述し、
全ての要素を描き終わってから、Render メソッドで一括反映するようにします。
https://docs.microsoft.com/ja-jp/dotnet/desktop/winforms/advanced/how-to-manually-render-buffered-graphics
引用返信 編集キー/
■98459 / inTopicNo.7)  Re[4]: PictureBox で画像を動かす
□投稿者/ 星は昴 (21回)-(2021/11/17(Wed) 19:11:01)
No98458 (魔界の仮面弁士 さん) に返信

 回答まことにありがとうございます。

> PictureBox のダブルバッファリングを活かすのであれば、
> Timer1 の Tick イベントでは、Pb.Invalidate(); を呼ぶだけにして、
> 実際の描画処理は、Pb の Paint イベントで、e.Graphics に対して行ってみてください。

private void Timer1_Tick(object sender, EventArgs e)
{
  NBallLeft = NBallLeft + Nmag * Nx1;
  NBallTop = NBallTop + (int)(Nmag * Nmag * 0.1) * Ny1;
  ・・・・・略
  Invalidate();
}

private void Pb_Paint(object sender, PaintEventArgs e)
{
  Graphics g = Graphics.FromImage(NCanvas);
  g.DrawImage(NBackBmp, 0, 0, NBackBmp.Width, NBackBmp.Height);
  g.DrawImage(NBallBmp, NBallLeft, NBallTop, NBallBmp.Width, NBallBmp.Height);
  g.Dispose();
  //Pb.Image = NCanvas;

  e.Graphics.DrawImage(NCanvas, 0, 0, NCanvas.Width, NCanvas.Height);
}

とやったのですが、ボールが左隅に張り付いたまま動きません。
引用返信 編集キー/
■98460 / inTopicNo.8)  Re[5]: PictureBox で画像を動かす
□投稿者/ 魔界の仮面弁士 (3220回)-(2021/11/17(Wed) 19:22:27)
No98459 (星は昴 さん) に返信
> とやったのですが、ボールが左隅に張り付いたまま動きません。

e.Graphics に対して直接描くのではなく、
NCanvas に描いてからそれを転写する手法にしたのですね。

ではその NCanvas のインスタンスは、どのように管理されていますか?

e.Graphics の方は、Paint イベントに入る前に毎回クリアされていますが、
NCanvas のインスタンスは使いまわされるので、
以前描いたボールが、消されずに残っているのではないか…と予想してみます。
引用返信 編集キー/
■98461 / inTopicNo.9)  Re[6]: PictureBox で画像を動かす
□投稿者/ 星は昴 (22回)-(2021/11/17(Wed) 20:03:36)
No98460 (魔界の仮面弁士 さん) に返信

 うーん。動かないですね(笑)。
> e.Graphics の方は、Paint イベントに入る前に毎回クリアされていますが、
ということなら

private void Pb_Paint(object sender, PaintEventArgs e)
{
  //背景
  e.Graphics.DrawImage(NBackBmp, 0, 0, NBackBmp.Width, NBackBmp.Height);
  //ボール
  e.Graphics.DrawImage(NBallBmp, NBallLeft, NBallTop, NBallBmp.Width, NBallBmp.Height);
}

でいけると思ったのですが、やはりボールは左上に貼り付いたままです。
引用返信 編集キー/
■98462 / inTopicNo.10)  Re[5]: PictureBox で画像を動かす
□投稿者/ KOZ (171回)-(2021/11/17(Wed) 20:10:01)
No98459 (星は昴 さん) に返信
> private void Timer1_Tick(object sender, EventArgs e)
> {
>   NBallLeft = NBallLeft + Nmag * Nx1;
>   NBallTop = NBallTop + (int)(Nmag * Nmag * 0.1) * Ny1;
>   ・・・・・略
>   Invalidate();
> }

Form の Invalidate を呼び出してますよ。

引用返信 編集キー/
■98463 / inTopicNo.11)  Re[6]: PictureBox で画像を動かす
□投稿者/ 星は昴 (23回)-(2021/11/17(Wed) 20:39:16)
No98462 (KOZ さん) に返信
>
> Form の Invalidate を呼び出してますよ。
>

 でした(^O^)。失礼いたしました。

 が、しかし・・・・やはりちらつきますねえ。最初とほとんど変わらないです。こんなものなのかなあ。

 スクリーンセーバの「バブル」のなんかとてもなめらかなのに。

引用返信 編集キー/
■98469 / inTopicNo.12)  Re[7]: PictureBox で画像を動かす
□投稿者/ KOZ (172回)-(2021/11/18(Thu) 09:15:11)
No98463 (星は昴 さん) に返信
>  が、しかし・・・・やはりちらつきますねえ。最初とほとんど変わらないです。こんなものなのかなあ。
>  スクリーンセーバの「バブル」のなんかとてもなめらかなのに。

MakeTransparent で透過画像を作るのでなく、最初から用意しておくとか
DrawEllipse で円を描くとどうでしょうね。
引用返信 編集キー/
■98472 / inTopicNo.13)  Re[8]: PictureBox で画像を動かす
□投稿者/ PATIO (20回)-(2021/11/18(Thu) 09:47:16)
No98469 (KOZ さん) に返信
> ■No98463 (星は昴 さん) に返信
>> が、しかし・・・・やはりちらつきますねえ。最初とほとんど変わらないです。こんなものなのかなあ。
>> スクリーンセーバの「バブル」のなんかとてもなめらかなのに。
>
> MakeTransparent で透過画像を作るのでなく、最初から用意しておくとか
> DrawEllipse で円を描くとどうでしょうね。

ダブルバッファリングが生きている時は背景描画は止まった状態になっているのでしたっけ?
自前でオフスクリーン描画をしていた口なのでその辺が良くわからないのですけれど。
ダブルバッファリングの設定と連動しているなら余計なお世話になりますね。
ちらつくというのは結局、ビットマップの描画を行う前に背景色による塗りつぶしが動いてしまっているからでは
ないかと思うのですが、違うでしょうか。
もしかしてボールの描画部分がちらちらしていますか?
全体がフラッシュしているような感じではなくて。
引用返信 編集キー/
■98475 / inTopicNo.14)  Re[9]: PictureBox で画像を動かす
□投稿者/ 星は昴 (24回)-(2021/11/18(Thu) 11:06:07)
No98472 (PATIO さん) に返信
 回答ありがとうございます。

> もしかしてボールの描画部分がちらちらしていますか?

 その通りです。

> 自前でオフスクリーン描画をしていた口なのでその辺が良くわからないのですけれど。
 オフスクリーン描画、どうやるのでしょうか?

 今の Delphi はまったく知らないのですが、20 年以上前の Delphi5 には、PictureBox に相当する、PaintBox というのがあって、その OnPaint に
   FOffBmp := TBitmap.Create;      //オフスクリーン
   FDrawSinX2(FOffBmp.Canvas);
   PaintBox1.Canvas.Draw(0, 0, FOffBmp); //画面に転送
   FOffBmp.Free;
とのように書くだけで、バッチリだったのですが。

private void Pb_Paint(object sender, PaintEventArgs e)
{
  //e.Graphics は、Paint イベントに入る前に毎回クリアされるらしい
  Bitmap offbmp = new Bitmap(NBackBmp.Width, NBackBmp.Height);
  Graphics g = Graphics.FromImage(offbmp);
  g.DrawImage(NBackBmp, 0, 0, NBackBmp.Width, NBackBmp.Height);
  g.DrawImage(NBallBmp, NBallLeft, NBallTop, NBallBmp.Width, NBallBmp.Height);
  e.Graphics.DrawImage(offbmp, 0, 0, NBackBmp.Width, NBackBmp.Height);
  g.Dispose();
  offbmp.Dispose();
}

とかやってもまったくいっしょです。

引用返信 編集キー/
■98476 / inTopicNo.15)  Re[10]: PictureBox で画像を動かす
□投稿者/ 魔界の仮面弁士 (3221回)-(2021/11/18(Thu) 13:01:27)
No98475 (星は昴 さん) に返信
> //e.Graphics は、Paint イベントに入る前に毎回クリアされるらしい


NBackBmp や NBallBmp の内容にもよりますが、たとえば、
NBackBmp を BackgroundImage か Picture に入れておいて、

private void Pb_Paint(object sender, PaintEventArgs e)
{
  e.Graphics.DrawImage(NBallBmp, NBallLeft, NBallTop, NBallBmp.Width, NBallBmp.Height);
}

だけでは駄目でしょうか。
引用返信 編集キー/
■98478 / inTopicNo.16)  Re[11]: PictureBox で画像を動かす
□投稿者/ 星は昴 (25回)-(2021/11/18(Thu) 14:06:24)
No98476 (魔界の仮面弁士 さん) に返信
> NBackBmp を BackgroundImage か Picture に入れておいて、
>
> private void Pb_Paint(object sender, PaintEventArgs e)
> {
>   e.Graphics.DrawImage(NBallBmp, NBallLeft, NBallTop, NBallBmp.Width, NBallBmp.Height);
> }
>
> だけでは駄目でしょうか。

 Form1_Load で

 Pb.BackgroundImage = NBackBmp;

として、実行しましたがダメです(^O^)。

> Picture に入れておいて、
 この Picture って何でしょうか?

引用返信 編集キー/
■98479 / inTopicNo.17)  Re[10]: PictureBox で画像を動かす
□投稿者/ PATIO (22回)-(2021/11/18(Thu) 14:14:53)
No98475 (星は昴 さん) に返信
> ■No98472 (PATIO さん) に返信
>  回答ありがとうございます。
>
>>もしかしてボールの描画部分がちらちらしていますか?
>
>  その通りです。
>
>>自前でオフスクリーン描画をしていた口なのでその辺が良くわからないのですけれど。
>  オフスクリーン描画、どうやるのでしょうか?
>
>  今の Delphi はまったく知らないのですが、20 年以上前の Delphi5 には、PictureBox に相当する、PaintBox というのがあって、その OnPaint に
>    FOffBmp := TBitmap.Create;      //オフスクリーン
>    FDrawSinX2(FOffBmp.Canvas);
>    PaintBox1.Canvas.Draw(0, 0, FOffBmp); //画面に転送
>    FOffBmp.Free;
> とのように書くだけで、バッチリだったのですが。
>
> private void Pb_Paint(object sender, PaintEventArgs e)
> {
>   //e.Graphics は、Paint イベントに入る前に毎回クリアされるらしい
>   Bitmap offbmp = new Bitmap(NBackBmp.Width, NBackBmp.Height);
>   Graphics g = Graphics.FromImage(offbmp);
>   g.DrawImage(NBackBmp, 0, 0, NBackBmp.Width, NBackBmp.Height);
>   g.DrawImage(NBallBmp, NBallLeft, NBallTop, NBallBmp.Width, NBallBmp.Height);
>   e.Graphics.DrawImage(offbmp, 0, 0, NBackBmp.Width, NBackBmp.Height);
>   g.Dispose();
>   offbmp.Dispose();
> }
>
> とかやってもまったくいっしょです。

オフスクリーン描画と言っているのは画面のコンテキストと互換性があるビットマップを作成して
そのビットマップ上に表示対象の内容を全て描画しておいてそのビットマップを画面に転送する方法です。
星は昴さんが書かれている方法と同じだと思います。
で、自前でこれをやる時に画面に対して無効化を行うとフレームワーク内で一旦背景色で塗りつぶすという
処理が自動で動いてしまうので、一旦背景色で塗りつぶしてからビットマップを転送という流れになって
画面がちらついてしまうのでフレームワークの該当処理を無効化してちらつきを抑えると言う事をやってました。

背景部分がちらつくのではなく、ボールの部分がちらついてる場合、
オフスクリーンのビットマップ上では指定した位置にボールがのった絵が出来上がっていると思いますので
ちらつきは現状のビットマップから新しいビットマップに書き換える際に発生していると思います。
単純に書き換える場合、移動したボールとの差分の部分だけが変化するはずなのでその描画のみが行われているなら
ちらつかないと思います。ちらつくというのは今回のケースで言えば白⇒黒⇒白となったり、黒⇒白⇒黒となる場合
なので何か余計な描画が入っているとしか思えません。
あと、自分がやっていたのは透過描画は使わずに自前でマスク用のビットマップを作ってやっていたくらいですね。
PictureBoxの描画モードとかも関係あるかもしれません。
引用返信 編集キー/
■98480 / inTopicNo.18)  Re[12]: PictureBox で画像を動かす
□投稿者/ 星は昴 (26回)-(2021/11/18(Thu) 15:31:18)
> 背景部分がちらつくのではなく、ボールの部分がちらついてる場合、
> オフスクリーンのビットマップ上では指定した位置にボールがのった絵が出来上がっていると思いますので
> ちらつきは現状のビットマップから新しいビットマップに書き換える際に発生していると思います。
> 単純に書き換える場合、移動したボールとの差分の部分だけが変化するはずなのでその描画のみが行われているなら
> ちらつかないと思います。ちらつくというのは今回のケースで言えば白⇒黒⇒白となったり、黒⇒白⇒黒となる場合
> なので何か余計な描画が入っているとしか思えません。
 うーん、なにやらメンドーな話になりましたね。
 ま、いまはC#の基本をマスターしているところですし、このスレもいささか伸びすぎました。とりあえずこの話題はいったん打ち切りたいと思います。
 回答を寄せてくださった方々、本当にありがとうございました。

解決済み
引用返信 編集キー/
■98483 / inTopicNo.19)  Re[12]: PictureBox で画像を動かす
□投稿者/ 魔界の仮面弁士 (3223回)-(2021/11/18(Thu) 18:07:47)
2021/11/19(Fri) 07:54:15 編集(投稿者)

No98478 (星は昴 さん) に返信
>> NBackBmp を BackgroundImage か Picture に入れておいて、
>  この Picture って何でしょうか?

失礼しました。
「BackgroundImage プロパティか Image プロパティ」の間違いです。


> として、実行しましたがダメです(^O^)。

「ダメ」というのは、『画像のちらつき』なのですよね?

下記のような実験コードを書いてみましたが、
DoubleBuffered = false な Form に描画する時のような
明確なちらつきを確認できませんでした…。


public partial class Form1 : Form
{
  public Form1()
  {
    InitializeComponent();
    pictureBox1.BackgroundImage = 適当な画像;
    ball = Icon.ToBitmap(); // とりあえず標準のアイコンで
    timer1.Interval = 16;
    timer1.Start();
  }

  private void pictureBox1_Paint(object sender, PaintEventArgs e)
  {
    e.Graphics.DrawImage(ball, left, 60);
  }

  int left = 0;
  int offset = 3;
  Image ball;
  private void timer1_Tick(object sender, EventArgs e)
  {
    left += offset;
    if (left + ball.Width >= pictureBox1.Width)
    {
      left = pictureBox1.Width - ball.Width;
      offset = -offset;
    }
    else if (left <= 0)
    {
      left = 0;
      offset = -offset;
    }
    pictureBox1.Invalidate();
  }
}
解決済み
引用返信 編集キー/
■98489 / inTopicNo.20)  Re[13]: PictureBox で画像を動かす
 
□投稿者/ KOZ (173回)-(2021/11/19(Fri) 00:12:29)
2021/11/19(Fri) 02:31:31 編集(投稿者)
No98483 (魔界の仮面弁士 さん) に返信

なんか面白そうなのでボール画像を作って 20 個ほど動かしてみました。
ちょっとカクつくかなーという気がしますが、ちらつきはしないと思います。

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

public partial class Form2 : Form
{
    public Form2()
    {
        InitializeComponent();
    }

    Bitmap ballBmp;
    List<CBall> balls;

    private void Form2_Load(object sender, EventArgs e)
    {
        pictureBox1.BackgroundImage = new Bitmap(@"D:\TEST\back.jpg");
        ballBmp = new Bitmap(300, 300);
        using (var g = Graphics.FromImage(ballBmp))
        {
            g.Clear(Color.Black);
            g.FillEllipse(Brushes.Brown, new Rectangle(1, 1, ballBmp.Width - 2, ballBmp.Height - 2));
            g.FillEllipse(Brushes.MistyRose, new Rectangle(4, 4, ballBmp.Width - 8, ballBmp.Height - 8));

            using (var titleFont = new Font("MS UI Gothic", 40, FontStyle.Bold))
            {
                const string title = "\u308F\u3093\u304F\u307E\u540C\u76DF";
                var sz = g.MeasureString(title, titleFont);
                var location = new Point((int)((ballBmp.Width - sz.Width) / 2), (int)((ballBmp.Height - sz.Height) / 2));
                g.DrawString(title, titleFont, Brushes.Brown, location);
            }
        }
        ballBmp.MakeTransparent(Color.Black);

        balls = new List<CBall>();
        for (int i = 0; i < 20; i++)
        {
            CBall ball = new CBall(ballBmp, ClientSize);
            balls.Add(ball);
        }

        timer1.Interval = 16;
        timer1.Enabled = true;
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        pictureBox1.Invalidate();
    }

    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        foreach (var ball in balls)
        {
            ball.Draw(e.Graphics, pictureBox1.ClientRectangle);
        }
    }

    class CBall
    {
        readonly Bitmap ballBmp;
        readonly Size size;
        readonly int mag;
        int left, top, dx, dy;

        const int MinBallSize = 100;
        const int MaxBallSize = 300;
        static Random random = new Random();

        public CBall(Bitmap bmp, Size clientSize)
        {
            ballBmp = bmp;
            int height = random.Next(MinBallSize, MaxBallSize);
            size = new Size(height, height);
            mag = random.Next(10, 20);
            left = random.Next(10, clientSize.Width);
            top = random.Next(10, clientSize.Height);
            dx = random.Next(0, 2) * 2 - 1;
            dy = random.Next(0, 2) * 2 - 1;
        }

        private Rectangle NextRectangle(Rectangle drawArea)
        {
            left += mag * dx;
            top += (int)(mag * mag * 0.1) * dy;

            if (left + size.Width > drawArea.Right)
            {
                dx = -1 * Math.Abs(dx);
                left += mag * dx;
            }
            if (left < drawArea.Left)
            {
                dx = Math.Abs(dx);
                left += mag * dx;
            }
            if (top + size.Height > drawArea.Bottom)
            {
                dy = -1 * Math.Abs(dy);
                top += (int)(mag * mag * 0.1) * dy;
            }
            if (top < drawArea.Top)
            {
                dy = Math.Abs(dy);
                top += (int)(mag * mag * 0.1) * dy;
            }
            return new Rectangle(left, top, size.Width, size.Height);
        }

        public void Draw(Graphics graphics, Rectangle drawArea)
        {
            var rect = NextRectangle(drawArea);
            graphics.DrawImage(ballBmp, rect);
        }
    }
}

解決済み
引用返信 編集キー/

次の20件>
トピック内ページ移動 / << 0 | 1 >>

管理者用

- Child Tree -