Replica Island 學習筆記 05 - 關卡數據

關卡數據

Replica Island的關卡數據記錄在以下兩個文件裏:

  • res/xml/level_tree.xml
  • res/xml/linear_level_tree.xml

其文件結構都是一樣的:

  • 文件含有一個levelTree標籤,levelTree標籤囊括所有的關卡信息;
  • levelTree標籤下包含一個或多個group標籤;
  • group標籤下包含一個或多個level標籤;
  • level標籤下不包含或者只包含一個dialog標籤,level標籤指定某個關卡的信息;
  • dialog標籤下包含以下標籤中的任何組合,每個標籤最多出現一次:diary、character1、character2,dialog標籤指定關卡內的NPC對話信息。

各個標籤支持的屬性:

標籤 屬性
resource time title restartable waitmessage past
levelTree            
group            
level 關卡布局數據 通關時間記錄
in res/values/strings.xml:
level_0_1_time ~ level_final_boss_time
關卡標題/存檔:
in res/values/strings.xml:
level_0_1_sewer ~ level_final_boss_lab
關卡是否可以重玩

默認值爲true
可設置爲false
關卡開始前是否顯示等待對話框

默認值爲false
可設置爲true
inThePast

默認值爲false
可設置爲true
dialog            
diary 日記數據:
in res/values/strings.xml:
Diary1 ~ Diary15
         
character1 NPC對話信息          
character2 NPC對話信息          

NPC對話信息

以下文件記錄了各關卡里的NPC對話信息:

xml/level_0_1_dialog_wanda.xml
xml/level_0_2_dialog_kabocha_2.xml
......
xml/level_4_9_dialog_wanda.xml
xml/level_final_boss_dialog.xml

其文件結構都是一樣的:

  • 文件含有一個dialog標籤,dialog標籤囊括關卡內的所有NPC對話信息;
  • dialog標籤下包含一個或多個conversation標籤,conversation標籤指定某處NPC的對話信息。有幾個conversation標籤,該關卡內就有幾處NPC要對話。
  • conversation標籤下包含一個或多個page標籤,page標籤指定某個NPC的一段對話。有幾個page標籤,該NPC就有幾段話要說。

除了通關對話level_final_boss_dialog.xml,其他的對話文件,都是每個文件裏只有一個NPC角色。page標籤支持以下三個屬性:

  • image:NPC頭像,保存在res/drawable目錄下:
    • res/drawable/kabocha_closeup_concern.png
    • res/drawable/kabocha_closeup_lunatic.png
    • res/drawable/kabocha_closeup_lunatic_02.png
    • res/drawable/kabocha_closeup_normal.png
    • res/drawable/kyle_closeup_angry.png
    • res/drawable/kyle_closeup_neutral.png
    • res/drawable/kyle_closeup_noglasses.png
    • res/drawable/rokudou_closeup_mask.png
    • res/drawable/rokudou_closeup_normal.png
    • res/drawable/wanda_happy.png
    • res/drawable/wanda_sad.png
    • res/drawable/wanda_smile.png
    • res/drawable/wanda_surprised.png
  • text:NPC對話字符串,字符串內容保存在以下文件裏,每個NPC一個文件:
    • res/values/kabocha.xml
    • res/values/kyle.xml
    • res/values/rokudou.xml
    • res/values/wanda.xml
  • title:NPC名字,保存在res/values/strings.xml裏:
    <!-- names -->
    <string name="Wanda">Wanda</string>
    <string name="Kyle">Kyle</string>
    <string name="Kabocha">Dr. Kabochanomizu</string>
    <string name="Rokudou">Mr. Rokudou</string>
    <string name="Android">Android</string>

例如如下的NPC對話情景:

XML代碼 字符串資源 遊戲畫面

res/xml/linear_level_tree.xml

<group>
    <level
        resource="@raw/level_0_3_lab"
        time="@string/level_0_3_time"
        title="@string/level_0_3_lab" >
        <dialog>
            <character1 resource="@xml/level_0_3_dialog_kabocha" />
        </dialog>
    </level>
</group>

res/values/strings.xml

<string name="level_0_3_lab">Memory #002</string>
 

res/xml/level_0_3_dialog_kabocha.xml

<conversation>
	<page
		image="@drawable/kabocha_closeup_normal"
		text="@string/Kabocha_0_3_1_1"
		title="@string/Kabocha" />
	<page
		image="@drawable/kabocha_closeup_normal"
		text="@string/Kabocha_0_3_1_2"
		title="@string/Kabocha" />
</conversation>

res/values/strings.xml

<string name="Kabocha">Dr. Kabochanomizu</string>

res/values/kabocha.xml

<string name="Kabocha_0_3_1_1">Jolly ho, my little creation!  You are almost ready to venture out by yourself.  I need to tell you about your mission, which is of critical importance to the future of this planet.  But before that, let me show you a trick.</string>
<string name="Kabocha_0_3_1_2">First, make your way through this maze.  Make sure you pick up the red gem on the way.</string>


res/xml/level_0_3_dialog_kabocha.xml

<conversation>
    <page
        image="@drawable/kabocha_closeup_normal"
        text="@string/Kabocha_0_3_2_1"
        title="@string/Kabocha" />
    <page
        image="@drawable/kabocha_closeup_normal"
        text="@string/Kabocha_0_3_2_2"
        title="@string/Kabocha" />
    <page
        image="@drawable/kabocha_closeup_normal"
        text="@string/Kabocha_0_3_2_3"
        title="@string/Kabocha" />
