前言

原贴写于饥荒游戏贴吧,为了使文章针对性更强,将原文切割并精简。此贴主要为编程0基础的modder讲解一些编程的基础知识。至于说有关饥荒框架的介绍,则会放在另一篇文章里讲解。

编程0基础的人,要想学习制作MOD,难度是比较大的,因为缺乏一些基本的编程概念,只懂得复制别人的代码或者在它们的基础上稍加改变,遇到稍微复杂一点的代码,就束手无策了。对于MOD崩溃或错误,也几乎没办法自行处理。但我也不推荐先去学一门编程语言之后再来学习MOD代码,这是没有必要的。事实上饥荒MOD里用到的基本编程知识都比较简单,所使用的lua语言相比c之类的强类型语言,也已经做了许多简化。单纯想要做MOD的话,只需要了解一些基本知识和概念就可以了。

以下内容全部基于lua语言。

标识符

一个名字

给常量,变量,函数,类一个名字,这样我们才能通过名字来使用它。一般使用英文字母、数字和下划线的组合来命名。

推荐命名规则

常量:每个字母都是大写,在每个单词之间加下划线。

变量和函数:第一个单词首字母小写,后续单词的首字母大写,其他都是小写。

类:所有单词首字母大写。

这个只是个人推荐的命名规则,读者可以根据自己的喜好决定命名规则。

变量

可以通过符号’=’赋值改变的量。

典型代表:人物的饥饿值。这个值在游戏里几乎每时每刻都在不停变化着,这样一来,我们就可以根据不同的变化,设置不同的效果,比如沃尔夫冈不同的饥饿值会有不同的形态,这个就是通过检测饥饿值来实现的。

常量

程序运行时,不会被改变的量

实际上,lua语言里没法自己定义常量。但是,对于某些量,我们不需要在游戏运行的过程中改变,又需要引用它。比如说长矛攻击力,在游戏过程中不需要改变,但官方所做的所有的武器的攻击力都是长矛攻击力的某倍数,这又需要引用它进行计算。这时候,不妨就把长矛攻击力看作是一个常量,用一个变量将其定义下来(SPEAR_DAMAGE,这个定义在tuning.lua里)

作用域

变量的生效区域。

在作用域以外的域内,如果你引用这个变量,又没有域内的同名变量,就会造成出错。

lua中对一个变量的作用域只有两个选项:local 和global。默认不加local修饰的变量为global(全局)变量,加了local的为局部变量。全局变量的作用域为整个程序。局部变量的作用域则在所定义的域中。一个选择控制结构内,一个函数体内,或者一个文件内,都是一个域。

这个作用域的主要价值在于,使得系统免于混乱。比如说,在被攻击的时候,需要计算所受到的伤害,为了方便进行多次计算,我们把这个数值设置为一个变量。但是,面对的敌人的攻击力会有变化,自身的防具减伤也会有变化,这时候我们就希望,计算结束,变量被引用到血量变化之后,这个变量能消失掉,不会影响我们下一次计算其他的伤害。这就是局部变量的重要作用。当然,局部变量还有另一个好处就是读取它的数据,要比全局变量快一些,不过,提高MOD性能不是本篇教程的重点,就不详细展开了。总而言之,全局变量,不到必不得已的情况,应当尽可能少用。

在上面我多次提到了声明和引用,可能有些人不太清楚这两个术语的意思。我这里就顺带把定义和赋值一起讲了。

定义和声明

定义,就是告诉系统,我设置了的这个变量/常量是什么。

声明,就是告诉系统,我设置了一个变量/常量,你给我记好了。

定义和声明是不一样的,但常常会混在一起。如果你只是想写写mod的话,不了解他们的区别也没关系,只认为是定义就够了。

引用

引用就是告诉系统,我要用这个变量/常量来做某某事。

比如说用于某个表达式的计算,系统就会帮你读取储存在其中的数据。

赋值

赋值就是告诉系统,往这个变量/常量里存入你给出的数据。

