本帖最后由 taroxd 于 2014-6-22 09:03 编辑
在本章,筆者會解說在選單畫面中選擇道具或技能之後,又在另一個新視窗進行分岐處理的方法。
在包含城鎮等地點的選單中選擇任意地點之後就會進行傳送──這次將以這樣的道具作為製作範例。
新增道具項目
和製作逃脫道具時相同,我們先設定傳送用的道具資料。
作用對象是「無」,使用時機則設為「僅在選單中」,備註欄就記入<TELEPORT>吧。設定完畢以後,再麻煩製作一個包含「道具的增減」事件指令的事件,測試看看道具的效果。
補充一點,為了方便起見,筆者都是用「道具」這個詞進行說明,但在本章製作的腳本,是可以直接對應技能的。換句話說,若在技能的備註欄中寫下 <TELEPORT> ,並讓作用對象和使用時機都採用同樣的設定的話,那樣也能夠做出同樣效果的技能出來。
[box=Sienna]新增視窗 [/box]
接著我們新增選擇傳送地點用的視窗類別。
這次別繼承Window_Selectable,改繼承看看Window_Command類別吧。什麼時候要繼承哪個類別視情況而定,而這次用Window_Command的話,因為不需要自己寫提供分支選項的程式碼,所以處理上比較方便。
class Window_Teleport < Window_Command def initialize super(0, 0) hide deactivate end end
class Window_Teleport < Window_Command
def initialize
super(0, 0)
hide
deactivate
end
end
Window_Command類別的initialize方法會接收x座標以及y座標兩個引數。這次不需要指定座標,所以筆者不設定Window_Teleport類別的initialize方法的引數,而是用super(0, 0)的形式叫出父類別的方法,將x、y座標都設為0。
再來呼叫hide讓視窗成為隱藏狀態,又呼叫deactivate方法將視窗設為無效中的狀態。這是因為視窗實際上產生的時間點是在移動到道具畫面之後,如果沒有選擇道具的就顯示這個畫面的話時機就錯誤了。
接著還需要視窗大小的指定。請將下面的程式碼寫在Window_Teleport類別中。
def window_width return 240 end def window_height Graphics.height end
def window_width
return 240
end
def window_height
Graphics.height
end
在Window_Command類別中,可以透過呼叫自己內部的window_width和window_height這兩個方法取得視窗的寬與高。這個設計是為了能夠進行更具彈性的處理,比方說如果指令的數量不同,視窗的大小就可以隨之調整。
這次我們用240這個值回傳寬,用Graphics.height回傳高。順帶一提,Graphics.height是回傳整個畫面高度的方法。
註:之所以要寫hide、deactivate的原因在於,繼承Window_Command類別所創造出的視窗,一開始就是activate的狀態,如果不寫的話,一但進入任何由Window_Comannd產生的視窗,就會跟著一併顯示。hide跟deactivate差別在於,前者是讓視窗不要出現,後者是讓使用者無法操作該視窗。倘若沒有經過後者,就會發現雖然看不見視窗,但還是能夠操作該視窗。因此兩者是不同的。
[box=Sienna]顯示視窗 [/box]
前一項製作出的視窗,我們在Scene_ItemBase類別中把它當成實體變數保管。然後像下面一樣重新宣告start方法,加上產生出Window_Teleport這個類別的實體變數的處理。另外在製作劇情提示畫面時也說過的,Window_Base中已經包含了所有視窗的釋放處理,所以不需要寫出dispose的處理。
class Scene_ItemBase alias xxx001_start start def start xxx001_start @teleport_window = Window_Teleport.new end end
class Scene_ItemBase
alias xxx001_start start
def start
xxx001_start
@teleport_window = Window_Teleport.new
end
end
然後我們重新宣告determine_item方法。
alias xxx001_determine_item determine_item def determine_item if item.note.include?("<TELEPORT>") show_sub_window(@teleport_window) else xxx001_determine_item end end
alias xxx001_determine_item determine_item
def determine_item
if item.note.include?("<TELEPORT>")
show_sub_window(@teleport_window)
else
xxx001_determine_item
end
end
determine_item是在將游標移動到道具上方,按下決定鍵的瞬間呼叫的方法。這部分的處理指定的是,如果在備註欄中含有<TELEPORT> 這個字串的話,就會呼叫show_sub_window方法,而如果沒有包含的話則是進行一般的處理。
show_sub_window方法是用來在道具畫面或技能畫面上方顯示別的視窗。在預設的程式碼中,只有在選擇道具或技能要作用在哪個角色上時有使用到。這個方法所進行的處理是,透過操作顯示域(viewport)的位置等參數,讓視窗在重疊的時候不會看起來怪怪的。只不過使用這個方法有一個前提,那就是視窗的高度一定要和整個畫面的高度一樣。
雖然目前只寫到一半,我們先在這裡測試一下吧。雖然會在選擇道具的瞬間變得進行無法操作,至少可以確認一下視窗現在是如何顯示的吧。
[box=Sienna]製作傳送點的清單場所 [/box]
我們把傳送點的資料用常數的形式準備一下吧。
Ruby的陣列可以不受限地同時保管數值或是文字列,所以直接寫出像下面這樣的程式碼很方便。
TELEPORT_PLACES = [ [41, "地點A", 1, 10, 10], [42, "地點B", 2, 25, 20], [43, "地點C", 3, 30, 15], ]
TELEPORT_PLACES =
[
[41, "地點A", 1, 10, 10],
[42, "地點B", 2, 25, 20],
[43, "地點C", 3, 30, 15],
]
這個二維陣列構造,可以將內部保管各種常數的陣列當成一整個單位看待,然後這些陣列又包含在TELEPORT_PLACES這個陣列裡頭。筆者打算將各個常數,依序作為開關ID、傳送點的名稱、地圖ID、x座標和y座標使用。
所謂的開關ID是指,當指定的開關為ON的狀態,就可以傳送到到那個地點。舉例來說可以作為這樣的目的使用:當進入新的城鎮時開關就會變為ON,那麼以後就能傳送到那個城鎮。
為了確保能夠運作,請把地點改寫為測試用的專案裡頭有效的地點。上面的範例只列有三個地點,但當然要幾個都沒有關係。然後麻煩再製作一個可以將指定的開關ID設為ON的事件。
[box=Sienna]選擇傳送點 [/box]
接下來要讓傳送點的視窗能夠顯示剛才製作出來的場所資料。
請在Window_Teleport類別中加入以下的程式碼:
def make_command_list TELEPORT_PLACES.each do |place| if $game_switches[place[0]] add_command(place[1], :teleport, true, place) end end end
def make_command_list
TELEPORT_PLACES.each do |place|
if $game_switches[place[0]]
add_command(place[1], :teleport, true, place)
end
end
end
利用陣列的each方法執行迴圈,指定的開關如果是ON,那麼屬於該開關的地點的名稱就會以「指令」的形式追加上去。
add_command的第四個引數能夠指定擴充資料。所謂的擴充資料是指附帶在那些指令之後的資料,這裡的例子就是讓指令帶有傳送點的資料本身。關於第三個引數,筆者會在下一章說明。
[box=Sienna]設定handler [/box]
最後要進行決定和取消處理的設定。
請將Scene_ItemBase類別按照下方修正。
alias xxx001_start start def start xxx001_start @teleport_window = Window_Teleport.new @teleport_window.set_handler(:teleport, method(:on_teleport)) @teleport_window.set_handler(:cancel, method(:on_teleport_cancel)) end
alias xxx001_start start
def start
xxx001_start
@teleport_window = Window_Teleport.new
@teleport_window.set_handler(:teleport, method(:on_teleport))
@teleport_window.set_handler(:cancel, method(:on_teleport_cancel))
end
接著實作on_teleport和on_teleport_cancel方法。
def on_teleport place = @teleport_window.current_ext $game_player.reserve_transfer(place[2], place[3], place[4]) SceneManager.goto(Scene_Map) end def on_teleport_cancel hide_sub_window(@teleport_window) end
def on_teleport
place = @teleport_window.current_ext
$game_player.reserve_transfer(place[2], place[3], place[4])
SceneManager.goto(Scene_Map)
end
def on_teleport_cancel
hide_sub_window(@teleport_window)
end
current_ext方法可以取得目前被選取的指令所對應的擴充資料。這裡表示的就是這些地點的資料,然後再從中取出地圖ID和座標,進行地點移動。
hide_sub_window方法是進行和show_sub_window相反的處理。在按下取消鍵後會關閉視窗,回到道具選擇的畫面。
透過以上的程式碼,就完成了傳送的基本處理。如果要更加實用,還需要一些例如讓傳送本身無效的處理等等,但那一點在製作逃脫道具已經解說過所以在此省略。要是有人一直留著之前的逃脫道具腳本,會造成同樣的地方被多次宣告,考量到腳本衝突,因此有必要使用別名。
|