手機(jī)上做整蠱網(wǎng)站全網(wǎng)推廣軟件
饑荒Mod 開發(fā)(十二):一鍵制作
饑荒Mod 開發(fā)(十四):制作屏幕彈窗
一鍵傳送源碼
饑荒的地圖很大,跑地圖太耗費(fèi)時(shí)間和饑餓值,如果大部分時(shí)間都在跑圖真的是很無聊,所以需要有一個(gè)能夠傳送的功能,不僅可以快速到達(dá)還能節(jié)省饑餓值。
饑荒二本之后可以制作出木牌,我們可以在地圖各個(gè)位置創(chuàng)建木牌,右鍵點(diǎn)擊木牌就可以傳送到其他的木牌
1 功能演示
1.1 創(chuàng)建木牌
需要先升級(jí)到一本,制作一個(gè)科學(xué)機(jī)器,這樣就可以制作木牌了。
1.2 右鍵傳送
將鼠標(biāo)放到木牌上, 會(huì)顯示 “傳送”, 右鍵單擊會(huì)顯示一個(gè)傳送面板
1.3 傳送面板
這個(gè)面板會(huì)列出所有的木牌,可以修改木牌的名字, 也可以直接點(diǎn)擊 “傳送” 就可以不消耗饑餓值 瞬間移動(dòng)到了目的地
接下來介紹如何實(shí)現(xiàn) 傳送功能
2 實(shí)現(xiàn)鼠標(biāo)懸浮顯示 “傳送”
要和饑荒中的物品“交互”,可以自定義一個(gè)Action,這樣鼠標(biāo)右鍵懸浮的時(shí)候會(huì)顯示一個(gè)自定義的“操作提示”,右鍵單擊的時(shí)候可以執(zhí)行指定的操作。那如何自定義一個(gè)action?
2.1 創(chuàng)建action
在Mod 根目錄下創(chuàng)建一個(gè) travel.lua文件,這個(gè)文件用來定義action
-- 創(chuàng)建一個(gè)新的動(dòng)作(Action),這個(gè)動(dòng)作可以通過右鍵觸發(fā),優(yōu)先級(jí)為10
local TRAVEL = GLOBAL.Action({}, 10, false, true)
TRAVEL.id = "TRAVEL" -- 設(shè)置動(dòng)作的ID為"TRAVEL"
TRAVEL.str = "傳送" -- 設(shè)置動(dòng)作的字符串表示為"傳送"
TRAVEL.fn = function(act) -- 設(shè)置動(dòng)作的函數(shù),這個(gè)函數(shù)定義了動(dòng)作的行為local tar = act.target -- 目標(biāo)實(shí)體local traveller = act.doer -- 執(zhí)行動(dòng)作的實(shí)體--traveller說一句話traveller.components.talker:Say("傳送中...")return true -- 先全部返回true看看效果 動(dòng)作成功
end-- 將新的動(dòng)作添加到游戲中
AddAction(TRAVEL)
-- 為"wilson"狀態(tài)圖添加新的動(dòng)作處理器,當(dāng)執(zhí)行"TRAVEL"動(dòng)作時(shí),使用"give"動(dòng)畫
AddStategraphActionHandler("wilson", GLOBAL.ActionHandler(TRAVEL, "give"))
創(chuàng)建完這個(gè)action之后,我們把鼠標(biāo)移動(dòng)到物品上時(shí),卻沒有任何的變化,我們還需要讓具體的物品支持這個(gè)動(dòng)作。
2.2 僅讓木牌顯示“傳送”,自定義 “Travelable”組件
傳送功能只能發(fā)生在木牌上,所以我們需要給“木牌”增加一個(gè)組件,讓鼠標(biāo)懸浮在木牌上的時(shí)候顯示一個(gè)自定義的提示“傳送”。在 scripts/components 目錄下新建 travelable.lua
-- 定義 Travelable 類
local Travelable = Class(function(self, inst)-- 初始化實(shí)例self.inst = inst-- 設(shè)置名稱self.name = "木牌"
end)-- 定義收集場(chǎng)景動(dòng)作的方法
function Travelable:CollectSceneActions(doer, actions, right)-- 如果是右鍵操作,則添加 TRAVEL 動(dòng)作if right thentable.insert(actions, ACTIONS.TRAVEL)end
end-- 定義保存狀態(tài)的方法
function Travelable:OnSave()-- 創(chuàng)建一個(gè)表來存儲(chǔ)數(shù)據(jù)local data = {}-- 保存名稱data.name = self.name-- 返回保存的數(shù)據(jù)return data
end -- 定義加載狀態(tài)的方法
function Travelable:OnLoad(data)-- 如果有數(shù)據(jù),則加載名稱if data thenself.name = data.nameend
end-- 定義執(zhí)行旅行的方法
function Travelable:DoTravel(traveller)-- 如果沒有旅行者,則返回if not traveller thenreturnend-- 如果旅行者已經(jīng)死亡,則返回if traveller.components.health and traveller.components.health:IsDead() thenreturnend-- 獲取當(dāng)前實(shí)例的世界位置local x, y, z = self.inst.Transform:GetWorldPosition()-- 設(shè)置旅行者的位置traveller.Transform:SetPosition(x-1, y, z)
end-- 返回 Travelable 類
return Travelable
2.3 木牌添加 自定義組件 “Travelable”
在modmain.lua 文件中導(dǎo)入 travel.lua,然后攔截 木牌的 構(gòu)造,添加自定義組件,這樣將鼠標(biāo)移動(dòng)到木牌上就會(huì)顯示傳送按鈕了。
modimport("travel.lua")AddPrefabPostInit("homesign", function(inst)inst:AddComponent("travelable")
end)
2.4 進(jìn)入游戲測(cè)試是否顯示 “傳送”
打開調(diào)試控制臺(tái), 輸入c_spawn(“homesign”)可以創(chuàng)建一個(gè)木牌,將鼠標(biāo)懸浮到木牌上將會(huì)出現(xiàn) “傳送” 提示
右鍵點(diǎn)擊之后會(huì)顯示“傳送中”
3 制作傳送面板
在scripts 目錄下創(chuàng)建 widgets 目錄,然后創(chuàng)建travelitem.lua,travelscreen.lua
3.1 travelitem 實(shí)現(xiàn)
每個(gè) travelitem 都表示一個(gè) 傳送點(diǎn)
-- travelitem.lua
local UIAnim = require "widgets/uianim"
local Widget = require "widgets/widget"
local Text = require "widgets/text"
local TextEdit = require "widgets/textedit"
local Image = require "widgets/image"
local ImageButton = require "widgets/imagebutton"local TravelItem = Class(Widget, function(self, homesign, isCurrent, traveller, screen)Widget._ctor(self, "TravelItem") -- 構(gòu)造函數(shù),創(chuàng)建一個(gè)名為"TravelItem"的小部件self.homesign = homesign -- 將homesign賦值給self.homesignself.traveller = traveller -- 將traveller賦值給self.travellerself.screen = screen -- 將screen賦值給self.screen--添加一個(gè)背景self.bg = self:AddChild(UIAnim()) -- 在self上添加一個(gè)UIAnimself.bg:GetAnimState():SetBuild("savetile") -- 設(shè)置UIAnim的Build為"savetile"self.bg:GetAnimState():SetBank("savetile") -- 設(shè)置UIAnim的Bank為"savetile"self.bg:GetAnimState():PlayAnimation("anim") -- 播放UIAnim的"anim"動(dòng)畫self.bg:SetScale(1, 0.8, 1) -- 設(shè)置UIAnim的縮放比例self.name = self.bg:AddChild(TextEdit(BODYTEXTFONT, 35)) -- 在bg上添加一個(gè)TextEditself.name:SetVAlign(ANCHOR_MIDDLE) -- 設(shè)置TextEdit的垂直對(duì)齊方式為中間self.name:SetHAlign(ANCHOR_LEFT) -- 設(shè)置TextEdit的水平對(duì)齊方式為左邊self.name:SetPosition(0, 10, 0) -- 設(shè)置TextEdit的位置self.name:SetRegionSize(300, 40) -- 設(shè)置TextEdit的區(qū)域大小self.name:SetString(homesign.components.travelable.name) -- 設(shè)置TextEdit的內(nèi)容為homesign.components.travelable.nameif isCurrent then -- 如果是當(dāng)前的self.name:SetColour(0, 1, 0, 0.4) -- 設(shè)置TextEdit的顏色else--添加一個(gè)傳送按鈕self.go = self.bg:AddChild(ImageButton("images/ui.xml", "button_small.tex", "button_small_over.tex", "button_small_disabled.tex")) -- 在bg上添加一個(gè)ImageButtonself.go:SetPosition(220, 0) -- 設(shè)置ImageButton的位置self.go:SetText("傳送") -- 設(shè)置ImageButton的文本為"傳送"self.go:SetFont(BUTTONFONT) -- 設(shè)置ImageButton的字體self.go:SetOnClick(function() -- 設(shè)置ImageButton的點(diǎn)擊事件self:Go()end)end--添加一個(gè)編輯按鈕self.button = self.bg:AddChild(ImageButton("images/ui.xml", "button_small.tex", "button_small_over.tex", "button_small_disabled.tex")) -- 在bg上添加一個(gè)ImageButtonself.button:SetPosition(-220, 0) -- 設(shè)置ImageButton的位置self.button:SetText("編輯") -- 設(shè)置ImageButton的文本為"編輯"self.button:SetFont(BUTTONFONT) -- 設(shè)置ImageButton的字體self.button:SetOnClick(function() -- 設(shè)置ImageButton的點(diǎn)擊事件self:Edit()end)
end)function TravelItem:Edit() local text = self.name:GetLineEditString() -- 獲取name的文本內(nèi)容--如果文本和原來的不一樣if text ~= self.homesign.components.travelable.name then -- 如果文本內(nèi)容和self.homesign.components.travelable.name不一樣self.homesign.components.travelable.name = text -- 將self.homesign.components.travelable.name設(shè)置為新的文本內(nèi)容end
endfunction TravelItem:Go()self.homesign.components.travelable:DoTravel(self.traveller) -- 調(diào)用self.homesign.components.travelable的DoTravel方法,參數(shù)為self.travellerself.screen:OnCancel() -- 調(diào)用self.screen的OnCancel方法
endreturn TravelItem
-- travelscreen.lualocal Screen = require "widgets/screen"
local Widget = require "widgets/widget"
local Menu = require "widgets/menu"
local Text = require "widgets/text"
local Image = require "widgets/image"
local ImageButton = require "widgets/imagebutton"
local TravelItem = require "widgets/travelitem"local TravelScreen = Class(Screen, function(self, homesign, traveller)Screen._ctor(self, "TravelScreen") -- 構(gòu)造函數(shù),創(chuàng)建一個(gè)名為"TravelScreen"的屏幕self.homesign = homesign -- 將homesign賦值給self.homesignself.traveller = traveller -- 將traveller賦值給self.travellerSetPause(true, "TravelScreen") -- 暫停游戲-- 創(chuàng)建一個(gè)背景self.root = self:AddChild(Widget("ROOT")) -- 添加一個(gè)名為"ROOT"的小部件self.root:SetVAnchor(ANCHOR_MIDDLE) -- 設(shè)置垂直錨點(diǎn)為中間self.root:SetHAnchor(ANCHOR_MIDDLE) -- 設(shè)置水平錨點(diǎn)為中間self.root:SetScaleMode(SCALEMODE_PROPORTIONAL) -- 設(shè)置縮放模式為等比例-- 添加一個(gè)背景self.bg = self.root:AddChild(Image("images/globalpanels.xml", "panel.tex")) -- 在root上添加一個(gè)圖像self.bg:SetSize(500, 650) -- 設(shè)置圖像的大小self.bg:SetPosition(0, 25) -- 設(shè)置圖像的位置-- 添加一個(gè)當(dāng)前標(biāo)題self.current = self.root:AddChild(Text(BODYTEXTFONT, 35)) -- 在root上添加一個(gè)文本self.current:SetPosition(0, 225, 0) -- 設(shè)置文本的位置self.current:SetRegionSize(350, 50) -- 設(shè)置文本區(qū)域的大小self.current:SetHAlign(ANCHOR_MIDDLE) -- 設(shè)置文本的水平對(duì)齊方式為中間self.current:SetString(self.homesign.components.travelable.name) -- 設(shè)置文本的內(nèi)容為self.homesign.components.travelable.name-- 添加一個(gè)菜單,用來顯示修改和取消按鈕self.menu = self.root:AddChild(Menu(nil, 200, true)) -- 在root上添加一個(gè)菜單self.menu:SetScale(0.6) -- 設(shè)置菜單的縮放比例self.menu:SetPosition(0, -225, 0) -- 設(shè)置菜單的位置self.cancelbutton = self.menu:AddItem("關(guān)閉", function() -- 在菜單上添加一個(gè)名為"關(guān)閉"的項(xiàng),點(diǎn)擊后執(zhí)行self:OnCancel()函數(shù)self:OnCancel()end)-- 添加兩個(gè)按鈕,用于翻頁self.upbutton = self.root:AddChild(ImageButton("images/ui.xml", "scroll_arrow.tex", "scroll_arrow_over.tex", "scroll_arrow_disabled.tex")) -- 在root上添加一個(gè)向上的按鈕self.upbutton:SetPosition(180, 200, 0) -- 設(shè)置向上按鈕的位置self.upbutton:SetRotation(-90) -- 設(shè)置向上按鈕的旋轉(zhuǎn)角度self.upbutton:SetScale(0.5) -- 設(shè)置向上按鈕的縮放比例self.upbutton:SetOnClick(function()self:ScrollUp() -- 當(dāng)點(diǎn)擊向上按鈕時(shí),執(zhí)行ScrollUp函數(shù)end)self.downbutton = self.root:AddChild(ImageButton("images/ui.xml", "scroll_arrow.tex", "scroll_arrow_over.tex", "scroll_arrow_disabled.tex")) -- 在root上添加一個(gè)向下的按鈕self.downbutton:SetPosition(180, -200, 0) -- 設(shè)置向下按鈕的位置self.downbutton:SetRotation(90) -- 設(shè)置向下按鈕的旋轉(zhuǎn)角度self.downbutton:SetScale(0.5) -- 設(shè)置向下按鈕的縮放比例self.downbutton:SetOnClick(function()self:ScrollDown() -- 當(dāng)點(diǎn)擊向下按鈕時(shí),執(zhí)行ScrollDown函數(shù)end)self.menu:SetHRegPoint(ANCHOR_MIDDLE) -- 設(shè)置菜單的水平注冊(cè)點(diǎn)為中間self.travelitems = self.root:AddChild(Widget("ROOT")) -- 在root上添加一個(gè)名為"ROOT"的小部件,用于顯示項(xiàng)目self.travelitems:SetPosition(-100, 0) -- 設(shè)置項(xiàng)目的位置self.travelitems:SetScale(0.8) -- 設(shè)置項(xiàng)目的縮放比例self.currentRow = 1 -- 設(shè)置當(dāng)前行為1self:LoadTravelItems(self.currentRow) -- 加載第一行
end)function TravelScreen:ScrollUp()if self.currentRow >= 5 then -- 如果當(dāng)前行大于等于5self.currentRow = self.currentRow - 5 -- 當(dāng)前行減5self:LoadTravelItems(self.currentRow) -- 加載新的當(dāng)前行的項(xiàng)目end
endfunction TravelScreen:ScrollDown()if self.currentRow <= #Pigpet.homesigns - 5 then -- 如果當(dāng)前行小于等于Pigpet.homesigns的數(shù)量減5self.currentRow = self.currentRow + 5 -- 當(dāng)前行加5self:LoadTravelItems(self.currentRow) -- 加載新的當(dāng)前行的項(xiàng)目end
endfunction TravelScreen:LoadTravelItems(index)self.travelitems:KillAllChildren() -- 刪除travelitems的所有子項(xiàng)--從 index 開始遍歷, 只顯示5個(gè)local num_items = 0 -- 初始化項(xiàng)目數(shù)量為0for i = index, #Pigpet.homesigns do -- 從index開始遍歷Pigpet.homesignsif num_items >= 5 then -- 如果項(xiàng)目數(shù)量大于等于5,就跳出循環(huán)breakendlocal v = Pigpet.homesigns[i] -- 獲取Pigpet.homesigns的第i個(gè)元素local isCurrent = v == self.homesign -- 判斷v是否等于self.homesignlocal item = self.travelitems:AddChild(TravelItem(v, isCurrent, self.traveller, self)) -- 在travelitems上添加一個(gè)TravelItemitem:SetPosition(120, 200 - num_items * 100, 0) -- 設(shè)置TravelItem的位置num_items = num_items + 1 -- 項(xiàng)目數(shù)量加1end
endfunction TravelScreen:OnCancel()SetPause(false) -- 取消暫停TheFrontEnd:PopScreen(self) -- 彈出當(dāng)前屏幕
endreturn TravelScreen
4 添加傳送功能
4.1 處理右鍵點(diǎn)擊函數(shù)
當(dāng)右鍵點(diǎn)擊 木牌的時(shí)候,我們需要打開一個(gè)面板,顯示所有可以傳送的地方,并且每個(gè)傳送點(diǎn)后面都會(huì)有一個(gè)“傳送”按鈕。我們將 travel.lua代碼稍微改動(dòng)下。當(dāng)右鍵點(diǎn)擊的時(shí)候,會(huì)調(diào)用 travelable 組件的OnSelect 函數(shù)
-- 創(chuàng)建一個(gè)新的動(dòng)作(Action),這個(gè)動(dòng)作可以通過右鍵觸發(fā),優(yōu)先級(jí)為10
local TRAVEL = GLOBAL.Action({}, 10, false, true)
TRAVEL.id = "TRAVEL" -- 設(shè)置動(dòng)作的ID為"TRAVEL"
TRAVEL.str = "傳送" -- 設(shè)置動(dòng)作的字符串表示為"傳送"
TRAVEL.fn = function(act) -- 設(shè)置動(dòng)作的函數(shù),這個(gè)函數(shù)定義了動(dòng)作的行為local tar = act.target -- 目標(biāo)實(shí)體local traveller = act.doer -- 執(zhí)行動(dòng)作的實(shí)體if tar and tar.components.travelable and traveller then -- 如果目標(biāo)實(shí)體存在,且具有travelable組件,且執(zhí)行動(dòng)作的實(shí)體存在tar:DoTaskInTime(.2, -- 在0.2秒后function()tar.components.travelable:OnSelect(traveller) -- 調(diào)用目標(biāo)實(shí)體的travelable組件的OnSelect方法,傳入執(zhí)行動(dòng)作的實(shí)體end)return true -- 動(dòng)作成功endreturn true -- 先全部返回true看看效果 動(dòng)作成功
end-- 將新的動(dòng)作添加到游戲中
AddAction(TRAVEL)
-- 為"wilson"狀態(tài)圖添加新的動(dòng)作處理器,當(dāng)執(zhí)行"TRAVEL"動(dòng)作時(shí),使用"give"動(dòng)畫
AddStategraphActionHandler("wilson", GLOBAL.ActionHandler(TRAVEL, "give"))
4.2 打開傳送面板
實(shí)現(xiàn) travelable 組件的OnSelect 函數(shù),在這個(gè)函數(shù)中,我們會(huì)打開一個(gè)全屏的面板,展示所有的可傳送點(diǎn)
local TravelScreen = require "widgets/travelscreen"
function Travelable:OnRemoveEntity()--從 homesigns 表中移除for k, v in pairs(Pigpet.homesigns) doif v == self.inst thentable.remove(Pigpet.homesigns, k)breakendend
endfunction Travelable:OnSelect(traveller)if not traveller thenreturnendif traveller.components.health and traveller.components.health:IsDead() thenreturnend--打開選擇地點(diǎn)頁面TheFrontEnd:PushScreen(TravelScreen(self.inst, traveller))
end