《era 麻雀》开发日志

era 麻雀v0.3.0-alpha.1d-221106 lackbfun

三缺一怎么说,三缺一
era麻雀.zip(7 MB) 最后更新于 2022-11-07 16:43:26
最新改动 feat: 完成向听数计算

路线图 Roadmap#

Alpha Version#

完成一个麻将游戏最基础的功能:摸切,鸣牌(吃 / 碰 / 杠),和牌。

Beta Version#

完成日麻规则:立直、振听、宝牌、役种、根据符数 / 翻数计算点数。

任务清单 Todo#

Alpha Version#

  • 洗牌
  • 摸起始手牌
  • 每巡摸牌
  • 摸牌后切牌
  • 别家切牌后鸣牌
  • 和牌
    • 自摸:自家摸牌后和牌
    • 荣和:别家切牌后和牌

Beta Version#

  • 立直
    • 立直(听牌)判定
    • 立直操作(切牌)
    • 立直宣言(特殊渲染牌河 / 自家立直棒标记 / 立直数 +1)
  • 振听(听牌判定)
    • 舍张振听(换听才能解除,否则只能自摸)
    • 同巡振听(临时)
    • 立直振听(触发方式类似同巡振听,持续时间类似舍张振听)
  • 宝牌
    • 表宝牌:宝牌 + 杠宝牌
    • 里宝牌:里宝牌 + 杠里宝牌(立直限定)
    • 赤宝牌:赤五万 / 赤五饼 / 赤五索
  • 役种
    • 门清限定
    • 高位替换 or 复合
  • 数值计算
    • 符数(来自手牌牌型)
    • 翻数(来自役种 / 宝牌)
    • 最终点数(来自符数、翻数、庄家 / 闲家亲家 / 子家、自摸 / 荣和、本场数 / 立直数)

开发思路讲解 Walkthrough#

参考雀魂进行牌谱设计#

下载雀魂牌谱油猴脚本
雀魂牌谱转天凤格式

 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
<mahjong ver="版本号" ref="uuid" title="铜之间四人东" time="对局时间">
  <log kyoku="第几局" round="本场数" riichi="立直数">
    <score e="东家点数" s="东家点数" w="东家点数" n="东家点数" />
    <dora>宝牌</dora>
    <uradora>里宝牌</uradora>
    <hand>四家起始手牌</hand>
    <input>四家进张</input>
    <output>四家舍张</output>
    <result type="和了/流局">
      <score>四家分数变化</score>
      <todo>三个不知道什么意义的数字</todo>
      <yaku>役种</yaku>
    </result>
    <ratingc>PF4</ratingc>
    <rule>
      <disp>铜之间四人东</disp>
      <aka53>启用赤五索</aka53>
      <aka52>启用赤五饼</aka52>
      <aka51>启用赤五万</aka51>
    </rule>
    <lobby>0</lobby>
    <dan>四家段位</dan>
    <rate>四家积分</rate>
    <sx>"F", "F", "F", "F"</sx>
    <name>四家名字</name>
    <sc>四家结算点数/马点</sc>
  </log>
</mahjong>

数字:

  • 11 ~ 47 代表 一万红中
  • 51 / 52 / 53 代表赤宝牌
  • 60 代表「摸切(摸到的牌当场切掉)」

字母:

  • 立直标记:r立直宣言牌(作为舍张)
  • 吃标记:c吃的牌(作为进张)
  • 碰标记:p位置(作为进张)
  • 杠标记:k位置(作为舍张,结合前面是否存在 p 可以判断暗杠/加杠)

其他碎碎念 Gossip#

这个项目其实是一个大型 era 开发示例工程,从一开始的初衷就是。
我只是想要亲手演示:
开发 era 游戏真的很简单,而且你可以做到很多你本来以为 era 不可能做到的事。

但自从 2022 年 5 月份立项以来,每每在难以入眠的深夜都会追悔莫及。
我他妈为什么要挖这么大一个坑?
复刻日麻需要的「设计量」实在是太多了,多到我很多次只要一想起就气馁。

