在上個範例中我們利用地圖編輯器完成了地圖的製作並把它存成文字檔,現在要把這個文字檔透過自建的內容管道(Content Pipeline extension library)載入到我們的專案裡,並且利用自建的Map類別將地圖繪出。
在上個範例中我們利用地圖編輯器完成了地圖的製作並把它存成文字檔,現在要把這個文字檔透過自建的內容管道(Content Pipeline extension library)載入到我們的專案裡,並且利用自建的Map類別將地圖繪出。
先將地圖分割圖(Tile Sheet)跟地圖文字檔加入專案。
為了載入文字檔,然後可以用 Content.Load()的方式載入,所以我們需要建立一個新的內容管道擴充專案,包含Importer跟Processor,用來匯入跟處理文字檔,步驟如下:
對著解決方案按右鍵>新增>新專案。
選擇內容管道擴充庫。
新增完畢後會多出一個專案,此專案下會有一個ContentProcessor1類別
專案裡已經預設有一個Processor類別,還缺一個Importer類別,對著內容管道擴充專案按右鍵,新增項目。
選擇Content Importer。
新增完如下圖。
接著我們要修改Importer跟Processor程式碼,先雙擊ContentImporter1.vb,我們在匯入附檔名屬性設定為 "*.txt",在Import()裡把文字檔讀入的文字傳到Processor裡。
在修改Processor之前要先做一個重要的步驟,要在ContentPipelineExtension1專案先把MyData.dll參考進去,MyData.dll是我用C#寫的一個類別,此類別是用來溝通遊戲專案跟ContentPipelineExtension1專案。
再來修改Processor程式碼,雙擊ContentProcessor1.vb,TInput就是從Importer傳過來的,TOutput就是要傳過去遊戲專案的MapData物件,而Process()裡我們New一個MapData物件,並把從Importer傳過來的內容放到MapData.text裡,回傳MapData物件。
修改完Importer跟Processor後建置專案,並在Content專案裡將ContentPipelineExtension1專案參考進來。
點擊Map.txt設定Content Importer跟Content Processor為我們剛剛建立的。
到這裡我們就完成了前半段工作,接下來我們要開始撰寫Game1的程式碼了,再這之前先將MyData.dll參考進來。
在Game1類別宣告變數
Public Class Game1
Inherits Microsoft.Xna.Framework.Game
Private WithEvents graphics As GraphicsDeviceManager
Private WithEvents spriteBatch As SpriteBatch
Dim width As Integer = 25 '圖片寬 幾格Tile
Dim height As Integer = 15 '圖片高 幾格Tile
Dim Map As Map '可以用TileSheet跟地圖文字檔組出地圖
Dim MapData As New tileLib.MapData '文字檔內容會存放在MyData.text
Dim tileSheet As Texture2D '地圖的來源分割小圖
Dim tileMap(,) As Integer '存放小圖Id的陣列
End Class
在LoadContent()載入地圖,MapData = Content.Load(Of tileLib.MapData)("Map"),文字檔已經成功的用Content.Load()方式載入了,感動內。我們將文字檔的內容解析出來傳入Map.tileMap中。
Protected Overrides Sub LoadContent()
' Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = New SpriteBatch(GraphicsDevice)
' TODO: use Me.Content to load your game content here
tileSheet = Content.Load(Of Texture2D)("TileSheet01")
MapData = Content.Load(Of tileLib.MapData)("Map")
Map = New Map()
'將文字檔解析並存入陣列
ReDim tileMap(width - 1, height - 1)
Dim arr() As String
arr = MapData.text.Split(ChrW(13))
For j As Integer = 0 To height - 1
Dim arr2() As String
arr2 = arr(j).Split(","c)
For i As Integer = 0 To width - 1
tileMap(i, j) = CInt(arr2(i))
Next
Next
Map.tileMap = tileMap
End Sub
在Draw()呼叫Map.DrawMap()就可以繪製出地圖了。
Protected Overrides Sub Draw(ByVal gameTime As GameTime)
GraphicsDevice.Clear(Color.CornflowerBlue)
' TODO: Add your drawing code here
Map.DrawMap(spriteBatch, tileSheet)
MyBase.Draw(gameTime)
End Sub
程式執行結果如下 (範例下載)
使用地圖編輯器除了可以縮小大地圖的檔案大小,也能很彈性的編輯不同關卡,大家可以用此範例下去自由發揮應用。
Map類別主要是做一些Tile Sheet分割圖片與地圖文字檔的對應轉換,以下附上程式碼供大家參考。
Class Map
Dim size As Integer = 32
Dim width As Integer = 25
Dim height As Integer = 15
Public tileMap(,) As Integer
Sub New()
ReDim tileMap(width - 1, height - 1)
For j As Integer = 0 To height - 1
For i As Integer = 0 To width - 1
tileMap(i, j) = -1
Next
Next
End Sub
Public Sub DrawMap(spriteBatch As SpriteBatch, tileSheet As Texture2D)
spriteBatch.Begin()
For j As Integer = 0 To height - 1
For i As Integer = 0 To width - 1
Dim cell As Integer = tileMap(i, j)
If cell > -1 Then
Dim srcBounds As Rectangle = Cell2Position(cell, tileSheet)
Dim Bounds As Rectangle = New Rectangle(i * size, j * size, size, size)
spriteBatch.Draw(tileSheet, Bounds, srcBounds, Color.White)
End If
Next
Next
spriteBatch.End()
End Sub
Function Cell2Position(cell As Integer, tileSheet As Texture2D) As Rectangle
Dim rect As Rectangle
Dim tileWidth As Integer = CInt(tileSheet.Width / 32)
Dim j As Integer = CInt(cell \ tileWidth)
Dim i As Integer = cell Mod tileWidth
rect = New Rectangle(i * size, j * size, size, size)
Return rect
End Function
End Class