質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

解決済

2回答

8916閲覧

画像がちらつく

unirou2

総合スコア37

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

0グッド

0クリップ

投稿2016/05/22 14:30

ゲームを作っています。
PictureBoxの中に敵キャラの画像と自分が操作する画像を表示させています。
敵キャラの画像は0.1秒につき1回動くようにしてるのですが、
自分が操作するキャラを動かし続けると、敵キャラが映らなくなってしまいます。

//using System.Drawing; //描画先とするImageオブジェクトを作成する Bitmap canvas = new Bitmap(PictureBox1.Width, PictureBox1.Height); //ImageオブジェクトのGraphicsオブジェクトを作成する Graphics g = Graphics.FromImage(canvas); //画像ファイルを読み込んで、Imageオブジェクトとして取得する Image img = Image.FromFile(@"C:\test\1.bmp"); //画像をcanvasの座標(20, 10)の位置に描画する g.DrawImage(img, 20, 10, img.Width, img.Height); //Imageオブジェクトのリソースを解放する img.Dispose(); //Graphicsオブジェクトのリソースを解放する g.Dispose(); //PictureBox1に表示する PictureBox1.Image = canvas;

【引用】
http://dobon.net/vb/dotnet/graphics/drawimage.html

[描画先とするImageオブジェクトを作成する] のところの
canvas を2つ作って 敵キャラと自キャラを分けています。


同じ canvas 内だと、画像はちらつかないのですが、
「追加情報:オブジェクトは現在他の場所で使用されています。」
というエラーが出たのでうまくできませんでした。


また、【C#におけるダブルバッファリング(画像表示の場合)】
http://home.a00.itscom.net/hatada/csharp/image/doublebuffering01.html
も試してみたのですが、改善しません。


自分が操作するキャラを動かすと、敵キャラが映らなくなってしまうこの現象の
なにか上手な解決策はありませんか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

また、【C#におけるダブルバッファリング(画像表示の場合)】
http://home.a00.itscom.net/hatada/csharp/image/doublebuffering01.html
も試してみたのですが、改善しません。

こんにちわ。更新時のチラつきは、たいていこの方法で解決できるのですが、
提示されたソースからは読み取れませんが、恐らく画像を更新している部分に問題があるのだと思います。

まず、画像の描画などは PictureBoxの Paintイベントのメソッド内に書きましょう。
そしてTimerクラスなどで、キー入力や座標移動などの処理をしてPictureBoxクラスのInvalidateメソッドを呼べば、書き換わります。
このとき、上記のDoubleBufferdがtrueだと、効果が出ると思います。

投稿2016/05/24 09:00

mugicya

総合スコア1046

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

unirou2

2016/05/24 16:18

回答ありがとうございます。独学かつ初心者なので言葉足らずで何をしてるか分かりにくい質問をしてしまい申し訳ありません。 System.Threading.Timerを使っていたことが、DoubleBufferdが適用されなかった理由なのかなと思いました。 【C# の Timer 種類別 特徴 と 使い方】 http://garafu.blogspot.jp/2015/01/c-timer.html 書き直してみたのですが、Timerは作動せず、Paintイベントも発生してない気がします。なにか気付く点はありませんか? int ax = 60, ay = 60;//敵キャラ座標 int[,] Danjon = new int[681, 681];//ダンジョンのマップ Bitmap canvas2 = new Bitmap(681, 681); Graphics g, g2, g3; Random rnd = new Random(); void Anemy() // ランダム { // タイマー生成 System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer(); timer.Interval = 1000; // タイマーを開始 timer.Start(); Image img0 = Image.FromFile(@".\images\0.bmp");//床の画像 Image img4 = Image.FromFile(@".\images\4.bmp");//敵キャラの画像 for (int n = 0; n < 1000; n++) { g2.DrawImage(img0, ax, ay, 20, 20);//床の画像を表示し、敵キャラを消す int af = rnd.Next(0, 4); switch (af) { case 0: if (Danjon[ax, ay + 20] == 0) // 0なら障害物なしで移動できる { ay += 20; } break; case 1: if (Danjon[ax, ay - 20] == 0) { ay -= 20; } break; case 2: if (Danjon[ax - 20, ay] == 0) { ax -= 20; } break; case 3: if (Danjon[ax + 20, ay] == 0) { ax += 20; } break; } g2.DrawImage(img4, ax, ay, 20, 20); pictureBox2.Invalidate(); // Imageオブジェクトのリソースを解放する // g2.Dispose(); } // タイマーを停止 timer.Stop(); } private void pictureBox2_Paint(object sender, PaintEventArgs e) { g2 = Graphics.FromImage(canvas2); Image img4 = Image.FromFile(@".\images\4.bmp"); g2.DrawImage(img4, ax, ay, 20, 20); pictureBox2.Image = canvas2; }
guest

0

ベストアンサー

こんばんわ。

そもそも、Timerクラスの使用法が怪しいですね。

