饥荒Mod 开发(十三):木牌传送

饥荒Mod 开发(十二):一键制作
饥荒Mod 开发(十四):制作屏幕弹窗

一键传送源码
饥荒的地图很大,跑地图太耗费时间和饥饿值,如果大部分时间都在跑图真的是很无聊,所以需要有一个能够传送的功能,不仅可以快速到达还能节省饥饿值。
饥荒二本之后可以制作出木牌,我们可以在地图各个位置创建木牌,右键点击木牌就可以传送到其他的木牌

1 功能演示

1.1 创建木牌

需要先升级到一本,制作一个科学机器,这样就可以制作木牌了。
在这里插入图片描述

1.2 右键传送

将鼠标放到木牌上, 会显示 “传送”, 右键单击会显示一个传送面板
在这里插入图片描述

1.3 传送面板

这个面板会列出所有的木牌,可以修改木牌的名字, 也可以直接点击 “传送” 就可以不消耗饥饿值 瞬间移动到了目的地
在这里插入图片描述
接下来介绍如何实现 传送功能

2 实现鼠标悬浮显示 “传送”

要和饥荒中的物品“交互”,可以自定义一个Action,这样鼠标右键悬浮的时候会显示一个自定义的“操作提示”,右键单击的时候可以执行指定的操作。那如何自定义一个action?

2.1 创建action

在Mod 根目录下创建一个 travel.lua文件,这个文件用来定义action在这里插入图片描述

-- 创建一个新的动作(Action),这个动作可以通过右键触发,优先级为10
local TRAVEL = GLOBAL.Action({}, 10, false, true)
TRAVEL.id = "TRAVEL"  -- 设置动作的ID为"TRAVEL"
TRAVEL.str = "传送"  -- 设置动作的字符串表示为"传送"
TRAVEL.fn = function(act)  -- 设置动作的函数,这个函数定义了动作的行为local tar = act.target  -- 目标实体local traveller = act.doer  -- 执行动作的实体--traveller说一句话traveller.components.talker:Say("传送中...")return true  -- 先全部返回true看看效果 动作成功
end-- 将新的动作添加到游戏中
AddAction(TRAVEL)
-- 为"wilson"状态图添加新的动作处理器,当执行"TRAVEL"动作时,使用"give"动画
AddStategraphActionHandler("wilson", GLOBAL.ActionHandler(TRAVEL, "give"))

创建完这个action之后,我们把鼠标移动到物品上时,却没有任何的变化,我们还需要让具体的物品支持这个动作。

2.2 仅让木牌显示“传送”,自定义 “Travelable”组件

传送功能只能发生在木牌上,所以我们需要给“木牌”增加一个组件,让鼠标悬浮在木牌上的时候显示一个自定义的提示“传送”。在 scripts/components 目录下新建 travelable.lua
在这里插入图片描述

-- 定义 Travelable 类
local Travelable = Class(function(self, inst)-- 初始化实例self.inst = inst-- 设置名称self.name = "木牌"
end)-- 定义收集场景动作的方法
function Travelable:CollectSceneActions(doer, actions, right)-- 如果是右键操作,则添加 TRAVEL 动作if right thentable.insert(actions, ACTIONS.TRAVEL)end
end-- 定义保存状态的方法
function Travelable:OnSave()-- 创建一个表来存储数据local data = {}-- 保存名称data.name = self.name-- 返回保存的数据return data
end   -- 定义加载状态的方法
function Travelable:OnLoad(data)-- 如果有数据,则加载名称if data thenself.name = data.nameend
end-- 定义执行旅行的方法
function Travelable:DoTravel(traveller)-- 如果没有旅行者,则返回if not traveller thenreturnend-- 如果旅行者已经死亡,则返回if traveller.components.health and traveller.components.health:IsDead() thenreturnend-- 获取当前实例的世界位置local x, y, z = self.inst.Transform:GetWorldPosition()-- 设置旅行者的位置traveller.Transform:SetPosition(x-1, y, z)
end-- 返回 Travelable 类
return Travelable

