零基础开发 era 游戏 #3 开发环境配置

工欲善其事,必先利其器。

其实任何文本编辑器都可以,只要你最后写出来的符合语法就行,Emuera 并不在乎你是用什么写的。
理论上你用 Windows 自带的「记事本」/「写字板」也是遵循相同的语法、写类似的内容,一样能做出新的 era 游戏。
但是何必呢?折磨虽小,痛苦永存。

这里简单介绍两个我(最中意)用得最顺手的文本编辑器。

Sublime Text#

资源请自行准备。

Sublime

其实破解 sublime 很简单,以二进制形式打开可执行文件(sublime_text.exe)改几个字节码就行了。但我不敢在写在这里(DMCA 警告)。
实在找不到可用资源又不想交那笔巨贵的保护费的话,建议使用免费的 VS Code。
VS Code 天下第一。

  1. Ctrl + Shift + P 打开命令面板。
  2. 输入 Install Package ControlEnter 安装包管理器「Package Control」。
  3. 安装完成后 Ctrl + Shift + P 打开命令面板。
  4. 输入 install 选择 Package Control: Install Package
  5. Enter 进入「安装包输入界面」。
  6. 继续输入 erabasic 安装代码高亮插件。

Sublime Text 的优势在于轻量,启动速度和内存占用比起 VS Code 来说都优秀得多。
缺点在于过于轻量,缺少很多便捷功能,插件安装 / 使用起来也远远不如 VS Code 简便。
而且插件市场也没有 VS Code 丰富。VSC 的话,只要你能想到的功能,基本上都有现成。
所以总的来说还是推荐使用 VS Code。

Visual Studio Code#

都说谷歌 / 苹果的砍刀部砍了多少多少项目,微软砍的一点也不少好吧。
还好 VS Code 活下来了,希望微软现在在测的 Loop 也能活下来 🙏。

微软家的良心软件:

  • 文(轻度使用)可当纯粹的文本编辑器
  • 武(重度使用)可调教成 IDE(集成开发环境)

VS Code

  1. 下载并安装完成后 Ctrl + Shift + P 打开命令面板。
  2. 输入 Preferences: Open User Settings (JSON) 打开自定义配置文件。
  3. 调成你顺手的设置,具体可以自行搜索「VSCode 配置」,此处不再赘述。

熟悉之后继续配置我们需要的、其他一些提升「era 游戏开发体验」的小细节:

  1. Ctrl + Shift + X 或点击图标按钮打开「扩展」侧边栏。
  2. 搜索 erabasic 扩展并安装。
    这时候就已经有代码高亮、自动补全、函数跳转……等等非常实用的开发辅助功能了。
  3. 再次打开配置文件(具体步骤参考上文),为 era 开发特别配置:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
  // 默认字体好像是 'Fira Code' 吧我记得
  // 以下是我使用的字体
  // 显而易见 你需要安装对应字体到本地电脑才能用上
  "editor.fontFamily": "'Ubuntu Mono derivative Powerline', 'Noto Sans SC', Consolas, monospace",
  // = 测试字体是否等宽,以及中英文是否等距(两个字母 = 一个汉字)。如果是的话两边等号应该对齐→ =
  // = 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,.'"`!?:;_\|&^()[]{}<>%+-*/ =
  "editor.fontSize": 18, // 字体大小
  "editor.tabSize": 2, // 缩进大小 随便 爱多少多少

  // 重点来了
  "[erabasic]": {
    // 只对 *.ERB / *.ERH 文件生效的配置
    "editor.detectIndentation": false, // 根据第一个 tab 来设置其他的空格,注意是关掉
    "editor.renderControlCharacters": true, // 渲染制表符,tab 会显示为 -> 箭头
    "editor.renderWhitespace": "all", // 渲染空格,space 会显示为 - - 省略号
    "editor.tabSize": 2, // 缩进大小 设置为 2 便于阅读复杂的多层嵌套代码
    // 几乎所有以缩进界定代码块的语言我都会设置成 2 格缩进,只有 Python 这种只认 4 格的奇葩例外
    "editor.insertSpaces": false, // 插入 tab 用空格代替,最好关掉以使用 tab,方便硬排版
    // 妈的 Emuera 根本不认缩进,无论有没有缩进,无论缩进是 tab 制表符(\t) 还是空格,都能正常运行
    // 哪怕你根本没有缩进也能运行,所以缩进其实是给你自己看的
    "files.encoding": "utf8bom" // 关键!设置默认使用的文件字符集编码为 UTF-8-BOM
    // Emuera 只认得出「带字节序」的 UTF-8,一般称之为 UTF-8-BOM 或者 UTF-8-SIG
    // 如果字符集编码不对 中文和日文字符会显示为乱码
  },
  // 重点走了

  "editor.formatOnSave": true, // 保存时自动格式化代码
  "files.autoSave": "onFocusChange", // 窗口失焦时自动保存文件
  "files.insertFinalNewline": true, // 文件末尾添加空行,以兼容一些落后程序的 EOF 问题,对我说的就是 eramaker
  "files.trimTrailingWhitespace": true // 自动清除多余的空格
}