C#

1namespace sample 2{ 3 public partial class Form1 : Form 4 { 5 Timer timer1 { get; set; } 6 7 Image img0 { get; set; } 8 Image img1 { get; set; } 9 10 PictureBox pictureBox1 { get; set; } 11 12 public Form1() 13 { 14 InitializeComponent(); 15 16 img0 = Image.FromFile(@".\images\0.bmp");//床の画像 17 img1 = Image.FromFile(@".\images\4.bmp");//敵キャラの画像 18 19 // このへん適当です 20 pictureBox1 = new PictureBox(); 21 pictureBox1.Paint += pictureBox1_Paint; 22 23 timer1 = new Timer(); 24 timer1.Interval = 1000; 25 timer1.Tick += timer1_Tick; // タイマー処理イベントメソッドの登録 26 27 timer1.Enabled = true; // Timerクラスは、デフォでは Falseになっている 28 timer1.Start(); 29 } 30 31 /// <summary> 32 /// タイマー処理 33 /// </summary> 34 void timer1_Tick(object sender, EventArgs e) 35 { 36 // ここにキー入力やキャラの移動のタイマー処理を書く 37 // 描画処理はここには書かない。無限ループするような処理は書かない。 38 39 pictureBox1.Invalidate(); 40 } 41 42 /// <summary> 43 /// 描画処理 44 /// </summary> 45 private void pictureBox1_Paint(object sender, PaintEventArgs e) 46 { 47 // ここに描画処理を書く 48 // キャラの移動結果などを見て描画するデータを作成して描画する。 49 } 50 51 /// <summary> 52 /// フォームクローズ時の処理 53 /// </summary> 54 private void Form_FormClosing(object sender, FormClosingEventArgs e) 55 { 56 // 解放処理などを書く 57 timer1.Stop(); 58 timer1.Dispose(); 59 60 img0.Dispose(); 61 img1.Dispose(); 62 63 pictureBox1.Dispose(); 64 } 65 } 66} 67

だいぶ手を加える事になるかと思いますが、前回の回答はこんな感じです。

投稿2016/05/24 17:25

mugicya

総合スコア1046

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

unirou2

2016/05/28 14:46 編集

こんばんは 動かすことができないのですが、何か気付くことありませんか? 何度も申し訳ないのですが、よろしくお願いします。 ``` namespace sample { public partial class Form1 : Form { Timer timer1 { get; set; } Image img0 { get; set; } Image img1 { get; set; } Bitmap canvas; Graphics g; PictureBox pictureBox1 { get; set; } public Form1() { InitializeComponent(); img0 = Image.FromFile(@".\images\0.bmp");//床の画像 img1 = Image.FromFile(@".\images\4.bmp");//敵キャラの画像 // このへん適当です pictureBox1 = new PictureBox(); pictureBox1.Paint += pictureBox1_Paint; timer1 = new Timer(); timer1.Interval = 1000; timer1.Tick += timer1_Tick; // タイマー処理イベントメソッドの登録 timer1.Enabled = true; // Timerクラスは、デフォでは Falseになっている timer1.Start(); } /// <summary> /// タイマー処理 /// </summary> void timer1_Tick(object sender, EventArgs e) { int af = rnd.Next(0, 4); switch (af) { case 0: if (Danjon[ax, ay + 20] == 0) { ay += 20; } break; case 1: if (Danjon[ax, ay - 20] == 0) { ay -= 20; } break; case 2: if (Danjon[ax - 20, ay] == 0) { ax -= 20; } break; case 3: if (Danjon[ax + 20, ay] == 0) { ax += 20; } break; } pictureBox1.Invalidate(); } /// <summary> /// 描画処理 /// </summary> private void pictureBox1_Paint(object sender, PaintEventArgs e) { g = Graphics.FromImage(canvas); g.DrawImage(img4, ax, ay, 20, 20); pictureBox1.Image = canvas; } /// <summary> /// フォームクローズ時の処理 /// </summary> private void Form_FormClosing(object sender, FormClosingEventArgs e) { // 解放処理などを書く timer1.Stop(); timer1.Dispose(); img0.Dispose(); img1.Dispose(); pictureBox1.Dispose(); } } } ```
mugicya

2016/05/30 18:46

私の提示したコードが理解不能であるなら、 ちょっと知識不足かもしれません。 各クラスの使用方法は、Microsoftのヘルプでもでてきますので、 自分で動くように頑張ってみてください。 その上で、判らない事があれば、また質問して下さいね。
unirou2

2016/05/31 12:50

厚かましくコードを載せてスイマセン。 自分の頭で考えてから出直してきます。 また機会があればお願いします。
IkedaIori

2016/05/31 14:01

```csharp private void pictureBox1_Paint(object sender, PaintEventArgs e) { g = e.Graphics; g.DrawImage(img4, ax, ay, 20, 20); } ``` のほうがいいと思います
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問