2.3 木牌添加 自定义组件 “Travelable”

在modmain.lua 文件中导入 travel.lua,然后拦截 木牌的 构造,添加自定义组件,这样将鼠标移动到木牌上就会显示传送按钮了。

modimport("travel.lua")AddPrefabPostInit("homesign", function(inst)inst:AddComponent("travelable")
end)

2.4 进入游戏测试是否显示 “传送”

打开调试控制台, 输入c_spawn(“homesign”)可以创建一个木牌,将鼠标悬浮到木牌上将会出现 “传送” 提示
在这里插入图片描述
右键点击之后会显示“传送中”
在这里插入图片描述

3 制作传送面板

在scripts 目录下创建 widgets 目录,然后创建travelitem.lua,travelscreen.lua
在这里插入图片描述

3.1 travelitem 实现

每个 travelitem 都表示一个 传送点

--  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") -- 构造函数,创建一个名为"TravelItem"的小部件self.homesign = homesign -- 将homesign赋值给self.homesignself.traveller = traveller -- 将traveller赋值给self.travellerself.screen = screen -- 将screen赋值给self.screen--添加一个背景self.bg = self:AddChild(UIAnim()) -- 在self上添加一个UIAnimself.bg:GetAnimState():SetBuild("savetile") -- 设置UIAnim的Build为"savetile"self.bg:GetAnimState():SetBank("savetile") -- 设置UIAnim的Bank为"savetile"self.bg:GetAnimState():PlayAnimation("anim") -- 播放UIAnim的"anim"动画self.bg:SetScale(1, 0.8, 1) -- 设置UIAnim的缩放比例self.name = self.bg:AddChild(TextEdit(BODYTEXTFONT, 35)) -- 在bg上添加一个TextEditself.name:SetVAlign(ANCHOR_MIDDLE) -- 设置TextEdit的垂直对齐方式为中间self.name:SetHAlign(ANCHOR_LEFT) -- 设置TextEdit的水平对齐方式为左边self.name:SetPosition(0, 10, 0) -- 设置TextEdit的位置self.name:SetRegionSize(300, 40) -- 设置TextEdit的区域大小self.name:SetString(homesign.components.travelable.name) -- 设置TextEdit的内容为homesign.components.travelable.nameif isCurrent then -- 如果是当前的self.name:SetColour(0, 1, 0, 0.4) -- 设置TextEdit的颜色else--添加一个传送按钮self.go = self.bg:AddChild(ImageButton("images/ui.xml", "button_small.tex", "button_small_over.tex", "button_small_disabled.tex")) -- 在bg上添加一个ImageButtonself.go:SetPosition(220, 0) -- 设置ImageButton的位置self.go:SetText("传送") -- 设置ImageButton的文本为"传送"self.go:SetFont(BUTTONFONT) -- 设置ImageButton的字体self.go:SetOnClick(function() -- 设置ImageButton的点击事件self:Go()end)end--添加一个编辑按钮self.button = self.bg:AddChild(ImageButton("images/ui.xml", "button_small.tex", "button_small_over.tex", "button_small_disabled.tex")) -- 在bg上添加一个ImageButtonself.button:SetPosition(-220, 0) -- 设置ImageButton的位置self.button:SetText("编辑") -- 设置ImageButton的文本为"编辑"self.button:SetFont(BUTTONFONT) -- 设置ImageButton的字体self.button:SetOnClick(function() -- 设置ImageButton的点击事件self:Edit()end)
end)function TravelItem:Edit() local text = self.name:GetLineEditString() -- 获取name的文本内容--如果文本和原来的不一样if text ~= self.homesign.components.travelable.name then -- 如果文本内容和self.homesign.components.travelable.name不一样self.homesign.components.travelable.name = text -- 将self.homesign.components.travelable.name设置为新的文本内容end
endfunction TravelItem:Go()self.homesign.components.travelable:DoTravel(self.traveller) -- 调用self.homesign.components.travelable的DoTravel方法,参数为self.travellerself.screen:OnCancel() -- 调用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") -- 构造函数,创建一个名为"TravelScreen"的屏幕self.homesign = homesign -- 将homesign赋值给self.homesignself.traveller = traveller -- 将traveller赋值给self.travellerSetPause(true, "TravelScreen") -- 暂停游戏-- 创建一个背景self.root = self:AddChild(Widget("ROOT")) -- 添加一个名为"ROOT"的小部件self.root:SetVAnchor(ANCHOR_MIDDLE) -- 设置垂直锚点为中间self.root:SetHAnchor(ANCHOR_MIDDLE) -- 设置水平锚点为中间self.root:SetScaleMode(SCALEMODE_PROPORTIONAL) -- 设置缩放模式为等比例-- 添加一个背景self.bg = self.root:AddChild(Image("images/globalpanels.xml", "panel.tex")) -- 在root上添加一个图像self.bg:SetSize(500, 650) -- 设置图像的大小self.bg:SetPosition(0, 25) -- 设置图像的位置-- 添加一个当前标题self.current = self.root:AddChild(Text(BODYTEXTFONT, 35)) -- 在root上添加一个文本self.current:SetPosition(0, 225, 0) -- 设置文本的位置self.current:SetRegionSize(350, 50) -- 设置文本区域的大小self.current:SetHAlign(ANCHOR_MIDDLE) -- 设置文本的水平对齐方式为中间self.current:SetString(self.homesign.components.travelable.name) -- 设置文本的内容为self.homesign.components.travelable.name-- 添加一个菜单,用来显示修改和取消按钮self.menu = self.root:AddChild(Menu(nil, 200, true)) -- 在root上添加一个菜单self.menu:SetScale(0.6) -- 设置菜单的缩放比例self.menu:SetPosition(0, -225, 0) -- 设置菜单的位置self.cancelbutton = self.menu:AddItem("关闭", function() -- 在菜单上添加一个名为"关闭"的项,点击后执行self:OnCancel()函数self:OnCancel()end)-- 添加两个按钮,用于翻页self.upbutton = self.root:AddChild(ImageButton("images/ui.xml", "scroll_arrow.tex", "scroll_arrow_over.tex", "scroll_arrow_disabled.tex")) -- 在root上添加一个向上的按钮self.upbutton:SetPosition(180, 200, 0) -- 设置向上按钮的位置self.upbutton:SetRotation(-90) -- 设置向上按钮的旋转角度self.upbutton:SetScale(0.5) -- 设置向上按钮的缩放比例self.upbutton:SetOnClick(function()self:ScrollUp() -- 当点击向上按钮时,执行ScrollUp函数end)self.downbutton = self.root:AddChild(ImageButton("images/ui.xml", "scroll_arrow.tex", "scroll_arrow_over.tex", "scroll_arrow_disabled.tex")) -- 在root上添加一个向下的按钮self.downbutton:SetPosition(180, -200, 0) -- 设置向下按钮的位置self.downbutton:SetRotation(90) -- 设置向下按钮的旋转角度self.downbutton:SetScale(0.5) -- 设置向下按钮的缩放比例self.downbutton:SetOnClick(function()self:ScrollDown() -- 当点击向下按钮时,执行ScrollDown函数end)self.menu:SetHRegPoint(ANCHOR_MIDDLE) -- 设置菜单的水平注册点为中间self.travelitems = self.root:AddChild(Widget("ROOT")) -- 在root上添加一个名为"ROOT"的小部件,用于显示项目self.travelitems:SetPosition(-100, 0) -- 设置项目的位置self.travelitems:SetScale(0.8) -- 设置项目的缩放比例self.currentRow = 1 -- 设置当前行为1self:LoadTravelItems(self.currentRow) -- 加载第一行
end)function TravelScreen:ScrollUp()if self.currentRow >= 5 then -- 如果当前行大于等于5self.currentRow = self.currentRow - 5 -- 当前行减5self:LoadTravelItems(self.currentRow) -- 加载新的当前行的项目end
endfunction TravelScreen:ScrollDown()if self.currentRow <= #Pigpet.homesigns - 5 then -- 如果当前行小于等于Pigpet.homesigns的数量减5self.currentRow = self.currentRow + 5 -- 当前行加5self:LoadTravelItems(self.currentRow) -- 加载新的当前行的项目end
endfunction TravelScreen:LoadTravelItems(index)self.travelitems:KillAllChildren() -- 删除travelitems的所有子项--从 index 开始遍历, 只显示5个local num_items = 0 -- 初始化项目数量为0for i = index, #Pigpet.homesigns do -- 从index开始遍历Pigpet.homesignsif num_items >= 5 then -- 如果项目数量大于等于5,就跳出循环breakendlocal v = Pigpet.homesigns[i] -- 获取Pigpet.homesigns的第i个元素local isCurrent = v == self.homesign -- 判断v是否等于self.homesignlocal item = self.travelitems:AddChild(TravelItem(v, isCurrent, self.traveller, self)) -- 在travelitems上添加一个TravelItemitem:SetPosition(120, 200 - num_items * 100, 0) -- 设置TravelItem的位置num_items = num_items + 1 -- 项目数量加1end
endfunction TravelScreen:OnCancel()SetPause(false) -- 取消暂停TheFrontEnd:PopScreen(self) -- 弹出当前屏幕
endreturn TravelScreen

