Visual Basic 中学校 投稿プログラム
VB2005対応 VB2008対応

 

Visual Basic 中学校 > 投稿プログラム >

一筆書き 

投稿者:名鉄2000系さん - BVE作成支援事務所

「一筆書き」はスタート地点からゴールまで同じますを通らないで、かつすべてのますを通ってたどり着くゲームです。まさに一筆書きの要領でスタート地点からゴールを目指すことになります。

ゲームとしてはシンプルなものですが、このプログラムを元にしていろいろなゲームを組むこともできそうですし、この手のゲームの作り方の参考にもなるでしょう。

ダウンロード   hitohude.lzh(39.6KB)         

VB2005で作成されたソースコード。プログラマ向けです。

ソースコードを編集するためにはVB2005またはVB2008が必要です。Express Editionでも大丈夫です。

VB2008で作業すると、最初だけ変換ウィザードが実行されます。

ソースコードの改変は自由ですが公開・配布については添付のReadMe.txtに記載のルールに従ってください。

 

V太:博士!ゲーム です!ゲームが届きました!

■画像1

B子:うん。まさに一筆書きね。スタート地点から「G」マークのついたゴールまでたどり着けばいいのね。

こんなゲームは簡単すぎて…、って、あれ、むぅぅ!

B子:制限時間もあるし、一筆書きってルールは簡単でもなかなか難しいわよ。

ステージ4がクリアできません…。制限時間が来ると無情に終了しちゃう…。

 

プログラムをいじって簡単にしちゃおうか。

面白そうね。ステージ4のデータはどこにあるのかしら?

博士:ふーむ。プログラムをいじる方が大変な気もするが少し協力してあげよう。

いいえ。このくらいのプログラムなら僕だけでなんとかなりそうです。多分Form1のLoadイベントで最初のステージの読み込みを行っていると思うので、そこを手掛かりにすればステージ4のデータの場所が分かると思います。

ほほぉ。言うのぉ。では、Form1のLoadイベントを見てみようかのぉ。

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    'ステージや残り時間の表示
   
Label2.Text = Class1.Sterge
    MaxTime = Class1.Time
    Label4.Text = Class1.Time

End
Sub

■リスト1

特にステージの読み込みのような処理はないわね。多分この処理は画面の初期表示と制限時間の設定ね。

じゃあ、LoadイベントじゃなくてShownイベントとかかな?

Shownイベントはないわよ。

うぅ。ひょっとしてForm1から開始じゃなくてSub Mainとかから開始するとか?

いいえ。Form1から開始よ。プロジェクトのプロパティでスタートアップフォームがForm1になっているわ。

うーーーん。でも、開始したら自動的にステージ1が表示されるからどこかで読み込み処理はしているはずなんだけどなぁ…。

ヒント 実は・・・

実は添付のreadme.txtにはステージの記述方法に関する詳細な情報があります。

 

 

では少し発想を変えてみようかの。データの読み込みを行っている場所は後で調べるとして、ステージ1の画像やグラフィックを描画している場所はどこかわかるかな?

描画処理はたいていPaintイベントですよね。このプログラムの場合PictureBox1にステージを描画しているからPictureBox1のPaintイベントのはずです。

Paintイベントを見てみるわ。

Private Sub PictureBox1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint

    Class1.Draw(e.Graphics)

End
Sub

■リスト2

ここはClass1のDrawメソッドを呼び出しているだけか…。

Drawって「描け」って意味よね。このメソッドの中で描画処理をやっているんでしょうね。

ちなみに「Class1」という名前はあまり良くないの。名前を見ただけでそのクラスにどんな機能があるかわかるような名前にすべきじゃ。

それはおいておいて、Class1のDrawメソッドの中を見るわね。