注意,此处的数据,不仅仅指数字,可以是lua语言允许的任何类型,比如说一段文字(字符串),一个布尔值(真或假)等等。在某些语言比如C语言中,定义和赋值是可以分开的。但在饥荒MOD的脚本语言lua中,这两者是连在一起的。对一个变量的第一次赋值,就是对它的定义了。

数据类型

对变量赋值,就是给它写入数据,那就涉及到了数据类型的问题。在初次赋值给一个变量时,所给予的值的数据类型,就是变量的数据类型。此后再给这个变量赋值,就必须赋予同一数据类型的值,如果值不同,就会导致系统崩溃(除了nil)。这里不展开细讲,只针对lua语言,简单地列出MOD中常用的几种类型

nil:表示无效值,可以给任何数据类型的变量赋这个值。实际效果相当于删除这个变量

boolean:包含两个值:false和true(假和真)

string:字符串,用一对双引号或单引号括起来

function:函数,这个会在下面讲

table:表,这个概念会在后面讲

函数

这是编程里的一个非常重要的概念。

函数与变量的区别,可以做这样的类比:一个变量,就好比是一个属性,你可以给一个客体以某个属性,让它可以被描述,比如说,属性:可以被烧毁。而函数,则是一种操作方法,你让一个客体拥有一个函数,就是让它有某种操作。比如说,操作方法:被烧毁的具体步骤和操作。

函数由函数名,参数表和函数体组成。函数也和变量一样,能被引用,也有作用域。不过与变量不同的是,函数需要单独定义,在不同的编程语言中,函数的定义格式不一样,但都少不了上面所说的三个基本组成。在lua中,函数也可以看成是变量,可以被赋值。另外,函数可以有返回值,也就是把计算的结果返回,供另一个函数或者表达式使用。

Lua中,函数定义的基本格式如下为:

function 函数名(参数表)

函数体

end

如果希望函数的作用域是局部的,则在function 前面添加local。这样,你将无法在其作用域之外调用该函数。

函数是怎样工作的呢?首先,你需要明白,定义函数并不会让函数工作。只有执行了函数语句才会让它工作。还是拿计算伤害来做例子。你定义了怎么计算伤害的函数,参数为攻击者的攻击力和防御者的护甲。这个函数在定义之后,本身并不会立刻工作。只有你设定了一系列的流程,让函数在出现攻击状态的时候触发,才能算是执行了这个函数。函数执行的时候,输入了两个参数:攻击者的攻击力和防御者的护甲。在函数体中,经过一系列的计算,得到了结果,利用return返回来,由变量接收或者加在各种表达式里使用。需要注意的是,即使是没有参数的函数,在执行时,也必须写成这样的形式: 函数名(实际参数表)

代码例子:

--定义了函数caldamage,但没有执行

function caldamage(attack,armor)

return attack-armor

end

local damage = caldamage(10,8) --这里执行了函数caldamage,并把计算的结果返回,赋值给damage

函数的作用是什么呢?就是使得你的编程显得更有逻辑,模块化,还能减少代码的使用量。定义好一个函数之后,就不再需要管这个函数里面详细的执行过程(也就是函数体写了什么),我们只需要知道这个函数的名字,参数表和返回值,和这个函数有什么作用。因为在饥荒的MOD中,大量的函数是没有返回值的(也就是返回值为nil),执行这样的函数,目的在于使用它的功能。

函数是做饥荒MOD时最重要的东西。我们做MOD,主要的目标就是修改或者向游戏添加函数。了解这些函数在什么时候会触发,需要哪些参数,有什么功能,返回值是什么,是非常重要的。

我们是在原游戏的基础上做MOD,也就是说,有很多已经定义好了的函数可以供我们使用。打个比方,饥荒这个游戏,就好比一部车,函数就是这部车上面的零件,它让这部车能够拥有某些功能:启动,刹车等等。我们现在觉得这部车不能满足我们的需要了,那么,很显然的,做适当的改装,要比重新造一部车容易。做MOD,就好比是做一些改装。既然是改装,那你就有必要了解到,你所需要改装的部分,需要哪些零件。有些核心零件是非要弄清楚不可的。