但自己开的坑,哭着也要填完。
我就是这么一个人,我做事无所谓有没有人认可,我做东西是做给自己的。
我想做,就会去做。

我也会软弱,也无数次产生过弃坑的念头。
但都是一时的畏难情绪,追根究底,我内心深处想不想做完?想。
那没什么好说的,随便哭,哭完继续干活呗。

(已废弃)需求设计 & 任务清单#

fix#

  • 设置界面等地方没有做容错处理,防止用户强行手动输入「显示为 disable」的按钮

feature#

  • 标题界面的 LOGO:用 SPRITE 绘制,自适应窗口大小
    • 研究 G 系列命令的 mask 功能,能否做到简单的 shader?
  • 研究 HTML_PRINT<img /> 标签的 srcb 属性,感觉可以做文章
  • 研究能不能实现真正的动图(而不是画一张擦一张实现伪动画)
    • 按照官方函数的 API 来说是可以实现的
    • SPRITEANIMECREATE / SPRITEANIMEADDFRAME / SETANIMETIMER
    • 复刻 EE demo 里的头像旋转 / 抖动功能(第一次看到给我逗乐了)
  • 参考《era 俄罗斯方块》的即时刷新画面/判断输入实现
    • 无限轮询 ONEINPUT(不需要回车)输入
    • 研究它是如何判断游戏进程里经过的时间的(难道是固定帧率做的?)
    • 人机 AI 仿真思考延迟
    • 房间设置可自定义等待时间
    • 类似雀魂的限时设计:长考 20 + 4,两个计时器
      前者不可恢复,后者自动重置,优先消耗后者
  • _fixed.config 强制规定:字高(关系到图片大小)、行高(关系到图片显示出来具体占几行)、禁止调整窗口尺寸(宽度/高度)、禁止最大化窗口
  • 整理摸切的全部流程,优化业务逻辑
  • 完善鸣牌操作:
    • 自家摸牌之后(立直/暗杠/加杠/自摸)
    • 别家切牌之后(吃/碰/杠/荣和)
  • 梳理整个游戏主流程:发牌,开始循环:
    1. 手牌满时判定是否和牌,询问自家操作(立直,和牌,暗杠/加杠,不能跳过)
    2. 切牌
    3. 询问别家操作(下家吃,别家碰/大明杠/和牌,跳过)
    4. 牌权切换到下家。DRAW SELF_ACTION OTHERS_ACTION 判断是否是玩家
  • 考虑用单独的 XML 文件来存麻将游戏用到的全局变量
    • data/mahjong_config.xml MAHJONG_CONFIG
  • 考虑是否要手写 MD5 来做牌山验证
  • 设计牌谱的数据结构:
    • 四家
      • 点数
      • 起始手牌
      • 进张记录
      • 舍张记录(牌河和舍张都可以从这里判断)被鸣的牌,雀魂是直接删掉,这里为了可读性考虑将其变为负数
  • 设计副露字符串格式(鸣牌座位 (call_seat + 4 - self_seat) %4)遍历所有可能性:
    • 吃 1 / 吃 2 / 吃 3
    • 碰下家 / 碰对家 / 碰上家
    • 大明杠下家 / 大明杠对家 / 大明杠上家
    • 碰下家加杠 / 碰对家加杠 / 碰上家加杠
    • 数字牌暗杠 / 字牌暗杠
  • 设计和牌分析数据结构,当然还是 XML
    • hand_tiles
    • win_tile
    • fu
    • yaku
    • han
    • 对局信息:立直数 本场数 庄家闲家
  • 对局结束自动保存牌谱文件,然后释放「各家手牌 MAP」和「当前牌谱 XML」
    • 格式 log/mahjong/mahjong_log_20220616_154759.xml(对局开始的时间)
    • 维护一个牌谱记录表:只保留最近 100 场牌谱,防止数据无限膨胀(其实也无所谓啦,但这是一个工程规范问题)
  • 特殊能力作弊功能
    • 预言(透视)下一张牌,可以加入预言成功率设定,或者只能预言部分信息(万饼索字)
    • 透视别家手牌
    • 神态系统:别家会透露神态,可以观察微表情来判断对方准备打什么牌
      说起来有点玄学,其实主要还是我想加入「明明很 xx 但正在打牌不得不忍住」的设定
    • 超算能力:自动计算向听,何切,安牌,危险牌,最可能的役种,听牌改良(剩余和牌张数)
      这个很简单,就是直接把人机 AI 的算法搬过来
      个屁啦,说得你好像已经写完人机 AI 了一样
  • 允许把牌谱转换为 天凤 / 雀魂 的牌谱格式(然后就能拿去给各种牌谱分析器读了)
  • 处理字符串形式的数组 1,2,3,4utils/common.erb @sarray_has
  • 字符串解析功能兼容缩写:1s2s3s4s5s6s123456s
  • 手牌拆分:单张 顺子 明刻 暗刻 明杠 暗杠
  • 游乐场功能
    • 根据 符数/翻数/庄闲/是否自摸 计算打点 已完成
    • 和牌分析(是否和牌/符数/役种/翻数/最后打点):可以手动输入字符串(123m444p),也可以点击图片
    • 何切题
  • 日麻教程:抄雀魂的教学
    • 新手入门
    • 首次打开生成 sprite:tutorial_page_1
    • 役种一览
    • 首次打开生成 sprite:yaku_sample_page_1
  • 数据统计:
    • GDRAWRAW 不存在 SPRITE 就绘制
    • 具体数据保存在特制的存档(我对 Emuera 原版乱七八糟的实现的信任度为 0)
    • 有没有必要加密?感觉没必要,一个小破单机而已,他都这样了,你就让他改吧