''' <summary>
''' 現在の状態を描画します。
'''
</summary>
Public Sub Draw(ByVal g As Graphics)

    For
i As Integer = 0 To Cells.Size.Width
        For j As Integer = 0 To Cells.Size.Height

            Select Case Cells.CellType(i, j)
                Case CellType.Floor
                    g.DrawImage(Cells.FloorImage, i * CellSize, j * CellSize, CellSize, CellSize)
'床を表示
               
Case CellType.Hole
                    g.DrawImage(Cells.HoleImage, i * CellSize, j * CellSize, CellSize, CellSize)
'穴を表示
               
Case CellType.Wall
                    g.DrawImage(Cells.WallImage(Cells.WallImageIndex(i, j)), i * CellSize, j * CellSize, CellSize, CellSize)
'壁を表示
           
End Select

       
Next
    Next

   
g.DrawRectangle(Pens.Yellow, Places.X * CellSize + 1, Places.Y * CellSize + 1, CellSize - 2, CellSize - 2) '現在地を表示
   
g.DrawString("G", New Font("MS Pゴシック", GoalFontSize), GoalColor, Goal.X * CellSize, Goal.Y * CellSize) 'ゴール地点の"G"を表示

   
'↓2つの文字をずらして重ねることにより、少し立体感を出す。
   
g.DrawString(Msg, New Font("MS Pゴシック", MsgFontSize), Brushes.Yellow, _MsgPoint) '適切な場所にメッセージを表示
   
g.DrawString(Msg, New Font("MS Pゴシック", MsgFontSize), Brushes.Red, _MsgPoint.X + 1.5, _MsgPoint.Y + 1.5) '適切な場所にメッセージを表示

End Sub

■リスト3

ぐわ!もうダメです。わかりません!

あきらめるのは早い!一見複雑そうに見えるが1つずつ見ていくと特に難しいことはやっていないんじゃ。まず注目すべきは最初に登場する2つのFor 〜 Nextじゃ。なぜ2重にループを行っていると思うかの?

多分。これは縦と横なのよ。このゲームは正方形に区切られたますめが基準になっているから、各ますごとにデータを表示するために2重ループになっているのね。

その通りじゃ。このような2重ループは2次元系のゲームを扱う時には基本の基本じゃ。

本当だ。よく見るとループの中でDrawImageを使ってグラフィックを描画している。しかもFloorとHoleとWallの3種類の画像を条件ごとに描画するようになっているみたいです。Floorは床、Holeは穴、Wallは壁ということでしょうか?

すばらしい。もう一歩じゃ。「3種類の画像を条件ごとに描画する」と言ったようじゃが、その条件とはなんじゃ?

えっと…、Select Caseで分岐しているから…条件は、Cells.CellType(i, j)です。

合格じゃ。つまり、このプログラムではCells.CellTypeプロパティを見るとそのステージの任意の位置のますめの状態が分かるというようになっているのじゃ。

ということは、Cell.CellTypeに値をセットしている個所こそがステージのデータを読み込んでいる場所ということになるのね?!

だいたいそのとおりじゃが、ちょっとだけ例外がある。このゲームでは現在の位置を移動するとそれまでいた場所に穴が開くようになっておる。つまり、プレイヤーが矢印キーを押したときにもCells.CellTypeが変化するのじゃ。この処理はClass1のMoveイベント内にある。そこだけ注意すればステージのデータを読み込んでいる場所を見つけられるじゃろう。

…と思ってさっきからプログラムを見ているんですけど目がちかちかしてきました…。

あら、V太ったら。こんなときに目で探す人なんて珍しいわよ。こういうときは検索するのよ。

でも、どう検索すればいいのかな?

ふふーん。そうね。検索もいろいろあるわよね。よく見ておきなさいよ。まず、[編集]メニューの[クイック検索]をクリックするのよ。そして、左上の「クイック検索」というところをドロップダウンして「フォルダを指定して検索」にするの。それで、CellTypeで検索しましょう。

■画像2

ほほー。なるほどのぉ。

これで検索すると該当する箇所が一覧表示されるし、一覧をクリックすると該当箇所にジャンプすることもできるから便利よ。

■画像3

わーお。すごいや。…でも、22件もあるのか…。

検索条件をもっと工夫すれば絞り込めるかもしれないけど22件くらいなら私たちの力でもっと絞れるわ。

まず、私たちはCellTypeに値をセットしているところを探しているから、Select CaseとかCaseとかではじまっている行は無視していいわ。そうすると、Class1.vbはすべて無視できることになるわね。

なんだ。それだったら、よく見ればCell.vbの74行目以下で値のセットを何箇所かやっているみたいだから怪しいね。

では、検索結果一覧でCell.vbの74行目をダブルクリックして該当箇所にジャンプしてみようかの。

なんか、長いロジックがあるわね。なんというメソッドの中かしら?

あっ!ここコンストラクタですよ。Cellクラスのコンストラクタでステージのデータを読み込んでいたんですね。

その通り。今回はプログラムの開始は確かにForm1のLoadからじゃが、Form1でクラスレベルで宣言しているClass1が、Newの中でCellクラスのコンストラクタを呼び出しているのじゃ。このように自動的にプログラムが実行されるのはイベントだけではなく、コンストラクタにも注意が必要だということを覚えておいた方がいいじゃろう。

※実際にはNewからTextInterpretationメソッドが呼び出されて、その中でCellクラスのコンストラクタが呼び出されている。

はい。

 

それで、結局ステージ4のデータはどこに?

Cellクラスのコンストラクタを呼び出している場所からたどっていけばわかるぞ。ここがまた探すのに時間がかかりそうじゃが結論だけいうとClass1のコンストラクタの中でテキストファイルからデータを読み込んでいる個所がある。ここで読み込んだデータがCellクラスのコンストラクタにわたるようになっている。

''' <param name="Sterge">今からプレイするステージです</param>
Public Sub New(ByVal Sterge As Integer)

    _Sterge = Sterge
