本帖最后由 决定吃小菜 于 2022-11-19 03:57 编辑
打开..\script\jymain.lua
不要因为全是英文而恐惧,搜索关键字“故事模式”,你瞧,游戏里出现的中文这里都有。
- function StartMenu()
- local menu = { { "故事模式", Normal_Game, 1 },
- { "挑战模式", Endless_Game, 1 },
复制代码工欲善其事,必先利其器,推荐大家使用IDEA免费的社区版,并且安装EmmyLua插件
一个完整的方法(函数)是被function ... end 包围的
三组中文很明显的告诉我们,一个本地(local)变量menu 就代表了标题页面出现的三个按钮,修改他们就会改变绘制在标题界面的三个按钮文本。对的,目前只能是文本内容的修改,你可以重新起名,例如:原始游戏,肉鸽游戏,退出游戏。
你可能会好奇,为什么双击exe开始游戏代码就会跑到这里运行呢。
被function ... end 包围的方法(函数)想要被执行,一定是存在另一个方法去调用了它,搜索一下StartMenu,区分大小写和词汇完整性后搜索结果应该就剩下3个了,锁定到最上面的。
- function JY_Main_sub()
- ...(省略若干代码)
- local r = StartMenu();
- ...(省略若干代码)
- end
复制代码
再搜索JY_Main_sub
- function JY_Main()
- --主程序入口
- os.remove("debug.txt");
- xpcall(JY_Main_sub, myErrFun);
- end
复制代码
再搜索JY_Main发现已经没有调用它的地方了- lib.Debug("JY_Main start."); --这一行只是输出日志,不在双引号里且后面带()的才是方法调用。
复制代码 其实应该已经发现那行注释,JY_Main已经是主程序入口了,是由更底层的东西调用了它,我们暂时停在这里就可以了。
JY_Main
就两行代码,我们可以非常轻松的读懂,下面就一行一行的解读这个方法里都做了什么。
复制代码 其实lua语言中不需要用分号(;)作语句结尾,敲了回车就会自动认作下一行
os是lua官方提供的库,你可以随时随地任意调用。这一行是把debug.txt文件删除了,也就是你每次启动游戏,上一次游戏产生的日志都会被清除干净,所以当你遇到闪退时千万别着急启动游戏,先阅读debug.txt确认问题所在。如果没有这一行代码,你的debug.txt文件就会越来越大,直到干爆你的硬盘。xpcall(JY_Main_sub, myErrFun)
这一行是捕捉游戏运行中产生的bug,将bug产生时的相关信息写入debug.txt以便作问题分析。xpcall也是官方提供的方法,官方为我们准备了很多常用方法,如同Photoshop里也给你预先做好了很多不同画笔效果。myErrFun里就很简单,只是把错误信息打印出来。下面回到JY_Main_sub
os.开头的方法都是lua官方为我们写好的,而lib.开头的方法则是金群lua复刻版底层特有的c++实现,都是了解功能后直接使用即可,暂时不需要关心内部实现
JY_Main_sub
这个方法一下子就变得复杂起来,所以我们可以暂时聚焦在我们关心的事情上,其他代码统统略过不看不研究
还记得我们的初心不?标题界面是怎么绘制出来的。
先看这几行代码:
- JY.Status = GAME_START; -- 修改了游戏状态
- Cls(); -- 画面重制,之后重点看这个
- PlayMIDI(16) -- 播放背景音乐,文件都在..\sound\目录下
- lib.ShowSlow(50, 0) -- 画面从黑色渐渐显现,这个效果打开游戏时仔细观察就能体会到。
- local r = StartMenu(); -- 标题按钮相关
复制代码 游戏状态是我们人为去定义的,是为开发者自己服务帮助我们去记忆状态,任何程序都有其生命周期,每个时期该做什么不该做什么都定好了程序才能健康的运行。
游戏音乐都在sound目录里,我们直接用电脑上的音乐软件打开game17.MID去听就是标题界面播放的那首。游戏毕竟不是音乐软件,没有太多复杂功能,就只有播放,每次调用会从头开始播放、会覆盖正在播放的。
重点看Cls(),这里藏了我们要找的东西。
Cls
源码中随处可见的方法,非常重要,但现在我们只需要理解,标题界面显示的图片是在这里定义的。
- function Cls(x1, y1, x2, y2)
- ...(省略若干代码)
- if JY.Status == GAME_START then
- lib.FillColor(0, 0, 0, 0, 0);
- --开场默认贴图
- lib.LoadPicture(CC.FirstFile, 1, 1, CC.ScreenW / 640 * 100);
- elseif JY.Status == GAME_MMAP then
- ...(省略若干代码)
- end
复制代码
还是一样,我们只需要专注于当前关心的代码即可。
可以看到lua方法即使定义了参数,在调用时也可以不传
前面JY_Main_sub定义的游戏状态在这里发挥了作用。
当状态是GAME_START会执行两行代码,其他代码现在完全没必要看。
lib.FillColor顾名思义,是填充颜色,那就要问了,往哪里填充,填充什么颜色?
后面紧跟的5个参数就是为我们解决这些问题,我们给这5个参数命名,lib.FillColor(x1, y1, x2, y2, color)
把屏幕看作左上角原点的坐标系,x轴左正右负,y轴下正上负,这4个坐标值围成的区域就是填充的区域,最后的color就是填充的颜色。
坐标都是0就会自动填满游戏窗口,颜色0就是黑色(其他颜色怎么填可以自行思考一下)
可以做一个小测验,临时写一些测试代码看看效果如何,我在底下追加了四行代码,你能预测出会有什么效果吗?
- function Cls(x1, y1, x2, y2)
- ...(省略若干代码)
- if JY.Status == GAME_START then
- lib.FillColor(0, 0, 0, 0, 0);
- --开场默认贴图
- lib.LoadPicture(CC.FirstFile, 1, 1, CC.ScreenW / 640 * 100);
- lib.FillColor(0, 0, 100, 100, C_RED);
- lib.FillColor(200, 0, 300, 100, C_RED);
- lib.FillColor(0, 200, 100, 300, C_RED);
- lib.FillColor(200, 200, 300, 300, C_RED);
复制代码
真实运行效果如下图:
其实就是在图片上画了四个红色正方形,为什么会在图片之上呢,废话,因为代码在绘制图片之后啊!没错,代码的运行先后是直接影响绘制顺序,如果你发现你写的代码似乎运行后没有效果,就要考虑是否被覆盖了。
下一行代码,lib.LoadPicture就是用来加载图片,第一个参数是图片文件路径,然后是坐标xy,最后是缩放参数,有些新的mod可能不支持缩放不能传。
标题界面引用的图片就是..\pic\title.png,可以直接用系统图片查看器查看。
至此标题界面我们解析完了。
|