在这里插入图片描述

4 添加传送功能

4.1 处理右键点击函数

当右键点击 木牌的时候,我们需要打开一个面板,显示所有可以传送的地方,并且每个传送点后面都会有一个“传送”按钮。我们将 travel.lua代码稍微改动下。当右键点击的时候,会调用 travelable 组件的OnSelect 函数

-- 创建一个新的动作(Action),这个动作可以通过右键触发,优先级为10
local TRAVEL = GLOBAL.Action({}, 10, false, true)
TRAVEL.id = "TRAVEL"  -- 设置动作的ID为"TRAVEL"
TRAVEL.str = "传送"  -- 设置动作的字符串表示为"传送"
TRAVEL.fn = function(act)  -- 设置动作的函数,这个函数定义了动作的行为local tar = act.target  -- 目标实体local traveller = act.doer  -- 执行动作的实体if tar and tar.components.travelable and traveller then  -- 如果目标实体存在,且具有travelable组件,且执行动作的实体存在tar:DoTaskInTime(.2,  -- 在0.2秒后function()tar.components.travelable:OnSelect(traveller)  -- 调用目标实体的travelable组件的OnSelect方法,传入执行动作的实体end)return true  -- 动作成功endreturn true  -- 先全部返回true看看效果 动作成功
end-- 将新的动作添加到游戏中
AddAction(TRAVEL)
-- 为"wilson"状态图添加新的动作处理器,当执行"TRAVEL"动作时,使用"give"动画
AddStategraphActionHandler("wilson", GLOBAL.ActionHandler(TRAVEL, "give"))

