DOBON.NET DOBON.NETプログラミング掲示板過去ログ

ワールド変換行列を用いた画像移動

環境/言語:[XP]
分類:[.NET]

タイトル通りなのですが、どうにも上手く動きません。
理想はスムーズに画像を上下左右に動かすことです。
コードはTipsにあるものをそのまま用いたのですが……

[VB.NET]
'PictureBox1のGraphicsオブジェクトを取得
Dim g As Graphics = PictureBox1.CreateGraphics()
'画像を読み込む
Dim img As Image = Image.FromFile("test.gif")
'普通に画像を描画
g.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height))
'ワールド変換行列を単位行列にリセット
g.ResetTransform()
'ワールド変換行列を下に平行移動する
g.TranslateTransform(0, img.Height + 10)
'画像を描画
g.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height))
'リソースを開放する
img.Dispose()
g.Dispose()

これだとチラつき(残像?)のようなものが残る上に移動もしてくれません。
自分の知識ではどこがどうなっているのかすらわからないのが現状です……。
どなたか教えていただけると助かります。
■No27925に返信(家財さんの記事)

ご自身が書いているコードが何をしているか考えてください。

> 'PictureBox1のGraphicsオブジェクトを取得
> Dim g As Graphics = PictureBox1.CreateGraphics()
(中略)
> '普通に画像を描画
> g.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height))

この時点で移動前と言われている場所に絵が描かれています。

> 'ワールド変換行列を下に平行移動する
> g.TranslateTransform(0, img.Height + 10)
> '画像を描画
> g.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height))

ここでさらに 10 ピクセル移動した先に絵を上書きしています。
従って、元の座標と 10 ピクセル移動した先の座標の 2 箇所で描いた状態で画面に表示されるでしょう。
残像ではなく、自分で重ねて二つ描いたに過ぎません。


> これだとチラつき(残像?)のようなものが残る上に移動もしてくれません。

移動していく様子を見せるのであれば、タイマーを使うなど一定時間ごとに処理をすすめる仕組みを使う必要があります。
また、必要でない限り、CreateGraphics メソッドを使うのではなく、Invalidate メソッドと Paint イベントを組み合わせてください。

(参考)作り方の一例
1.Paint イベントで最初の位置に描画する。
2.Timer の Tick イベントで現在の座標を表すメンバー変数を +10 し、Invalidate メソッドを呼ぶ。
3.Paint イベントでメンバー変数を参照して描画する。
4.2 と 3 の繰り返し。
回答ありがとうございます。
ただ、ど素人の私にはいまいちよく分からず……。
検索エンンジや過去ログなども調べてみても
解決には繋がりませんでした。

できれば、作り方の一例の具体的なコードを
お教えいただければ……。
■No27929に返信(家財さんの記事)
> できれば、作り方の一例の具体的なコードを
> お教えいただければ……。

このあたりの内容も一度お読み頂いていますでしょうか。
(「安易な質問」→「丸投げした投稿」)
http://dobon.net/vb/bbs/index.html#irresponsible

私が先の投稿で書いた「一例」もわからない状態であれば、まず、一つずつやり方を模索してください。

1.一定時間ごとに何らかの処理を実現する。
 たとえば、1 秒ごとにラベルに現在時刻(DateTime.Now)を表示するなど。(タイマーを使う)

2.前回の状態を保持し、それを元の処理を実現する。
 たとえば、ボタンを押した回数をラベルに表示するとして、メンバー変数にクリック回数を覚えておくなど。(メンバー変数を使う)

3.Paint イベントで画像を描くことを実現する。
 たとえば、今回の DrawImage のコードを Paint イベントに移植して、e.Graphics に対して処理する。こうすることでフォームがほかのウィンドウによって上書きされても、絵が消えなくなる。

4.定期的にイベントを起こし、メンバー変数に加減算し、Invalidate メソッドを呼び、Paint イベントで描画する。
 最終形です。1 〜 3 で得た知識・経験を元に組み合わせができるとは思います。
> このあたりの内容も一度お読み頂いていますでしょうか。
> (「安易な質問」→「丸投げした投稿」)
> http://dobon.net/vb/bbs/index.html#irresponsible

はい、投稿の度に読み返しています。
ただ、本当に知識不足で自分が分かっていることさえ、自信がもてません。
四則演算が出来ないのに方程式を解いてるような独学知識なので……。

