粮荒MOD入门教程(1)-制作一把专属手持武器

饥荒MOD入门教程(1)--制作一把专属手持武器

实例下载

按下面流程制作的一个示范已经上传到了百度云盘,如果在制作过程中有什么疑问,可以参考。
实例下载

基本工具

mod tools
这是一个官方提供的工具合集,除了提供上传到创意工坊的功能之外,其他的介绍如下:
2. Spriter
这个软件用于制作动画,这里的动画并不单单指会动的那些。不会动的那些,比如说插在地上的长矛,在游戏里表现出来的也是动画,只是只有一帧所以没变化而已。在地图上的大部分实体,都是通过动画表现出来的,这是MOD里非常重要而且用得最多的部分。但是,官方提供的是免费版,只提供基础基础的功能,如果你想要深入制作动画,最好在steam上购买spriter pro,如果没有这么多钱,就去百度一下吧。
3. FMOD_Designer
用于制作可导入游戏中的音效,音乐等。
4. Tiled
制作地图的软件,如果要制作奇遇,就需要用到这个软件。理论上,如果你有足够的耐心,也可以自己编辑出一个大地图然后导入到游戏中去。
5. Sublime
编程工具,可以高亮显示各种不同的逻辑块,方便编程。不过我不太喜欢它黑色的背景,相比之下我更喜欢用Notepad ++。
6. 其它
mod tools还有一个极为重要功能:
自动帮你打包Spriter制作的动画为游戏里使用的.zip动画文件包,以及转换PNG图片为游戏里使用的tex图片文件。
去哪里下载这个mod tools呢?
正版可以在steam库的工具库里找到。
盗版的话去这里下载:
https://github.com/kleientertainment/ds_mod_tools
不过我并不知道盗版该如何安装,麻烦自行百度吧,觉得时间出不起的话,不如买一份正版饥荒。

两条基本编程原则

  1. 尽量保持代码的良好可读性。
    所谓可读性,有很多含义,但这里只说最基本的:代码要规范整洁,比如说,在一个控制结构(if、for)下的代码,必须要右缩进一个tab的距离。这样你才容易清楚地观察到各个代码块之间的层次区别。
    程序并不是编写了一次就能一劳永逸的,你会在运行中发现很多BUG,这时候你就需要去寻找原因,去修改代码,良好的可读性有助于你快速发现问题。
  2. 用一款良好的工具帮助编程。
    记事本也可以编程,但记事本没有折叠,没有字体颜色区分,这就使得你想要快速找到自己想要的代码变得非常困难。这里还是推荐使用Notepad ++。使用工具是为了高效率编程,节约时间精力。编程在大多数时候都无关智力,是单纯的体力活。

制作手持武器–贴图篇

  • 材料:需要好几张图,要求必须是RGB 8位,透明背景的PNG图片。
  • 工具:图片处理工具(比如PS),Spriter。

图片的具体需求:

  • 一张64*64大小的图片,用于物品栏图标。这里64*64不是必须的,你也可以32*32,128*128,但必须要满足长宽相等,以及数字为2的整数次方的条件。
  • 一张随意大小的图片,用于表示装备放置在地上的样子。
  • 一张合适大小的图片,用于表示装备拿在手上的样子。

2和3对大小要求不一样的原因是,放在地上的图片,是可以在spriter里调整大小的。
但3不能,3原本是多大,在游戏里就会显示出多大。我第一次做的时候选用64*64的图片来做3,结果实际显示的大小刚好有人物的拳头那么大。