4.2 打开传送面板

实现 travelable 组件的OnSelect 函数,在这个函数中,我们会打开一个全屏的面板,展示所有的可传送点

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--打开选择地点页面TheFrontEnd:PushScreen(TravelScreen(self.inst, traveller))
end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/282975.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IDEA2023 + spring cloud 工程热部署设置方法

基于spring cloud 工程进行热部署 &#xff0c;实现每次修改工程源文件&#xff0c;后台自动启动&#xff0c;方便开发测试工作。具体分为5步骤即可&#xff1a; 1、修改工程的pom文件&#xff0c;增加adding devtools 工具包。 <dependency> <groupId>org.s…

为什么该团队A做的事情,却被其它团队做了

第一种原因&#xff0c;原本方案只需要直接改动系统 service1&#xff0c;但由于团队1并没有解决该问题的动力&#xff0c;其他人不得不绕道去修改系统 service2&#xff0c;service3&#xff0c;service4 来解决该问题。 在一个大型电商系统中&#xff0c;有四个团队负责不同的…

ElasticSearch学习篇8_Lucene之数据存储(Stored Field、DocValue、BKD Tree)

前言 Lucene全文检索主要分为索引、搜索两个过程&#xff0c;对于索引过程就是将文档磁盘存储然后按照指定格式构建索引文件&#xff0c;其中涉及数据存储一些压缩、数据结构设计还是很巧妙的&#xff0c;下面主要记录学习过程中的StoredField、DocValue以及磁盘BKD Tree的一些…

