FormにImageが触れているかを判定するには?


ぺりー  2008-11-13 19:32:19  No: 101286

実習で迷路を作っています。
フォームにランダムに描いた迷路でImageを動かし
迷路の壁の中だけを動くようにしたいと考えています。

Private Sub form_KeyDown(KeyCode As Integer, Shift As Integer)
  Select Case KeyCode
   Case 39
    Image1.Move Image1.Left + 5, Image1.Top
   Case 40
    Image1.Move Image1.Left, Image1.Top + 5
   Case 37
    Image1.Move Image1.Left - 5, Image1.Top
   Case 38
    Image1.Move Image1.Left, Image1.Top - 5
   End Select
End Sub

この操作を、イメージが壁に触れているときに無効にしたいのですが
FormにLineメソッドで引いたラインと、中を動き回るImageが
触れているかどうかを判定するにはどうしたらよいでしょうか。
お教えいただければ幸いです。


魔界の仮面弁士  2008-11-13 21:28:35  No: 101287

Point メソッドを使えば、指定した座標の色が分かりますので、
それで、Line 描画の有無を判定する事ができるかと思います。

しかし、描画した画像の状態から判定するのではなく、
地図情報を別に管理しておき、その状態に基づいて
壁判定や描画処理を行った方が、応用しやすいかと思いますよ。

たとえば、縦横 8 マスの単純な迷路があったとして、それぞれのマスは
  「空白」(通過できるマス)
  「壁」(通過できないマス)
  「スタート」(開始地点:通過できるマス)
  「ゴール」(到達地点)
の 4 種の状態になっているとします。
図形化すると下記のようなイメージです。

    0 1 2 3 4 5 6 7 8 9
                        
0  ■■■■■■■■■■
1  ■□□□■■□□.S.■
2  ■■□□□□□■□■
3  ■■■□■■■■□■
4  ■□□□■□□□□■
5  ■□■■■□■■□■
6  ■□□□□□□■■■
7  ■■■■□■□□□■
8  ■.G.□□□■□■□■
9  ■■■■■■■■■■

この場合、上記を縦横10マスの二次元配列に格納しておくようにすれば、
現在位置の座標から、壁判定が可能になるかと思います。

たとえば、現在位置が (1,8) の座標だとすれば、
それを配列に照らし合わせることで
  今(1,8) は「S(スタート地点)」のマスである。
  上(0,8) は「■(壁)」なので進めない。
  右(1,9) は「■(壁)」なので進めない。
  下(2,8) は「□(道)」なので通過できる。
  左(1,7) は「□(道)」なので通過できる。
といった状態判定を行うのは、さほど難しくは無いですよね。

また、迷路を描画する場合、上記の地図情報を基にして、
最初はテキストのまま表示するようにし、次のバージョンでは

┏━━━┳┳━━━┓
┃□□□┗┛□□.S.┃
┣┓□□□□□┃□┃
┣┻━□┏━━┛□┃
┃□□□┃□□□□┃
┃□━━┛□━┓□┃
┃□□□□□□┗━┃
┣━━━□┃□□□┃
┃.G.□□□┃□┃□┃
┗━━━━┻━┻━┛

のようなラインを引き、さらに次のバージョンでは、それを発展させて、
壁の部分も画像化する…といった拡張もしやすくなるでしょうし、
道の種類を増やす(ワープゾーン等)といった変化もつけやすいかな、と。


魔界の仮面弁士  2008-11-14 00:41:19  No: 101288

もう一案。

Line メソッドで直線を描く際に、線分の両端座標をすべて記録しておき、
それを元にして壁の有無を調べるという方法もあります。

一般論として、2点 (X0,Y0)-(X1,Y1) を通る直線は、
  y = ( ( y1 - y0 ) / ( x1 - x0 ) ) * ( x - x0 ) + y0
という式で表されますので、上記 x に現在の自キャラの横座標を
代入してみて、y が縦座標と一致するようであれば、その自キャラが
線の上に重なっている事になります。

そして移動を考慮する場合、「現在位置」から「移動後の位置」までの
線分が、壁を表す直線と交わるかどうかを算出する事になるでしょう。
http://www5d.biglobe.ne.jp/~tomoya03/shtml/algorithm/Intersection.htm

これをすべての壁線分に対して調べていけば、カーソル入力された方向に
移動可能かどうかを調査できます。

なお、実際にゲームとして扱う場合には、これに壁の厚み(線の太さ)と
自キャラImage のサイズ、移動距離単位(今回は 5 かな?)を考慮して
算出する事になるでしょうね。

>  Select Case KeyCode
>   Case 39
>     Image1.Move Image1.Left + 5, Image1.Top

こういう時には、37〜40 などの「マジック・ナンバー」を使うのではなく、
vbKeyUp, vbKeyLeft, vbKeyRight, vbKeyDown といった「定数」を使って
指定した方が、コードの意味がわかりやすくなりますよ。


ぺりー  2008-11-20 11:11:18  No: 101289

魔界の仮面弁士様

詳しい解説ありがとうございます。
まず初めに教えていただいた、Pointを使った方法でやってみて
全ての機能が実装できたら応用していきたいと思います。

もうひとつ、自キャラの表示についてもお伺いしたいのですが、
Imageはストレッチを有効にすればコントロールのサイズに合わせて
画像を拡大縮小できますが、PictureBoxではできませんでした。
画像を少し小さくして表示するため、
Imageの四隅それぞれの座標を取得する
画像の大きさを変えてPictureBoxで表示する
どちらかが必要になるかと思うのですが、両方分かりかねている状態です。

因みに元の画像は別のフォームのドローツールで描かれたもので、Bmp形式です。
VBは5.0です。

ご指導お願いいたします。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加