</conversation>

res/values/strings.xml

<string name="Kabocha">Dr. Kabochanomizu</string>

res/values/kabocha.xml

<string name="Kabocha_0_3_2_1">I’ve outfitted you with a special type of energy weapon that allows you to control machines.  While standing on the ground, <b>hold down the attack button</b> for a few seconds to charge up the <b>Possession Orb</b>.</string>
<string name="Kabocha_0_3_2_2">Once the Possession Orb is released, you can control its movement by tilting the phone.  Running it into a mechanical object will allow you to possess that object.  Pressing the attack button will destroy it and return control to your body.</string>
<string name="Kabocha_0_3_2_3">Try possessing that robot down there and using him to break through those blue blocks.  Here’s a hint: releasing a possessed robot causes it to explode.</string>



res/xml/level_0_3_dialog_kabocha.xml

<conversation>
    <page
        image="@drawable/kabocha_closeup_normal"
        text="@string/Kabocha_0_3_3_1"
        title="@string/Kabocha" />
    <page
        image="@drawable/kabocha_closeup_normal"
        text="@string/Kabocha_0_3_3_2"
        title="@string/Kabocha" />
    <page
        image="@drawable/kabocha_closeup_normal"
        text="@string/Kabocha_0_3_3_3"
        title="@string/Kabocha" />
</conversation>

res/values/strings.xml

<string name="Kabocha">Dr. Kabochanomizu</string>

res/values/kabocha.xml

<string name="Kabocha_0_3_3_1">Jolly good work!  You’re already asymptotically equal to my best neural net model.  </string>
<string name="Kabocha_0_3_3_2">One more thing about possession: those energy orbs require a lot of power to maintain, so you can only use them for a short time if you have not collected any gems.  Collecting gems will extend the amount of time the orb can survive before dissipating.</string>
<string name="Kabocha_0_3_3_3">Let’s practice possession a little more.  I’ll meet you up top.</string>




LevelTree.java

LevelTree負責管理所有的關卡信息,它提供方法loadLevelTree來加載所有的關卡信息:

public static final void loadLevelTree(int resource, Context context) {
    ...
}

方法get用於獲取指定關卡信息:

public static final Level get(int row, int index) {
    return levels.get(row).levels.get(index);
}

方法get的參數row指定group標籤的下標,index指定group標籤內level標籤的下標。

方法loadAllDialog用於加載所有的NPC對話信息:

public final static void loadAllDialog(Context context) {
    ...
}

方法loadLevelTree和loadAllDialog共有兩處引用,且都是一同調用的:

// AndouKun.onCreate()
int levelTreeResource = R.xml.level_tree;
if (mLinearMode != 0) {
	levelTreeResource = R.xml.linear_level_tree;
}

if (!LevelTree.isLoaded(levelTreeResource)) {
	LevelTree.loadLevelTree(levelTreeResource, this);
	LevelTree.loadAllDialog(this);
}

// MainMenuActivity.onCreate()
SharedPreferences prefs =
		getSharedPreferences(PreferenceConstants.PREFERENCE_NAME, MODE_PRIVATE);
final int row = prefs.getInt(PreferenceConstants.PREFERENCE_LEVEL_ROW, 0);
final int index = prefs.getInt(PreferenceConstants.PREFERENCE_LEVEL_INDEX, 0);
int levelTreeResource = R.xml.level_tree;
if (row != 0 || index != 0) {
	final int linear = prefs.getInt(PreferenceConstants.PREFERENCE_LINEAR_MODE, 0);
	if (linear != 0) {
		levelTreeResource = R.xml.linear_level_tree;
	}
}

if (!LevelTree.isLoaded(levelTreeResource)) {
	LevelTree.loadLevelTree(levelTreeResource, this);
	LevelTree.loadAllDialog(this);
}

這兩處調用都是將所有的關卡信息、NPC對話信息一次性都加載入內存。這並不是最優化的處理,其實對於NPC對話信息,應該只加載玩家當前要玩的關卡和下一關卡的對話信息即可。不知道爲什麼Chris Pruett沒有這麼做,也許因爲Replica Island只是個教學產品?

關卡布局數據

關卡布局數據保存在以下文件中:

  • raw/level_0_1_sewer_kyle.bin
  • raw/level_0_1_sewer_wanda.bin
  • ......
  • raw/level_4_9_underground.bin
  • raw/level_final_boss_lab.bin

關卡布局數據通過方法LevelSystem.loadLevel()來解析。分析該方法的代碼後,可以得知關卡布局數據文件的格式:

位移(字節) 長度(字節) 類型 說明
0 1 byte 關卡布局數據文件的標識,值必須爲96。
1 1 byte 關卡地圖的層數 layerCount
2 1 byte 關卡地圖背景層的索引,下標從1開始。
3 layerSize1 1 byte 關卡地圖層1 地圖層類型
4 1 byte 地圖磚塊索引 tileIndex 作用?下標起始值?
5 4 float, little endian 地圖層捲動速度 scrollSpeed 單位?
9 1 byte TiledWorld 地圖層數據標識,值必須爲42。
10 4 int, little endian 地圖層的寬度(以磚塊數量計)layerWidth
14 4 int, little endian 地圖層的寬度(以磚塊數量計)layerHeight
18 totalLayerTiles byte array 地圖層的磚塊索引數組
totalLayerTiles = layerWidth * layerHeight
  layerSize2   關卡地圖層2
  ......   ......
  layerSizeN   關卡地圖層N (N = layerCount)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章