todo#

  • 业务逻辑
    • 版本更新检测 22.6.10 done
    • 标题界面 22.6.12 done
    • 麻将游戏
      • 公平洗牌 22.5.29 done
      • 各家(仿真)摸起始手牌 22.5.30 done
      • 主游戏流程:回合结束自动轮换到下家,循环到有人和牌或流局
      • 鸣牌判定 22.6.14 done
      • 和牌判定 22.6.14 done
      • 振听判定
      • 听牌判定(立直判定)
      • 役种判定
      • 符数计算
      • 翻数计算 22.6.13 done
      • 打点计算 22.6.13 done
    • 牌谱回放
    • 基础教程
    • 统计数据
    • 游戏设置 22.6.12 done
    • 退出游戏 22.6.12 done
  • 操作
    • 输入容错:统一处理(理论上)玩家无法进行的操作 22.6.1 done
    • 便捷功能开关(自动和牌 / 自动摸切 / 不吃碰杠 / 自动理牌) 22.5.31 done
    • 自动和牌
    • 自动摸切
    • 不吃碰杠
    • 自动理牌:兼容庄家起手的手牌排序 22.5.31 done
    • 作弊功能:透视别家手牌 22.5.31 done
    • 作弊功能:预测下一张牌 22.5.31 done
    • 玩家手动进行摸切操作 22.5.31 done
    • 玩家手动进行鸣牌操作
  • 人机
    • 简单人机 AI:人机进行摸切操作
    • 简单人机 AI:人机进行鸣牌操作
    • 完整人机 AI(进张数、向听数、向听前进后的进张数、改良进张、役种预测、速度、打点、和率、危险度安牌预测
    • 多难度人机 AI
      • 简单难度:遵循最基本的几条原则
      • 普通难度:分析局势后根据权重判断何切
  • 显示
    • 渲染可交互的玩家手牌 22.5.29 done
    • 渲染副露
    • 渲染别家手牌 22.6.1 done
    • 渲染各家牌河(舍张历史 / 现物记录)
    • 渲染对局信息(各家点数 / 东四局ALL LAST / 立直棒 × n / 本场数 × m
    • 渲染牌桌(把以上图像叠成一整张图)
    • i18n(内置多语言支持) 22.6.10 done
    • 使用开源的等宽字体 22.6.11 done 最后选定更纱黑体
  • 声音
    • 操作音效(打牌 / 吃 / 碰 / 杠 / 立直 / 荣和 / 自摸) 22.5.29 done
    • 自动轮换的 BGM

lackbfun © 2021 - 2024