现在饥荒MOD本身的结构是非常开放的,但官方没有给出详细的说明文档,当我们想要实现一项功能的时候,我们不知道官方有没有给出来,怎么办呢?我的建议是,思考一下游戏里的各种功能,以及他人已经发布的MOD,有没有和你的需求类似的,去参考一下相应的代码。易宁修改也是一个很好的参考,但易宁修改毕竟是直接修改游戏的核心文件,与MOD还是有一些区别的,所以要使用的话,前提是理解其含义。

表不是一门编程语言的必须概念,但这个概念在饥荒MOD里使用得非常频繁。游戏的整个框架,也非常依赖于表。表的重要作用也和函数一样,是为了让你的编程显得逻辑清晰。比方说,现在有4个个体,a,b,c,d,有多项属性描述:health、sanity、hunger、damage、armor、attack_period、walkspeed、runspeed。这些属性,对于4个个体来说,有的有,有的没有,我们要怎么组织起来呢?用多张表连起来,就是一个好主意。首先,我们来给属性分一下类,health、sanity、hunger是饥荒中的三大基本属性,各自单独成一类,damage、armor、attack_period是和战斗有关的,分类为combat,至于walkspeed、runspeed则是和移动有关的,分类为locomotor。那么,我们就有多张表了:

一张总表: 个体属性表

属性

a

b

c

d

health

a的血

b的血

c的血

d的血

sanity

a的精神

b的精神

c的精神

d的精神

hunger

a的饥饿

b的饥饿

c的饥饿

d的饥饿

combat

a的战斗属性

b的战斗属性

c的战斗属性

d的战斗属性

locomotor

a的移动属性

b的移动属性

c的移动属性

d的移动属性

这个表中的每一个元素,都是一张表,现在不妨取a的战斗属性表出来,是这样的: 个体属性表

damage

armor

attack_period

数值

20

50

3

那么,我们想要引用a1的damage的时候,怎么办呢?先在总表第一横栏中找到a,然后在竖栏中找到combat,这样我们就得到了提示:转去找a1的战斗属性表。然后在战斗属性表中,我们在横栏中找到了damage,这时候竖栏中只有一项,就不必再查找了。我们在查找过程中,寻找的a,combat,damage 就是所谓的索引。我们按先横后竖的顺序查找的,a为1级索引,combat为2级,damage为3级。按顺序最后找到damage的具体的值(20),就是所谓的值。这个值不仅仅是数值,比如说在总表中找到的a的战斗属性表,也可以称为值。再拓展一些,如果说战斗属性表中的竖表不只有一项,而是有两项:max,min,此时我们想要查damage最大值,该如何呢?那就要增加一个四级索引max。当你想要引用a的伤害最大值时,在编程里的调用语句,你就可以写a.combat.damage.max

结合饥荒Mod编程,我们常常会看到类似这样的一条语句