Tips#

  1. Ctrl + F 在当前文件中搜索关键词。
  2. Ctrl + Shift + F 在整个项目的所有文本文件中搜索关键词。

一个关于自动删除多余空格的小坑#

最后的 "files.trimTrailingWhitespace": true 需要特别注意一下。
如果代码习惯不好,建议改成 false

什么叫代码习惯不好?比如

PRINT 你吃牛肉干    ← 注意行尾的空格
PRINT 嘛?

预期的显示应该是 你吃牛肉干   嘛?;但如果开启「自动清除多余空格」功能就会变成

PRINT 你吃牛肉干 ← 我空格呢?
PRINT 嘛?

最后显示为 你吃牛肉干嘛?
玩家可能会懵逼「我吃牛肉关你什么事?牛跟你告状了?」造成误解。

代码习惯好的话不应该直接硬打空格强行排版,而是采用更为稳妥和优雅的写法(俗称提高项目「健壮性」Robustness最早的鲁棒性是哪个傻逼翻译的 ),比如

PRINTFORM % "你吃牛肉干", 20, LEFT % ← 随便它怎么修空格
PRINT 嘛?

我暂时只想到这种可能稍微影响游戏体验的问题,实际开发中你可能会遇到更恶劣、更难以处理、甚至根本就无从下手让人摸不着头脑的 bug。
无尽的调试(debug)是开发中不可避免的一环,无法接受的话趁早退坑保平安。

调教完成,享受辅助功能拉满的偷税的开发过程吧。
乐观点说,这套应该是目前最舒适最优雅的 era 开发环境配置了。

在安卓手机上进行开发#

用手机写 era 游戏,乍一听,这像是某种玩笑话;但我非常郑重地告诉你,并不是。
它是一个客观长期存在的需求。

众所周知,有相当一部分约有 30%人偏爱使用手机(uEmuera / XEmuera)游玩 era 游戏。
其中又有部分喜欢折腾的深度玩家,期望在手机上直接查看 / 修改 era 游戏的源代码。

我知道这个现象的存在(收到过数次反馈),但一直没有去尝试解决。
因为我自己是没有这个需求的(我甚至几乎不用手机玩 era 游戏),所以不怎么上心。
而且个人思维惯性是这样,比较前沿。一说「手机开发 era」,我脑子里直接蹦出来的方案是最新的技术栈:部署一个 在线版 VS Code,然后直接在手机上通过浏览器访问。
(这个折腾起来有点麻烦的,懒癌一犯就摸了。)

直到 2022 年 8 月初,我在查背景资料的时候,偶然间在 era 日文 Wiki 发现,这个页面竟然推荐了安卓端的编辑器:

Jota+ Text Editor
Android 用テキストエディタ。
有志の手によりシンタックスハイライト設定ファイルが配布されており、
これを適用すると ERB 構文が色分けされる。
Google Play

安装#

简单调研了一下,「Jota+」是安卓平台上一个代码(文本)编辑器,完成度还算不错。
当然,我看上的主要是内置编码转换 / 自定义代码高亮这两个功能。

它的前身是「Jota Text Editor」,最新版为「Jota+ β」。
不过「Jota+ β」需要购买 PRO 使用凭证,白嫖的话还是用免费的「Jota+」就好。
(有一说一,就这点东西,660 円确实有点小贵。)
点击直接下载 apk 文件

至于代码高亮,遗憾的是前人写好的配置文件已经在曾经的 旧储备库爆炸事件 中佚失了。

Jota+ Text Editor 用 シンタックスハイライト設定ファイル (リンク切れ)

但是没关系,我可以现写一个。

配置#

在手机存储空间新建文本文件 /sdcard/.jota/keyword/user/csv.erh.erb.erd.conf

#
# EraBasic keyword file for Jota Text Editor.
#
# This file is in the Public Domain and distributed on "AS IS" basis.
#
# https://lackb.fun/era/era-diy-tutorial-3-editor/

