要开始做游戏了
每当周围漂亮的小姐姐和别人打游戏“嗨”到飞起而我无法加入其中时,一股挫败感便会直冲我的天灵盖。
为何我打游戏可以菜
到如此抠脚!!!怎么练都上不了分,日复一日,我终于由黄金
成长为了青铜
…
罢了,我还是以"小视频"相伴吧!毕竟只要动动手指就可以了。
不,我要雄起
,不会打游戏,我可以做游戏啊!
于是我加入了公司一夜狼人杀游戏的开发,并成为了苦逼的包工头。
项目还没开始就要结束?
在这个项目之前,公司有多个自主研发的游戏,所以基础建设基本不用从零开始搭了,脚手架一把梭就可以开干…
但万万没想到,正当我想撸起袖子准备搞起的时候,却遇到了一个尴尬而扭捏的问题。
什么问题?
后端丢给我一个长达510多行的信令接口文件,它大概是长这样的。 里面包含了游戏中前后端交互的各个消息定义。
不幸的是,按照现有的游戏架子,需要前端根据信令文件手动编写这样一个JS配置
XDM,你怎么看? 我估计你此时和我一样,心中一万只草泥马在辽阔的大草原奔腾不止。
让你痛苦的地方,往往是可以提升的地方
工作中我们往往会遇到很多低效,易错和痛苦的点。如果你能主动解决这些让你(往往也是让其他人)感到不爽的问题。
相信我,你一定会收获良多,技术上、软实力上、装逼技巧上,都能得到一定的提升。
比如上面这个问题,我们要写一个脚本自动生成符合条件的配置文件
问题分析
我们先来看几组消息定义,看看其内容都有什么规律。
1.消息接口
// -301 通知所有用户游戏配置变更消息
message GameConfigChangeNotify {
int32 actionTime = 1; //角色行动时长,
int32 speakOrderTime = 2;//玩家顺序发言时长
int32 round = 3; // 顺序发言次数
int32 speakFreedomTime = 4;//玩家自由发言时长
bool speakAuth = 5; // 是否允许用户游戏中自主开闭麦 false不允许 true允许
int64 selfSetRoleUid = 6; //可自主选着身份的用户
}
JS配置
{
GameConfigChangeNotify: -301
}
2.消息接口
// 1. 注意后面跟着问号?
// -350 猎人发动技能提醒 ?
message HunterActionNotify{
//战斗ID
int64 battleId = 1;
int32 duration = 2;
}
// 2. 注意后面跟有&和()等特殊符号
// -352 胜负判定&复盘结果(此时游戏结束)
message FinalNotify{
//战斗ID
int64 battleId = 1;
int32 duration = 2;
FinalRes finalRes = 3; // 胜负结果
Review review = 5; // 复盘结果
}
// 3. 注意跟着中文的括号(),并且//后面的数字没有空格,且{前面没有空格
//345 结束发言(自己结束)
message SpeakEndReq{
//战斗ID
int64 battleId = 1;
}
JS配置
{
HunterActionNotify: -350,
FinalNotify: -352,
SpeakEndReq: 345
}
规则总结
你看,规则其实挺简单的,分成以下几条看
//
后面跟着一个或者多个空格,紧接着就是数字(正数或者负数),这个数字就是配置value。- 数字(例如
345
)与message
之间是一段注释,可能由中文或一些特殊字符构成。 message
与下一个{
之间的英文字母就是配置的key。
正则解析脚本
有了上面的解析,就不难写出解析转换配置的脚本了。
const fs = require('fs')
let dayWerwolfFileContent = fs.readFileSync('./.protofile/DayWerwolf.proto', 'utf-8')
let dayWerwolfMap = {}
dayWerwolfFileContent.replace(/\/\/\s*?(-?\d+)[^\w]*?message\s+(\w+)\s*?{/g, ($0, $1, $2) => {
if ($1 && $2) {
dayWerwolfMap[$2] = +`${$1}`
}
})
fs.writeFileSync('.protofile/map.js', `
module.exports = {
DayWerwolf: ${JSON.stringify(dayWerwolfMap, null, 2)}
}
`)
最后只需要执行脚本node parse.js
就完事啦!
module.exports = {
DayWerwolf: {
"GameConfigChangeNotify": -301,
"GameRoleChangeNotify": -302,
"GameAutoNextReq": 303,
"GameStartNotify": -320,
"ShuffleNotify": -321,
"ChooseIdentityNotify": -322,
"ChooseIdentityReq": 322,
"AllIdentityNotify": -323,
"ConfirmIdentityReq": 323,
"DarkNotify": -324,
"ActionNotify": -325,
"GhostActionNotify": -326,
"GhostActionReq": 326,
"GhostCopyResNotify": -327,
"GhostChangeIdentityReq": 327,
"ActionEndNotify": -328,
"WolfActionNotify": -329,
"WolfActionReq": 329,
"WolfActionResNotify": -330,
"LackeyActionNotify": -331,
"LackeyActionReq": 331,
"NightWatcherActionNotify": -332,
"NightWatcherActionReq": 332,
"SeerActionNotify": -333,
"SeerActionReq": 333,
"SeerActionResNotify": -334,
"RobberActionNotify": -335,
"RobberActionReq": 335,
"RobberActionResNotify": -336,
"TroublemakerActionNotify": -337,
"TroublemakerActionReq": 337,
"TroublemakerActionResNotify": -338,
"DrunkardActionNotify": -339,
"DrunkardActionReq": 339,
"DrunkardActionResNotify": -340,
"InsomniacActionNotify": -341,
"InsomniacActionRes": 341,
"PullIdentityReq": 342,
"IdentityNotify": -342,
"DaybreakNotify": -343,
"SpeakRoundsNotify": -344,
"SpeakNotify": -345,
"SpeakEndReq": 345,
"SpeakEndNotify": -346,
"VoteNotify": -347,
"VoteReq": 347,
"VoteResNotify": -348,
"OutNotify": -349,
"HunterActionNotify": -350,
"HunterActionReq": 350,
"OutResNotify": -351,
"FinalNotify": -352,
"MsgNotify": -357,
"UserStatusChangeNotify": -600
}
}
为了让其他项目也可以省掉手动编写配置文件的时间,我赶紧将该脚本内置到了公司的脚手架里。
正文结束
Ctrl + Enter