inst.components.sanity:DoDelta(-10)`

这句话的意思是当前对象的精神减10。

具体是怎么操作的呢?首先,游戏里这么多个体,要在茫茫人海中找到你,必须要有个名字,这个名字就是inst,然后,inst下有很多属性类,我们需要的精神值,归类为components,也就是组件。组件这个概念,是饥荒为了编程上的逻辑清晰而创造出来的一个概念,会在介绍饥荒编程框架的文章里详细说明。然后我们继续在components表里找包含着精神值和操作精神值的函数的表,就是sanity。这时候你可以看到sanity后面是冒号:而不是之前的那些点号. 这是因为,我们是希望执行这个函数。如果是想要引用这个函数做其他操作的话,还是要用点号. 的。学过C++的人都会了解类的概念,对这个肯定不陌生。没学过的人呢,看我在下面关于类的解释。

类和面向对象编程

类这个概念,就是在面向对象编程的思想上发展起来的。为什么要使用类呢?就是因为面向对象编程显得逻辑结构清晰,易于实现、互动和维护。那么,什么是一个类呢?在编程上,可以理解为一些变量和函数的集合。这个集合是封装起来的,其中有一些变量和函数你可以访问和引用,称为公有变量和公有函数,还有一些是你访问不到,也无法使用的,就是私有变量和私有函数。需要注意的是,类本身只是一个逻辑结构,并不是实体。用现实的东西举个例子,自行车就是一个类的概念,它有很多基本属性:颜色,材质等等,也有很多操作:骑、前进、刹车等等。属性就是变量,操作就是函数。颜色、材质,是你能够看到的,就是公有变量,而内部的转盘的颜色你看不到,就是私有变量。而骑和刹车的操作,是你能够决定的,就是公有函数。而前进这个操作,你没法直接进行,你必须要反复踩踏板,才能让自行车前进,所以前进就是私有函数。在头脑中想到自行车这个概念,就是类。而想到你的自行车,就是一个具体的实体。

结合到饥荒MOD里,sanity这就是一个类,这里面有很多属性:当前精神值,最大精神值等等,也有很多操作:精神增加/减少,设置当前精神值,设置最大精神值等等。而具体到一个人物的sanity,那就是这个类的实体了。

实际上,在lua里,只有表,没有类这个概念。但是饥荒的游戏制作者为了编程方便,还是用某种手段,在表的基础上,类这个概念创造出来了。我们只需要认识到,怎样使用一个类就可以了。

引用类中的变量,操作方法就和引用表中元素一样。如果想要调用函数,则需要将点号.改成冒号:,并且在函数名后面添加(函数参数表)。

比如说人物的当前精神值,人物的最大精神值等等,同时也有一些操作函数,比如上面举例的DoDelta。我之前说过了,在lua里,函数也可以看成变量。如果你想要引用这个函数,比如说引用去给一个函数赋值,那么,上面的冒号:就要改成点号.,而且后面的”(-10)”也要去掉。如果你想要执行这个函数,那就要用冒号: 并且添加相应的参数。

以上就是全部的0基础入门内容了。

理解了这部分内容,就可以去看下一篇,饥荒MOD框架概述了。

c语言写类似饥荒的游戏,饥荒MOD lua编程0基础入门相关推荐

  1. c++ 小游戏_C/C++编程笔记:C语言写推箱子小游戏,大一学习C语言练手项目

    C语言,作为大多数人的第一门编程语言,重要性不言而喻,很多编程习惯,逻辑方式在此时就已经形成了.这个是我在大一学习 C语言 后写的推箱子小游戏,自己的逻辑能力得到了提升,在这里同大家分享这个推箱子小游 ...

  2. 好玩的c语言编程游戏,C语言写个贪吃蛇游戏

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 C语言写个贪吃蛇游戏 贪吃蛇是个非常经典的游戏,用C语言来实现也是一个好玩的事情.这个游戏我写完后放在知乎,竟然点赞的人数超级多.我觉得大家喜欢,一个方面 ...

  3. 【笔记】用vs2017 c语言写 贪吃蛇 小游戏

    目录 文章目录 前言 一.贪吃蛇游戏 设计逻辑 二.详细介绍 1.设置界面(界面大小,背景颜色) 2.设置贪吃蛇的身体并显示 3.使之能够移动并能够穿墙 4.添加食物并让蛇吃掉 5.设置背景音乐 完整 ...

  4. ChatGPT实现用C语言写一个扫雷小游戏

    前几天我们利用 ChatGPT实现用C语言写一个学生成绩管理系统 其过程用时不到30秒,速度惊人 今天又让ChatGPT用C语言写了一个扫雷小游戏,它的回答是:抱歉,我是AI语言模型,无法编写程序. ...

  5. c语言写的黑白棋游戏代码,C语言编写的黑白棋游戏源代码..doc

    C语言编写的黑白棋游戏源代码. C语言编写的黑白棋游戏/*3.3.4 源程序*/ #include "graphics.h" /*图形系统头文件*/ #define LEFT 0x ...

  6. c语言游戏总出bug,C语言 编写的简单移动游戏出现bug?_编程_游戏设计_C语言_天涯问答_天涯社区...

    C语言 编写的简单移动游戏出现bug? 第一次按上下左右没什么问题,之后就会卡住..不知道出了什么错 源码如下:(用vc++的win32 console程序编写) #include #include ...

  7. 使用Python写俄罗斯方块,以游戏的方式学习编程

    本文将用Python写一个终端版俄罗斯方块,用游戏的方式学习编程. 这个小游戏分享给学习Python的朋友,感受一下Python的魅力,锻炼编程思维. 更多小游戏请看 这里. 演示效果图见下文. 代码 ...

  8. 【游戏开发】Lua Love2d | Love2d基础知识

    小提示: 此系列文章属于个人学习笔记,如果其中有误,希望大家指正. 也希望大家能够提出一些游戏开发学习上的建议等等的~ 谢谢大家!(๑•̀ㅂ•́)و✧ 教程简介: 了解如何使用 LOVE 2D 和 L ...

  9. bat贪吃蛇游戏代码_C语言写个贪吃蛇游戏

    贪吃蛇是个非常经典的游戏,用C语言来实现也是一个好玩的事情.这个游戏我写完后放在知乎,竟然点赞的人数超级多.我觉得大家喜欢,一个方面是因为写得简单,大家都能看得懂,一个可扩展性还是非常强的. 我试了说 ...

最新文章

  1. Android异步处理二:AsynTask介绍和使用AsyncTask异步更新UI界面
  2. 【图解】一图了解《上海市推进新一代信息基础设施建设 助力提升城市能级和核心竞争力三年行动计划(2018-2020年)》...
  3. 云管理成功的关键:应用工作流
  4. JS 原型链 prototypt 和隐式原型 _proto_
  5. python操作微信小程序云端数据库_微信小程序·云开发云数据库的基本使用-微信小程序云开发实例-腾讯云微信小程序...
  6. 几个有趣的python技巧
  7. REVERSE-PRACTICE-BUUCTF-25
  8. RedHat Linux 7.3基础环境搭建
  9. 山东工业大学计算机及应用,彭玉旭副教授
  10. sql中exists,not exists的用法 1
  11. 10098 - Generating Fast
  12. 中医针灸学综合练习题库【2】
  13. 美通社企业新闻汇总 | 2019.1.16 | 微软与药店巨头沃博联达成战略合作,科勒中国第13家工厂落成...
  14. docker X509 证书错误的终极终极终极解决
  15. 解决CPU风扇转速为“0”的问题
  16. go语言消息推送服务器,Golang 消息推送系统
  17. matlab示波器模拟,[转载]利用MATLAB命令窗口绘制Simulink仿真示波器波形的方法
  18. 【单片机】4.3 中断允许与中断优先级的控制
  19. Python3D绘图后用自带展示器查看(可旋转)
  20. Python:生成随机偏态分布

热门文章

  1. MAC电脑中屏幕录制软件Camtasia[破解版]
  2. 淘宝店铺(宝贝描述模板)克隆攻略
  3. exfat默认配置大小_U盘exFAT格式好不好?格式化分配单元大小多少合适?
  4. 零基础nodejs部署web网站
  5. matlab角接触球轴承和圆锥滚子轴承轴承寿命校核
  6. FPGA的亚稳态跟MTBF
  7. 数值分析-秦九韶算法
  8. 课程学习--英语口语--第1讲--英文演讲--马云在香港大学毕业致谢词
  9. 飞行机器人专栏(十二)-- 提高机器人系统可靠性的关键要素与实践
  10. 爬取豆瓣TOP250-避免反爬虫(2021-10-09)