ただ、決して安易に質問した訳ではないことは理解してもらいたいです。
先述の通り、検索エンジン・過去ログ、また手持ちの.NETの専門書も参考にして
それでもわからなかったので……。

ひとつずつ示して下さって本当にありがとうございます。
まだ自分の知識では覚束無いところもありそうですが、何とかしてみます。

未だ解決には至っていないのでチェックはしません。
こういったことは私から書くべきではないかもしれません。
家財さんが今後、力をつけていく、自力で解決できるようになっていくためにも、一つの考え方としてお読み頂ければと思います。

■No27932に返信(家財さんの記事)
> ただ、決して安易に質問した訳ではないことは理解してもらいたいです。

ルールにおける「安易な質問」の定義については私がどうこう言う立場にありませんので何ともいいかねます。

以下は私見ですが、「作り方の一例の具体的なコードをお教えいただければ」というお願いは「実際にコードを書いてください」というお願いと同じではないでしょうか?
安易に出した依頼ではないにしても、このような丸投げ行為や、誰かにコードを書くという仕事をさせる行為はこの場所に限らずあまり良いこととは言えません。
(受け取り方は人によりますが)

> 先述の通り、検索エンジン・過去ログ、また手持ちの.NETの専門書も参考にして
> それでもわからなかったので……。

やりたいことを思い浮かべるとして、それをそのまま探しても見つかりません。
実現するためにはどういったことが必要か切り分けていき、個々に問題を解決していくことが今後求められると思います。

最初から問題の切り分けを求めることも酷かもしれません。せめて、調べた・考えた過程を提示するなど、努力した部分を具体的に見せてほしいと思います。
どういったキーワードで検索したのか?どういった書籍でどのようなやり方で探したのか?そういった過程を見せるだけでも心証は違いますし、調べ方に問題があればそれについてアドバイスをもらえて、今後の改善につながる可能性もありますよね。
何度も申し訳ありません。感謝しています。
ただ、やはり今の私の知識では解けなかったので
ルールにあるとおり「解決済み」にチェックはできません。

いつか分かるときが来たら改めて返信をしようかと思います。
■No27932に返信(家財さんの記事)

> 四則演算が出来ないのに方程式を解いてるような独学知識なので……。
>
四則演算を覚えなければ方程式解くのは無理でしょ?

まず難しいことはやらないでいろいろ基本的なことを覚えた方が良いのでは
ないでしょうか?
Timer, Paintイベントが提案されているのにそれを試してみないのでは話が
先に進みません。Timer,Paintイベントが分からなければTimer,Paintイベント
ってなんなのか調べて分からないところを聞くとよいのではないでしょうか?
回答ありがとうございます。
やはり、基礎がなっていないということを実感しました。
今まではどこぞで拾ってきたサンプルコードをあれこれ弄って
「ここをこう変えたらどう動くだろう」
「ここをこうしたらうまいこと動くかもしれない」
というやり方で、四則演算という名の基礎を余所から借りて
無理やりコードを組んできたようなものなので……。

一度、独学で身についてしまった知識を捨てて
一からやり直してみたいと思います。
過去の質問を見る限り、色んなサイトのTipsを組み合わせただけで簡単なゲームを作りたいのでしょうか?
(時期的にゲーム系専門学校の卒業制作をやっつけでやってる様な印象ですがw)

まあ勉強方法のお手伝い程度ですが、以下の事を実践しましょう。

1.コメントだけ読め

'PictureBox1のGraphicsオブジェクトを取得
'画像を読み込む
'普通に画像を描画
'ワールド変換行列を単位行列にリセット
'ワールド変換行列を下に平行移動する
'画像を描画
'リソースを開放する

こちらのTipsは素晴らしい事に、ほぼ1行毎にコメントがあります。
『画像を描画』って二箇所にあり、『画像をクリア』って意味合いの言葉は何所にも無いですよね?
だったら画像は二箇所に表示されて当然です。


2.全体を理解できないソースを丸ごとコピペするな

Tipsの上から1行ずつコピペし、実行していきましょう。
コメントとコードを付き合わせて、各行での処理結果がどうなっているのかを確認しましょう。

まずこの2点は『最低限』やった上で質問に来ましょう。
『Tipsをコピペした。私の理想どおりにならない。サンプルを提示してくれ』ではお話になりませんよw
回答ありがとうございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板