小游戏开发规范
创建一个小游戏只需要一个 plugin.php 文件,放在 app/plugins/game_center_xxx/ 目录下,注册 game_center.register Hook 即可。
目录结构
app/plugins/game_center_dice/ # 插件目录 = 插件 ID
└── plugin.php # 所有代码都在此文件命名规范
所有游戏中心子插件必须以 game_center_ 为统一前缀:
| 项目 | 规则 | 示例 |
| 目录名 / manifest id | game_center_ + 小写字母 | game_center_dice |
| 游戏注册 ID | 与插件 ID 一致 | $games['game_center_dice'] |
| PHP 函数前缀 | game_center_xxx_ | game_center_dice_register() |
| CSS 类/ID 前缀 | game-center-xxx-* | .game-center-dice-board |
注册合约
在 manifest 中声明 Hook,注册函数接收当前游戏列表并追加自己的游戏:
'hooks' => [
'game_center.register' => 'game_center_dice_register',
],
function game_center_dice_register(array $games, array $ctx): array
{
$games = is_array($games) ? $games : [];
$games['game_center_dice'] = [
'id' => 'game_center_dice', // 唯一 ID,与插件 ID 一致
'name' => '掷骰子', // 显示名称
'desc' => '三颗骰子猜大小', // 简短描述
'cost' => 10, // 每次消耗积分
'max_win' => 2000, // 最高赢取积分(展示用)
'svg_icon' => 'game_center_dice_svg_icon', // 返回 SVG 图标的函数名
'render' => 'game_center_dice_render', // 返回游戏界面 HTML
'play' => 'game_center_dice_play', // 处理游戏操作
];
return $games;
}注册字段说明
| 字段 | 类型 | 必填 | 说明 |
id | string | ✅ | 全局唯一,与插件 ID 一致 |
name | string | ✅ | 游戏名称,显示在游戏大厅 |
desc | string | ✅ | 简短描述,显示在游戏卡上 |
cost | int | ✅ | 每次消耗积分,必须 ≥ 1 |
max_win | int | 最高可赢积分,展示用 | |
svg_icon | string | ✅ | 返回 SVG HTML 的函数名 |
render | string | ✅ | 返回游戏界面 HTML 的函数名 |
play | string | ✅ | 处理游戏操作的函数名 |
render 回调
function game_center_dice_render(array $ctx): string传入上下文 $ctx:
| 字段 | 说明 |
game | 该游戏的注册数据 |
balance | 当前用户积分 |
message | 上一次游戏的结果消息 |
返回游戏界面 HTML。游戏中心会将其包裹在统一容器中,不需要包含标题、返回按钮或积分余额。
必须包含:带 data-replace-target=".game-center-play" 的表单,用于 AJAX 提交替换。
play 回调
function game_center_dice_play(array $ctx): array传入上下文 $ctx:
| 字段 | 说明 |
user_id | 当前用户 ID |
cost | 本次消耗的积分 |
bet | 用户提交的押注数据 |
game | 该游戏的注册数据 |
返回值:
return [
'payout' => 0, // 总派彩积分(0=没赢)
'result' => [...], // 游戏结果数据(JSON,存入记录表)
'html' => '...', // 更新后的游戏界面 HTML
'message' => '...', // 结果消息(toast 提示)
];积分说明
游戏中心在调用 play() 之前已扣除 cost 积分:
payout = 0:玩家净损失cost积分payout = cost × 2:玩家净赚cost积分(翻倍)payout = cost × 200:玩家净赚cost × 199积分(大奖)
押注无效时用 err() 终止,游戏中心会回滚积分扣减。
表单与 AJAX
- 表单
method="post",不设置data-no-ajax - 设置
data-replace-target=".game-center-play" - 包含
form_token()和name="game_id"隐藏字段 play()返回的html替换到.game-center-play容器message以 toast 提示显示
CSS 规范
- 所有选择器以
game-center-xxx-开头 - 颜色使用系统变量(
--brand、--bg等),禁止写死颜色值 - 字号使用
--font-size-*变量 - 禁止使用
!important - 处理窄屏适配(
@media(max-width:720px))
完整示例
参考 app/plugins/game_center_dice/plugin.php,或者老虎机、猜数字、幸运转盘、石头剪刀布的源码。
交付检查清单
- ✅ 目录名和 manifest id 一致,以
game_center_开头 - ✅
plugin.php以if (!defined('APP_ROOT')) exit;开头 - ✅ 所有 PHP 函数以
game_center_xxx_前缀 - ✅ 所有 CSS 选择器以
game-center-xxx-前缀 - ✅ manifest 声明了
game_center.registerHook - ✅ 注册函数返回包含
id、name、desc、cost、svg_icon、render、play的完整数组 - ✅
render()返回的表单含data-replace-target=".game-center-play" - ✅ 表单包含
form_token()和name="game_id" - ✅
play()返回含payout、result、html、message - ✅ 所有用户输入输出使用
h()转义 - ✅ 颜色使用系统 CSS 变量,无写死颜色,无
!important