零基础开发 era 游戏 #13 ERH 头文件

本家用法#

宏定义和全局变量 / 常量都是需要预先写在 *.erh 里面的。
读取顺序之前讲过了:config > macro > csv > erh > (erd) > erb。

ERD 是 EE+EM 版特有功能,本文最后会讲。

宏定义 #DEFINE#

类似 C 语言里的「宏定义」,#DEFINE 实际上是在「预处理」这一步发生的。
什么叫预处理呢,就是在 读取脚本之后、解释脚本之前 对宏定义的 文本 进行替换。

宏定义是在「源代码」这个层面直接进行批量的文本(字符串)替换。
常量(constant)最大的区别在于:系统是不会给 宏定义 分配内存空间的。
所以不能把宏定义视为一般的常量。

编辑 ./erb/头文件.erh

#DEFINE 一个宏定义的数值 1 + 2 + 3 + 4
#DEFINE 一个宏定义的字符串 "排,排球比赛。赛,赛程安排。"
#DEFINE 你是一个 "哼 "
#DEFINE 一个一个一个 "啊啊啊啊啊啊啊啊啊啊"
#DEFINE 无言投下 你是一个 + 你是一个 + 你是一个 + 一个一个一个

编辑 ./erb/游戏业务逻辑.erb

@SYSTEM_TITLE
    PRINTFORML 一个宏定义的字符串 = %一个宏定义的字符串%
    PRINTFORML 一个宏定义的数值   = {一个宏定义的数值}
    PRINTFORML 一个复合的宏定义   = %无言投下%
    QUIT

宏定义的边缘效应

不要被这个词唬住了,其实这个概念就是一个很简单的边界问题。
我们都上过小学,乘法分配律都会对吧:

$$ (a + b) × c = a × c + b × c $$

Q:为什么式子前面的 $ a + b $ 要用括号框起来呢?
A:因为「乘除法」计算的优先级比「加减法」高。
如果这里不框起来,实际上就相当于 $ a + b × c = a + (b × c) $,没错吧。

编辑 ./erb/头文件.erh

#DEFINE 安全的宏定义 (10 + 10)
#DEFINE 不安全的宏定义 10 + 10

编辑 ./erb/游戏业务逻辑.erb

@SYSTEM_TITLE
    PRINTL 一般使用是没问题的:
    PRINTFORML 安全的宏定义={安全的宏定义} 不安全的宏定义={不安全的宏定义}
    PRINTL 但是用到复杂的算式中就不一定了。
    PRINTL
    PRINTFORML 把同样的 20 分成 5 份:
    PRINTFORML %"", 2%安全的宏定义(20) ÷ 5 = {安全的宏定义 / 5}
    PRINTFORML 不安全的宏定义(20) ÷ 5 = {不安全的宏定义 / 5}
    PRINTL
    PRINTL 后者为什么会出错呢?
    PRINTL 把式子手动替换一下就一目了然了:
    PRINTL   安全的宏定义 => (10 + 10) / 5
    PRINTL 不安全的宏定义 =>  10 +  10 / 5
    QUIT

变量(动态)#

编辑 ./erb/头文件.erh

#DIM 广域数值变量 = 123
#DIMS 广域字符串变量 = "ABC"

编辑 ./erb/游戏业务逻辑.erb

PRINTFORML 广域数值变量={广域数值变量} 广域字符串变量=%广域字符串变量%

数组 / 多维数组变量

编辑 ./erb/头文件.erh

#DIM 广域数值数组变量 = 1, 2, 3
#DIMS 广域字符串数组变量 = "Aa", "Bb", "Cc"

; 所有数组变量在定义时都是可以手动指定数组大小的
{
#DIMS 广域数组变量的多行写法, 12 =
    "子", "丑", "寅", "卯",
    "辰", "巳", "午", "未",
    "申", "酉", "戌", "亥"
}
; 不能在跨行的花括号内部写注释,会被视为代码,进而产生语法错误

; Emuera 支持的数组最多只有三维,四维及以上的数组不受支持
#DIM 广域多维数组, 3, 3, 3  ; 多维数组不能设定初始值

如果没有手动指定数组大小,则「数组大小」默认为「设定的初始值」的元素数量。
从这个角度来看,实际上 普通变量 = 大小为 1 的数组,而 变量:0 可以简写为 变量
是不是通了?全连起来了。

编辑 ./erb/游戏业务逻辑.erb

@SYSTEM_TITLE
    PRINTFORML 广域数值数组变量   = {广域数值数组变量:0}  {广域数值数组变量:1}  {广域数值数组变量:2}
    PRINTFORML 广域字符串数组变量 = %广域字符串数组变量:0% %广域字符串数组变量:1% %广域字符串数组变量:2%
    PRINTL 广域数组变量的多行写法(跟普通数组一样的用法)
    REPEAT 12
        PRINTS @"%广域数组变量的多行写法:COUNT% "
        SIF COUNT % 4 == 3
            PRINTL
    REND
    广域多维数组:0:1:2 = 777
    PRINTFORML 广域多维数组:0:1:2={广域多维数组:0:1:2}
    QUIT

常量(静态)CONST#

#DIM CONST 数值常量 = 123
#DIMS CONST 字符串常量 = "ABC"

变量 的区别就是 常量 不能重新赋予新的值(进行修改)。
可以理解为「只读」、不能写入的变量。

至于数组常量,当然也是支持的。
另外,由于多维数组不能赋予初始值,因此即便常量支持多维数组也没有意义。

存档变量 SAVEDATA#

同样支持数组,以及多维数组。
需要特别注意的是,当存档变量包括字符串 / 字符串数组时,必须将配置文件修改为:

セーブデータをバイナリ形式で保存する:YES

以二进制格式(而不是纯文本)保存存档文件。

#DIM SAVEDATA SAVE_A_INT = 114514
#DIMS SAVEDATA SAVE_A_STR = "逸一时,误一世(劝谏)"

当执行 SAVEDATA, 存档栏位, "存档名称" 命令的时候,除了已经预设好的角色相关变量,带有 SAVEDATA 关键词的存档变量也会一并被保存。

角色变量 CHARADATA#

编辑 ./erb/头文件.erh

#DIM CHARADATA C_INT_ARRAY, 100
#DIMS CHARADATA C_STR_ARRAY, 100
#DIM CHARADATA SAVEDATA CS_INT_ARRAY, 100

编辑 ./erb/游戏业务逻辑.erb

@SYSTEM_TITLE
    #DIM 角色编号 = 0
    ADDVOIDCHARA 角色编号
    C_INT_ARRAY:角色编号:99 = 9527
    C_STR_ARRAY:角色编号:99 = 嗨嗨嗨
    CS_INT_ARRAY:角色编号:99 = 33
    PRINTFORML C_INT_ARRAY:角色编号:99={C_INT_ARRAY:角色编号:99}
    PRINTFORML C_STR_ARRAY:角色编号:99=%C_STR_ARRAY:角色编号:99%
    PRINTFORML CS_INT_ARRAY:角色编号:99={CS_INT_ARRAY:角色编号:99}
    QUIT

角色变量关键词 CHARADATA 可以与 SAVEDATA 复合,变成可以存档的角色变量。

再强调一遍,存档保存字符串记得要设置 セーブデータをバイナリ形式で保存する:YES

全局变量 GLOBAL#

#DIM GLOBAL G_INT_ARRAY, 100
#DIMS GLOBAL G_STR_ARRAY, 100
#DIM GLOBAL SAVEDATA GS_INT_ARRAY, 100

同样可以与 SAVEDATA 复合,此时再执行 SAVEGLOBAL 命令,除了全局变量 Global.csvGlobals.csv 之外,带有 GLOBAL SAVEDATA 关键词的头文件也会一并被保存到公共通用存档 global.sav

一般用来保存用户在游戏系统内部自定义的偏好设置(所谓「客制化」customization)。

EE+EM 扩展功能#

强力安利这个 EM+EE 改进版。
这是目前功能最强大、设计最先进、更新最勤奋的 Emuera 版本,没有之一。
大家快来用啊。
两位作者都在我们的 Discord 里,有任何问题随时可以反馈。

ERD 功能#

首先需要启用 EmueraEE+EM 的专属配置项 ERD機能を利用する:YES
然后就可以使用全新的 *.erh 定义变量自动加载数据文件(支持 *.erd 文件)机制了。

总结一下就是以平常调用标准 *.csv 数据的方式调用 *.erd 或自订的 *.csv
只要是在 *.erh 头文件里定义过的数组变量,如果有同名的 数组变量名.csv 或者 数组变量名.erd 文件就会对其进行读取,并将其中的设定的值作为该数组变量的索引别名。

注意,以下所有文件都必须UTF-8-BOM 编码。
否则内部解析失败,会导致明明代码没有任何问题,却报错:
"文件名"は解釈できない識別子です 的问题。

编辑 ./csv/WTF.csv

;----------------------------------------------------------------
; 头文件定义的 WTF 数组变量索引名 - WTF.csv
;----------------------------------------------------------------

0,第一项
1,第二项
2,第三项

编辑 ./csv/Data_csv.csv

;----------------------------------------------------------------
; 头文件定义的 DATA_CSV 数组变量索引名 - Data_csv.csv
;----------------------------------------------------------------

0,CSV数据A
1,CSV数据B
2,CSV数据C

编辑 ./erb/Data_erd.erd:(看清楚了,*.erd 文件是放在 ./erb/ 目录下的)

;----------------------------------------------------------------
; 头文件定义的 DATA_ERD 数组变量索引名 - Data_erd.erd
;----------------------------------------------------------------

0,ERD数据A
1,ERD数据B
2,ERD数据C

编辑 ./erb/头文件.erh

;----------------------------------------------------------------
; 头文件 定义广域变量 - 头文件.erh
;----------------------------------------------------------------

#DIM WTF = 111, 222, 333
#DIMS DATA_CSV = "AAA", "BBB", "CCC"
#DIM DATA_ERD = 147, 258, 369

编辑 ./erb/游戏主要逻辑.erb

@SYSTEM_TITLE
    CALL PRINT_DATABASE
    PRINTL
    WTF:第一项 = 1234567890
    DATA_CSV:CSV数据B = 小脚子,露出黑鸡了吧。
    DATA_ERD:ERD数据C = 9527
    CALL PRINT_DATABASE
    QUIT


@PRINT_DATABASE
    PRINTFORML 索引来自 WTF.csv:WTF:0={WTF:第一项} WTF:1={WTF:第二项} WTF:2={WTF:第三项}
    PRINTFORML 索引来自 Data_csv.csv:DATA_CSV:0=%DATA_CSV:CSV数据A% DATA_CSV:1=%DATA_CSV:CSV数据B% DATA_CSV:1=%DATA_CSV:CSV数据C%
    PRINTFORML 索引来自 Data_erd.erd:DATA_ERD:0={DATA_ERD:ERD数据A} DATA_ERD:2={DATA_ERD:ERD数据B} DATA_ERD:2={DATA_ERD:ERD数据C}

lackbfun © 2021 - 2024