実習で迷路を作っています。
フォームにランダムに描いた迷路で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が
触れているかどうかを判定するにはどうしたらよいでしょうか。
お教えいただければ幸いです。
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.□□□┃□┃□┃
┗━━━━┻━┻━┛
のようなラインを引き、さらに次のバージョンでは、それを発展させて、
壁の部分も画像化する…といった拡張もしやすくなるでしょうし、
道の種類を増やす(ワープゾーン等)といった変化もつけやすいかな、と。
もう一案。
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 といった「定数」を使って
指定した方が、コードの意味がわかりやすくなりますよ。
魔界の仮面弁士様
詳しい解説ありがとうございます。
まず初めに教えていただいた、Pointを使った方法でやってみて
全ての機能が実装できたら応用していきたいと思います。
もうひとつ、自キャラの表示についてもお伺いしたいのですが、
Imageはストレッチを有効にすればコントロールのサイズに合わせて
画像を拡大縮小できますが、PictureBoxではできませんでした。
画像を少し小さくして表示するため、
Imageの四隅それぞれの座標を取得する
画像の大きさを変えてPictureBoxで表示する
どちらかが必要になるかと思うのですが、両方分かりかねている状態です。
因みに元の画像は別のフォームのドローツールで描かれたもので、Bmp形式です。
VBは5.0です。
ご指導お願いいたします。