'ステージを変える

   
If Not My.Computer.FileSystem.FileExists(Application.StartupPath & _
       "\sterge\sterge" & Sterge & ".txt") Then
'次のステージがあるかを調べる
       
MsgBox("ステージファイルが存在しません", 48, "エラー")
       
End
   
End If

   
Dim strText As String = IO.File.ReadAllText(Application.StartupPath & _
"\sterge\sterge" & Sterge & ".txt", System.Text.Encoding.GetEncoding("Shift-JIS"))
'次のステージを取得

   
TextInterpretation(strText)

End
Sub

■リスト4

つまり、そのテキストにステージデータがあるんですね?!

そのとおり。

えっと、テキストファイルの場所は「Application.StartupPath & "\sterge\sterge" & sterge & ".txt"」ね。

これは、プログラムと同じ場所にあるstergeフォルダの中にsterge4.txtというファイルがあるということだね。

プログラムの場所って、環境によって違うけど普通はbinフォルダの中のDebugフォルダの中ね。

その場所ならソリューションエクスプローラで「すべてのファイルを表示」アイコンをクリックすると素早く見ることができるぞ。

■画像4

おお!sterge4.txt発見!

こういうわけじゃからこのプログラムではexeの他にこのstergeフォルダやimageフォルダがないとうまく動かすことができん。

こういう構造をとるときは、binフォルダの中じゃなくてform1.vbとかと同じ位置にフォルダやファイルをを用意していおいて、「出力ディレクトリにコピー」の設定を「常にコピー」などにしておくと便利ね。こうすればbinフォルダはいつでも丸ごと消すことができるようになるしファイルの管理も楽だわ。

■画像5

もっといいのは画像やテキストを全部リソースに含めちゃうことかな。そうすれば、友達のパソコンに持って行くときにexeファイルだけ持って行けば済むようになるからね。

 

ちょっと脱線してしまったがステージ4の内容は自分の目でsterge4.txtを開いて確認してほしい。このようにデータをプログラムの外のファイルに格納することによってこのプログラムは非常に柔軟なプログラムになっている。何しろステージを変更したい場合でもプログラムをいじる必要は一切ないのじゃ。

確かに…。いちいちプログラムをいじらないで済むってすばらしいことよね。

 

 

あまりワイワイガヤガヤやっておると時間がいくらあっても足りんから後は自分の目でいろいろ見てみてほしい。そして余裕があるならプログラムを改造してみてほしい。

僕はこのゲームに音楽をつけたいなぁ。

せっかくソースコード付きでダウンロードできるんだからゲームだけやるってのは考えものね。このチャンスを活用しましょう。

 

投稿していただいた 名鉄2000系さん、ありがとうございます!

今後もみなさんからのプログラムの投稿をお待ちしています。

 

 

 

それから…、ステージのスペルは本当は「stage」です。英語の試験のときには気を付けてください。