author=lackbfun
version=0.1.0
comment=\[SKIPSTART\].*?\[SKIPEND\]
weakcomment=^\s*(;[!#];)?\s*\[SKIPEND\]|^\s*(;[!#];)?\s*\[SKIPSTART\]
linecomment=(^\s*|[^!#]);(?![!#];)[^\r\n]*
string="(\\\"|.)*?"|%(\\%|.)*?%
type=@[^,\(\r\n]*
constant=\b(SAVEDATA|CHARADATA|GLOBAL|DYNAMIC|STATIC|CONST|REF)\b
statement=\[IF[^\r\n]+\]|\[ENDIF\]|\b(PRINTDATA[KD]?[LW]?|STRDATA|ENDDATA|DATALIST|ENDLIST|NOSKIP|ENDNOSKIP|S?IF|ELSE(IF)?|ENDIF|SELECTCASE|IS|TO|CASE|CASEELSE|CONTINUE|BREAK|REPEAT|REND|FOR|NEXT|WHILE|WEND|DO|LOOP|CATCH|ENDCATCH|TRYC(CALL|JUMP|GOTO)(FORM|LIST)?|ENDFUNCGOTO|FUNC|ENDUFNC)\b
number=\b[0-9.]*\b|\d+p\d+|\{(\\\}|.)*?\}
operator=(!|'?=|>|<|\+|-|\*|\/|%|&|\||\^|:)
green=
blue=\b(PRINT(FORM)?(V|S)?(K|D)?(L|W)?|PRINTSINGLE(FORM)?(V|S)?(K|D)?|PRINTBUTTON(C|LC)?|PRINT_ABL|PRINT_TALENT|PRINT_MARK|PRINT_EXP|PRINT_PALAM|PRINT_ITEM|PRINT_SHOPITEM|UPCHECK|DRAWLINE|CLEARLINE|PRINT_IMG|PRINT_RECT|PRINT_SPACE|SETCOLOR|SETCOLOR|RESETCOLOR|SETBGCOLOR|SETBGCOLOR|RESETBGCOLOR|GETCOLOR|GETDEFCOLOR|GETBGCOLOR|GETDEFBGCOLOR|GETFOCUSCOLOR|FONTBOLD|FONTITALIC|FONTREGULAR|FONTSTYLE|GETSTYLE|CHKFONT|SETFONT|GETFONT|FORCEKANA|ALIGNMENT|CURRENTALIGN|REDRAW|CURRENTREDRAW|PRINTCPERLINE|LINEISEMPTY|BARSTR|MONEYSTR|SKIPDISP|ISSKIP|MOUSESKIP|TOUPPER|TOLOWER|TOHALF|TOFULL|TOSTR|ISNUMERIC|TOINT|STRLENS|STRLENSU|SUBSTRING|SUBSTRINGU|CHARATU|STRFIND|STRFINDU|STRCOUNT|SPLIT|REPLACE|UNICODE|POWER|ABS|SIGN|SQRT|GETBIT|MAX|MIN|LIMIT|INRANGE|SETBIT|CLEARBIT|INVERTBIT|ADDCHARA|DELCHARA|SWAPCHARA|SORTCHARA|GETCHARA|ADDDEFCHARA|ADDVOIDCHARA|DELALLCHARA|PICKUPCHARA|EXISTCSV|FINDCHARA|FINDLASTCHARA|COPYCHARA|ADDCOPYCHARA|VARSIZE|RESETDATA|RESETGLOBAL|RESET_STAIN|SWAP|CSVNAME|CSVCALLNAME|CSVNICKNAME|CSVMASTERNAME|CSVBASE|CSVCSTR|CSVABL|CSVTALENT|CSVMARK|CSVEXP|CSVRELATION|CSVJUEL|CSVEQUIP|CSVCFLAG|GETNUM|GETPALAMLV|GETEXPLV|FINDELEMENT|FINDLASTELEMENT|VARSET|CVARSET|ARRAYSHIFT|ARRAYREMOVE|ARRAYSORT|ARRAYCOPY|CUPCHECK|SAVEDATA|LOADDATA|DELDATA|CHKDATA|SAVENOS|SAVEGLOBAL|LOADGLOBAL|OUTPUTLOG|SAVECHARA|LOADCHARA|CHKCHARADATA|FIND_CHARADATA|GETTIME|GETMILLISECOND|GETSECOND|FORCEWAIT|INPUT|TINPUT|TINPUTS|TWAIT|ONEINPUT|TONEINPUT|TONEINPUTS|WAITANYKEY|BREAK|CONTINUE|RANDOMIZE|DUMPRAND|INITRAND|BEGIN|CALLTRAIN|DOTRAIN|RETURN|RETURNF|DEBUGCLEAR|ASSERT|TOOLTIP_SETCOLOR|TOOLTIP_SETDELAY|HTML_PRINT|HTML_TAGSPLIT|CLEARTEXTBOX|STOPCALLTRAIN|TIMES|BAR|BARL|SAVEGAME|LOADGAME|WAIT|RESTART|QUIT|GETTIMES|RAND|CBRT|LOG|LOG10|EXPONENT|SUMARRAY|MATCH|MAXARRAY|MINARRAY|SUMCARRAY|CMATCH|MAXCARRAY|MINCARRAY|GROUPMATCH|NOSAMES|ALLSAMES|MESSKIP|CONVERT|COLOR_FROMNAME|COLOR_FROMRGB|INRANGEARRAY|INRANGECARRAY|GETLINESTR|PRINTCLENGTH|STRFORM|GETCONFIG|GETCONFIGS|HTML_POPPRINTINGSTR|HTML_GETPRINTEDSTR|HTML_ESCAPE|HTML_TOPLAINTEXT|TOOLTIP_SETDURATION|AWAIT|STRJOIN|GETKEY|GETKEYTRIGGERED|MOUSEX|MOUSEY|ISACTIVE|SAVETEXT|LOADTEXT|SPRITECREATED|SPRITEWIDTH|SPRITEHEIGHT|SPRITEPOSX|SPRITEPOSY|SPRITESETPOS|SPRITEMOVE|ARRAYMSORT|CLIENTWIDTH|CLIENTHEIGHT|GCREATED|GWIDTH|GHEIGHT|GGETCOLOR|GCREATE|GCREATEFROMFILE|GDISPOSE|GCLEAR|GFILLRECTANGLE|GDRAWSPRITE|GSETCOLOR|GDRAWG|GDRAWGWITHMASK|GSETBRUSH|GSETFONT|GSETPEN|GSAVE|GLOAD|SPRITECREATE|SPRITEANIMECREATE|SPRITEANIMEADDFRAME|SPRITEDISPOSE|SPRITEGETCOLOR|CBGSETG|CBGSETSPRITE|CBGCLEAR|CBGREMOVERANGE|CBGSETBUTTONSPRITE|CBGCLEARBUTTON|CBGSETBMAPG|CBGREMOVEBMAP|INPUTMOUSEKEY|SETANIMETIMER|HTML_STRINGLEN|HTML_SUBSTRING|REGEXPMATCH|ISDEFINED|EXISTVAR|ENUM(FUNC|VAR|MACRO)(BEGINS|ENDS)?WITH|GETVARS?|SETVAR|VARSETEX|ARRAYMSORTEX|QUIT_AND_RESTART|FORCE_QUIT|FORCE_QUIT_AND_RESTART|FORCE_BEGIN|EXISTFUNCTION|ENUMFILES|GDRAWTEXT|GGETFONT|GGETFONTSIZE|GGETFONTSTYLE|GGETTEXTSIZE|GDRAWGWITHROTATE|PLAYSOUND|STOPSOUND|PLAYBGM|STOPBGM|EXISTSOUND|SETSOUNDVOLUME|SETBGMVOLUME|XML_DOCUMENT|XML_RELEASE|XML_EXIST|XML_GET|XML_SET|XML_TOSTR|XML_ADDNODE|XML_REMOVENODE|XML_REPLACE|XML_ADDATTRIBUTE|XML_REMOVEATTRIBUTE|MAP_CREATE|MAP_EXIST|MAP_RELEASE|MAP_GET|MAP_HAS|MAP_SET|MAP_REMOVE|MAP_SIZE|MAP_CLEAR|MAP_GETKEYS|MAP_TOXML|MAP_FROMXML|EXISTFILE|UPDATECHECK|GETMEMORYUSAGE|CLEARMEMORY|PRINTSINGLEFORM(?:K|D)?|PRINTFORM(?:L?C)(?:K|D)?|PRINTFORM(?:K|D)?(?:L|W)?|DATAFORM|PRINTPLAINFORM|DRAWLINEFORM|REUSELASTLINE|STRLENFORMU?|ENCODETOUNI|INPUTS|ONEINPUTS|THROW|DEBUGPRINTFORM|DEBUGPRINTFORML|PUTFORM|RETURNF?|RETURNFORM)\b ?
red=\b(CALLF?|CALLFORMF|CALLEVENT|(TRY)?(CALL|JUMP|GOTO)(FORM)?|)\b
yellow=\b(DAY|MONEY|ITEM|FLAG|TFLAG|UP|PALAMLV|EXPLV|EJAC|DOWN|COUNT|TARGET|ASSI|MASTER|NOITEM|LOSEBASE|SELECTCOM|ASSIPLAY|PREVCOM|TIME|ITEMSALES|PLAYER|NEXTCOM|PBAND|BOUGHT|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|GLOBAL|RANDDATA|SAVESTR|TSTR|STR|GLOBALS|SAVEDATA_TEXT|ISASSI|NO|BASE|MAXBASE|ABL|TALENT|EXP|MARK|PALAM|SOURCE|EX|CFLAG|JUEL|RELATION|EQUIP|TEQUIP|STAIN|GOTJUEL|NOWEX|DOWNBASE|CUP|CDOWN|TCVAR|NAME|CALLNAME|NICKNAME|MASTERNAME|CSTR|CDFLAG|DITEMTYPE|DA|DB|DC|DD|DE|TA|TB|ITEMPRICE|ABLNAME|TALENTNAME|EXPNAME|MARKNAME|PALAMNAME|ITEMNAME|TRAINNAME|BASENAME|SOURCENAME|EXNAME|EQUIPNAME|TEQUIPNAME|FLAGNAME|TFLAGNAME|CFLAGNAME|TCVARNAME|CSTRNAME|STAINNAME|CDFLAGNAME1|CDFLAGNAME2|STRNAME|TSTRNAME|SAVESTRNAME|GLOBALNAME|GLOBALSNAME|GAMEBASE_AUTHER|GAMEBASE_AUTHOR|GAMEBASE_INFO|GAMEBASE_YEAR|GAMEBASE_TITLE|GAMEBASE_GAMECODE|GAMEBASE_VERSION|GAMEBASE_ALLOWVERSION|GAMEBASE_DEFAULTCHARA|GAMEBASE_NOITEM|RAND|CHARANUM|LASTLOAD_TEXT|LASTLOAD_VERSION|LASTLOAD_NO|LINECOUNT|ISTIMEOUT|__INT_MAX__|__INT_MIN__|EMUERA_VERSION|WINDOW_TITLE|MONEYLABEL|DRAWLINESTR|__FILE__|__FUNCTION__|__LINE__|RESULTS?|ARGS?|LOCALS?)\b
magenta=\s*#(DEFINE|DIMS?|FUNCTIONS?|LOCALS?SIZE|SINGLE|PRI|LATER|ONLY)\b

或者 直接下载 配置文件后放到对应位置。

测试#

ERB 测试用例 test_erb_highlight.erb

@SYSTEM_TITLE
    ; 单行注释
    LOCAL = 777
    LOCALS = 草草草
    ;#; PRINTL 已开启调试模式
    PRINTFORML LOCAL={LOCAL} LOCALS=%LOCALS%
    [SKIPSTART]
        多行注释
        第二行注释
    [SKIPEND]
    CALL 一般函数, 111, 222
    REPEAT 3
        PRINTVL 行内函数(RESULT, "测试时间 " + GETTIMES())
    REND
    QUIT


@一般函数, 参数A, 参数B
    #LOCALSIZE 3
    #DIM 参数A
    #DIM REF 参数B
    [IF_DEBUG]
        LOCAL += 100 * 20 / 2 % 2000 + 1 - 1
    [ENDIF]
    LOCAL:1 = 参数A
    LOCAL:2 = 参数B
    RETURN LOCAL:0 + LOCAL:1 + LOCAL:2


@行内函数(arg1, arg2)
#FUNCTIONS
    #LOCALSSIZE 1
    #DIM arg1
    #DIMS arg2
    LOCALS '= @"arg1={arg1} arg2=%arg2%"
    RETURNF LOCALS

ERH 测试用例 test_erh_highlight.erh

#DEFINE FIVE 5
#DIM CONST BIT = 1p0, 1p1, 1p2, 1p3, 1p4, 1p5, 1p6, 1p7

CSV 测试用例 test_csv_highlight.csv

; 假装这里是 Base.csv

1,体力
2,精力  ; 你懂的

如果代码高亮有渲染错误 bug(我相信一定有)欢迎反馈,在 Discord 直接回报就行。

其实有相当一部分是囿于 Jota+ 自身的渲染引擎功能有限,理论上根本无法实现的。
但欢迎积极反馈任何问题,万一可以解决呢。

lackbfun © 2021 - 2024