在讲下面的内容之前,要补充一些下面会用到的说明:
一个在地图上(注意是地图上,放在物品栏里的不算)显示的实体,显示出来的是一个动画。
一个实体可以有多个动画,通过代码来控制播放。简单的比如一棵草,有三个动画:成熟、被采摘后,枯萎后。
对于一个实体的地图表现,以下这些参数是很重要的

  • Build:储存着实体的图片材质,比如兔子在冬天会变成冬兔,但仍然是那只兔子,基本的属性没有改变,只是换了一个Build而已。做人物MOD,改变外观,实质上也不过是改变wilson的Build罢了。
  • Bank:控制着材质的组织形式和使用方法。具体来说,就是控制着Animation。一个bank可以拥有多个Animation,而每个Animation则具体地表述了Build中的图片该如何使用。举个例子,所有的人物,使用的bank都是wilson。
  • Animation:就是所谓的动画了,任何会在地图上显示出来的实体,都有动画。比如说人物,在站立不动的时候,就会循环播放idle动画。动画的播放选择,如果是动画少的,比如前面说的一棵草,就直接在函数代码里顺带写一写就可以了。但如果是像人物这样有着丰富动画的,就需要有一个专门的文件来统一调度在什么时候使用什么动画。这个文件叫做StateGraph,也就是状态图,人物的状态图文件就在stategraphs下,名字叫SGwilson。
  • Symbol:这是给图片集做标记的。在Spriter里,同一个文件夹下的图片集,都归结为同一个symbol。文件夹的名字,就是symbol的名字。symbol的主要用途在于覆盖,以及代码控制显示部位。比如说装备武器的时候,就是用武器的symbol覆盖了swap_object这个symbol。同时,人物的左手变成大手,也是因为隐藏了ARM_normal这个symbol,改成显示ARM_Carry这个symbol。

现在可以来讲相应内容了。假设你已经用图片处理工具弄好了相应的图片。

  • 物品栏图片 myitem.png
    粮荒MOD入门教程(1)-制作一把专属手持武器
  • 地上动画图片 ground_myitem.png
    粮荒MOD入门教程(1)-制作一把专属手持武器
  • 手上动画图片 swap_myitem.png
    粮荒MOD入门教程(1)-制作一把专属手持武器

然后就开始来正式制作一个MOD吧,这里仅仅讲单机版的。联机版的稍有不同但也没多大差别,聪明的人自然懂得举一反三。

  • 建立mod文件夹和基本文件
    在游戏目录下的mods文件夹里建立一个文件夹,名字就叫mymod吧。
    然后在mymod里,建立modinfo.lua和modmain.lua两个文件。
    modinfo是用于储存你的mod基本信息的,包括mod名字、mod描述、mod作者以及mod版本等等,mod设置也写在这个文件里。
    modmain.lua是控制整个MOD文件调用的核心,要想把mod里的专属武器、专属人物输入到游戏里,都需要经过这个文件。这个文件很重要,但在做一个专属装备的时候,它的作用仅仅是写几行代码,让装备能被注册到游戏里而已。

  • 添加物品栏图片
    在\mymod\images\inventoryimages下添加物品栏图片 myitem.png
    注意,images这个文件夹,名字不能随意改动,后面的inventoryimages文件夹可以改动,甚至也可以不要,直接将图片放在images文件夹下也可以。不过还是推荐使用inventoryimages,能够区分不同图片的区别,也不会造成重名问题。 这个路径是涉及到后面编程时的代码的,区分大小写。所以如果总是报错,记得先检查大小写是否正确。
    然后在这个文件夹下,新建一个.xml文件。输入以下内容并保存
    <Atlas>
    <Texture filename="myitem.tex" />
    <Elements>
    <Element name="myitem.tex" u1="0" u2="1" v1="0" v2="1" />
    </Elements>
    </Atlas>

    .xml文件是用来控制切割图片的,不过对于这样只有一张的图,就直接取整张,无需切割了。这里也不做过多的解释。
    游戏里使用的图片是.tex格式的,但如果你的png图片长、宽都是2的整次方倍,并且是8位RGB,背景透明的,那么mod tools会帮你自动转换成.tex图片。推荐使用这种方法来转换图片,而不要使用TEXCreator,虽然后者转换的图片也能被游戏使用,但可以在游戏运行日志里看到对不合长宽范式的图片会有警告信息,也许会在某处出错。
    如果mod tools没有转换你的图片,那么肯定是你的图片不符合格式。它对格式有着严格要求:
    RGB 8位,带ALPHA通道,png,长、宽是2的整数次方倍(长宽可以不相等,不过对于物品栏图标来说,最好还是要相等)。一个简单的处理办法是,用PhotoShop新建一个长宽符合要求的RGB 8位,背景内容为透明的画布,然后把原图片复制过来,保存为png格式。

  • 添加地上动画
    在\mymod\exported\下建立一个新的文件夹,名字随意,就叫ground_myitem吧
    然后再在这个文件夹下建立一个文件夹,同样名字随意,我的习惯是仍然叫ground_myitem
    然后在这个文件夹下添加地上动画图片 ground_myitem.png
    接着打开你的Spriter,File–>New Project ,点击OK,在弹出的浏览框里找到
    饥荒游戏根目录\mods\mymod\exported\ground_myitem,点击选择文件夹。(注意下面的”文件夹:”输入框里不要填字)
    粮荒MOD入门教程(1)-制作一把专属手持武器
    然后你会看到这样的画面
    粮荒MOD入门教程(1)-制作一把专属手持武器
    点开右边的那个文件夹,在里面双击图片ground_myitem.png,移动那个十字到你觉得合适的位置。
    粮荒MOD入门教程(1)-制作一把专属手持武器
    附带说一句,mod tools提供的spriter是简易免费版,不提供如图所示的九宫格自动定位坐标点的功能。你需要在steam上购买spriter pro,或者去百度盗版的spriter pro。
    这个十字就是图片的控制点,决定着你的人物在拾取它的时候会拾取哪个部位,对拾取这个动作其实影响不大,但是对后面手持的影响就很大了。然后把图片拖到中间的大屏幕上,设定合适的大小(位置不用管)
    然后看到下面的Animations栏,要改动名字。
    entity_000,这个是对应着装备的Bank的名字,我们就改成myitem_build吧。
    NewAnimation则对应着Animation的名字,就改成idle吧。
    做完这些,你就可以保存了,注意保存的位置必须要在图片文件夹所在的位置,比如这里就是
    \mods\mymod\exported\ground_myitem
    保存的名字,就是你的装备的Build名,这里就叫myitem_build吧。
    这样一来,物品的地上动画也做好了。

  • 添加手上动画
    在\mymod\exported\下建立一个新的文件夹,名字随意,就叫swap_myitem吧,然后再在这个文件夹下,建立一个新的文件夹,将图片放入其中。此处必须把图片放在文件夹中,不可放在外层。scml文件则必须放在外层。文件夹的名字对应着这个物件的symbol名,这里不妨就填swap_myitem。然后,同3一样,打开spriter,

    • build名改为swap_myitem_build ,这个和后面使用时的代码会要求一致。
    • bank名改为swap_myitem_bank,其实改什么都没关系,不会用到。
    • 重要!Animation名改为BUILD,不可以作任何改动,包括换成小写。
    • 存放手上图片的文件夹(就是相当于第三步里的ground_myitem\下的ground_myitem文件夹),它的名字会涉及到后面代码编辑时symbol的名字,我这里用的是swap_myitem