neuq-acm预备队训练week 10 P3386 【模板】二分图最大匹配

题目描述 给定一个二分图&#xff0c;其左部点的个数为 n&#xff0c;右部点的个数为 m&#xff0c;边数为 e&#xff0c;求其最大匹配的边数。 左部点从 1 至 n 编号&#xff0c;右部点从 1至 m 编号。 题目限制 输入格式 输入的第一行是三个整数&#xff0c;分别代表 n&a…

【微服务】Spring Aop原理深入解析

目录 一、前言 二、aop概述 2.1 什么是AOP 2.2 AOP中的一些概念 2.2.1 aop通知类型 2.3 AOP实现原理 2.3.1 aop中的代理实现 2.4 静态代理与动态代理 2.4.1 静态代理实现 三、 jdk动态代理与cglib代理 3.1 jdk动态代理 3.1.1 jdk代理示例 3.1.2 jdk动态代理模拟实现…

设计模式——策略模式

引言 策略模式是一种行为设计模式&#xff0c; 它能让你定义一系列算法&#xff0c; 并将每种算法分别放入独立的类中&#xff0c; 以使算法的对象能够相互替换。 问题 一天&#xff0c; 你打算为游客们创建一款导游程序。 该程序的核心功能是提供美观的地图&#xff0c; 以…

[python]用python获取EXCEL文件内容并保存到DBC

目录 关键词平台说明背景所需库实现过程方法1.1.安装相关库2.代码实现 关键词 python、excel、DBC、openpyxl 平台说明 项目Valuepython版本3.6 背景 在搭建自动化测试平台的时候经常会提取DBC文件中的信息并保存为excel或者其他文件格式&#xff0c;用于自动化测试。本文…

用GitBook制作自己的网页版电子书

用GitBook制作自己的网页版电子书 前言 几年前阅读过其他人用GitBook创建的文档&#xff0c;可以直接在浏览器中打开&#xff0c;页面干净整洁&#xff0c;非常清爽&#xff0c;至今印象深刻。 GitBook非常适合用来为个人或团队制作文档&#xff0c;对于我这种偶尔写博客的人…

【Hadoop面试】HDFS读写流程

HDFS&#xff08;Hadoop Distributed File System&#xff09;是GFS的开源实现。 HDFS架构 HDFS是一个典型的主/备&#xff08;Master/Slave&#xff09;架构的分布式系统&#xff0c;由一个名字节点Namenode(Master) 多个数据节点Datanode(Slave)组成。其中Namenode提供元数…

Java架构师系统架构内部维度分析

目录 1 导语2.1 安全性维度概述2.2 流程安全性2.3 架构安全性2.4 安全维度总结3 伸缩性维度概述和场景思路3.1 无状态应用弹性伸缩3.2 阿里云Knative弹性伸缩3.3 有状态应用弹性伸缩3.4 伸缩性维度总结想学习架构师构建流程请跳转:Java架构师系统架构设计 1 导语

DSP捕获输入简单笔记

之前使用stm32的大概原理是&#xff1a; 输入引脚输入一个脉冲&#xff0c;捕获1开始极性捕获&#xff0c;捕获的是从启动捕获功能开始计数&#xff0c;捕获的是当前的计数值&#xff1b; 例如一个脉冲&#xff0c;捕获1捕获上升沿&#xff0c;捕获2捕获下降沿&#xff1b;而两…

vue2入门

vue2官方文档&#xff1a;安装 — Vue.js 1、安装 新建"vue"文件夹——>新建vue1.html 直接用<script>标签引入vue&#xff1a; <script src"https://cdn.jsdelivr.net/npm/vue2.7.14/dist/vue.js"></script> tips: CDN:一个网络…