手上动画和地上动画还有一个很大的区别,就是你在spriter里调节的大小、方向,是不会在手上显示出来的。你的图片里,武器朝向哪个方向,有多大,那么实际到了游戏就维持着相同的样子。所以如果你要改动在手上的武器朝向,只能改图片。
你设定的图片控制点,就是人物的手持位置。比如我把控制点设置在了武器的尖头上,实际效果如下图:
粮荒MOD入门教程(1)-制作一把专属手持武器

如此,就完成了所有的美术准备,下一步就是代码了。

制作手持武器–代码篇

首先我们要给这个新武器起个名字,就叫myitem吧。

  • 在modinfo里填写基本信息
name = "My item example" --Mod的名字
description = "A simple item example" --Mod描述
author = "LongFei" --作者名
version = "0.1"  --Mod版本
forumthread = ""--MOD在klei论坛的下载地址,没有可以留空,但不可删除
api_version = 6--mod的API版本
--priority = -9999 --mod的启动优先级,越低的越晚启动,一般不用设置,除非和其他MOD有冲突需要调整
dont_starve_compatible = true--以下几句,都是设置兼容性的,分别对应DS,ROG,SW和DST
reign_of_giants_compatible = true
shipwrecked_compatible = true
dst_compatible = false

icon_atlas = ""--mod的图标设置
icon = ""--mod的图标图片
  • 在modmain里注册这个武器
    PrefabFiles = {
        "myitem",--PrefabFiles是一张注册表,是用来向游戏注册prefab的,所有的新设定的prefab都必须在这里注册。如果你有多个prefab,就在中间用逗号隔开。prefab在某种意义上可以说是饥荒世界的原子,武器也算是一个prefab,所以也要注册。
    }
  • 编写武器的具体代码
    在\mods\mymod\scripts\prefabs目录下,新建一个lua文件,叫
    myitem.lua,文件名应该要和你在modmain里注册的名字一致。
    打开这个文件,输入以下内容:
local assets=
{ 
    Asset("ANIM", "anim/myitem_build.zip"),--这个是放在地上的动画文件
    Asset("ANIM", "anim/swap_myitem_build.zip"), --这个是手上动画
    Asset("ATLAS", "images/inventoryimages/myitem.xml"),--物品栏图标的xml
    Asset("IMAGE", "images/inventoryimages/myitem.tex"),--物品栏图标的图片
}
--目前我还弄不清楚下面这代码的具体意义,但就先这样空着吧,不能随意乱删,因为有一定的格式要求
local prefabs = 
{
}

local function OnEquip(inst, owner) --当你把武器装备到手上时,会触发这个函数
    owner.AnimState:OverrideSymbol("swap_object", "swap_myitem_build", "swap_myitem")--这句话的含义是,用swap_myitem_build这个文件里的swap_myitem这个symbol,覆盖人物的swap_object这个symbol。swap_object,是人物身上的一个symbol,swap_myitem_build,则是我们之前准备好的,用于手持武器的build,swap_myitem就是存放手持武器的图片的文件夹的名字,mod tools自动把它输出为一个symbol。
    owner.AnimState:Show("ARM_carry") --显示持物手
    owner.AnimState:Hide("ARM_normal") --隐藏普通的手
end

local function OnUnequip(inst, owner) 
    owner.AnimState:Hide("ARM_carry") --隐藏持物手
    owner.AnimState:Show("ARM_normal") --显示普通的手
end


local function fn()--这个函数就是实际创建物体的函数,上面所有定义到的函数,变量,都需要直接或者间接地在这个函数中使用,才能起作用
    local inst = CreateEntity()--创建一个实体,常见的各种inst,根源就是在这里。
    local trans = inst.entity:AddTransform()--给实体添加转换组件,这主要涉及的是空间位置的转换和获取
    local anim = inst.entity:AddAnimState()--给实体添加动画组件,从而实体能在游戏上显示出来。
    MakeInventoryPhysics(inst)--给实体设定为"物品"的物理属性,这是一个写在data\scripts\standardcomponents里的标准函数,类似的还有MakeCharacterPhysics,就是设定"人物"的物理属性,基本上所有会动的生物,都会有MakeCharacterPhysics

    anim:SetBank("myitem_bank")--设置实体的bank,此处是指放在地上的时候,下同
    anim:SetBuild("myitem_build")--设置实体的build
    anim:PlayAnimation("idle")--设置实体播放的动画


    inst:AddComponent("inventoryitem")--添加物品栏物品组件,只有有了这个组件,你才能把这个物品捡起放到物品栏里。
    inst.components.inventoryitem.imagename = "myitem" --物品栏图片的名字
    inst.components.inventoryitem.atlasname = "images/inventoryimages/myitem.xml"--物品栏图片的xml文件。为什么会有这么两句呢?在单个文件下也许会迷惑,但如果换成一个张大图就容易理解了。举个例子,游戏的操作界面,HUD,你可以在data\images下找到HUD.tex,用textool打开就会看到是一整张大的图片,包含了整个操作界面的所有图片,xml就是用来切割分块这张大的图片,并分别给它们重新命名的,新的命名就会被前面的imagename 使用。

    inst:AddComponent("equippable")--添加可装备组件,有了这个组件,你才能装备物品
    inst.components.equippable:SetOnEquip( OnEquip ) -- 设定物品在装备和卸下时执行的函数。在前面定义的两个函数是OnEquip,OnUnequip里,我们主要是围绕着改变人物外形设定了一些基本代码。 在装上的时候,会让人物的持物手显示出来,普通手隐藏,卸下时则反过来。需要注意的是,OnEquip,OnUnequip都是本地函数,要想让它们发挥作用,就必须要通过这里的组件接口来实现。
    inst.components.equippable:SetOnUnequip( OnUnequip )


    return inst
end

return Prefab("common/inventory/myitem", fn, assets, prefabs)--最后,返回这个实体到modmain里注册。Prefab这个函数,第一个参数只需要看最后一个/后面的部分,视为这个prefab的ID,fn则是上面定义的fn,是这个物品的创建函数,assets,对应上面的assets,主要是用于注册美术资源,如果你在这里注册了相应的美术资源,就不需要在modmain里再注册一次。prefabs,目前还未明确具体的作用。

至此,专属武器就算制作完成了。想要测试效果的,可以打开MOD后,进入游戏,在控制台里输入c_give("myitem"),便可获得该武器。下一篇讲如何让武器变成可制作的,以及添加一些常用的功能。