更新记录

1.0.0(2026-06-24) 下载此版本

作为 1.0.0 起始版本,初始化 jz-gameManager 通用游戏管理器插件,面向 uni-app 场景,采用 分层架构 + Facade 模式 + 事件驱动 设计,提供统一入口 GameManager 单例。

核心层(core)

  • GameManager:单例门面,统一管理子模块与生命周期,提供 createGameManager() / getGameManager() / destroyGameManager() / configure() / dispose() 等入口方法,并聚合状态、模式、数据、计时器、音效、音乐、朗读、随机数、分数、多人联机的便捷 API。
  • GameStateMachine:游戏状态机,内置 11 种通用状态(idle / ready / loading / playing / paused / round-start / round-end / intermission / waiting / game-over / error)与默认跳转规则,支持自定义状态、跳转规则、快照导出 / 恢复。
  • GameModeManager:游戏模式管理,支持单机 / 多人联机 / 对战 / 合作四种模式以及 realtimeSync / roomManagement / playerDataSync / voiceChat / hostAuthoritative 等特性查询。
  • GameTimerManager:计时器管理,支持倒计时、正计时、回合计时、间隔触发器,统一暂停 / 继续 / 停止,多计时器并行。
  • GameDataManager:数据管理,提供运行时内存、本地持久化、房间数据同步、玩家数据同步、多槽位进度存档、自动保存、数据导入 / 导出能力。
  • MultiplayerManager:多人联机管理,房间创建 / 加入 / 离开、玩家管理、消息收发、状态同步、自定义消息处理器、请求-响应通讯、踢人等能力。

适配层(adapters)

  • ConnectProvider:多人联机抽象接口,定义 init / send / broadcast / request / kick / getPeerId / getPeers / on / off / dispose 契约。业务侧通过实现该接口可对接任意 WebRTC 方案(推荐基于 jz-webrtc-connect 包装),实现核心逻辑与具体通讯实现的解耦。

数据层(data)

  • GameStoreBase:数据存储基类,提供版本号、变更通知、patch / snapshot / restore 协议。
  • PlayerStore / RoomStore / ProgressStore:玩家数据、房间数据、进度存档专用 Store。
  • StorageDriver:内置 MemoryDriver(运行时内存)与 UniStorageDriver(基于 uni.setStorage 持久化)两种驱动。

工具层(utils)

  • SoundPlayer:音效播放器,支持多实例并发、音量控制、循环播放。
  • MusicPlayer:背景音乐播放器,支持渐入渐出、暂停 / 继续 / 切换、队列管理。
  • TextReader:文字朗读器,基于 Web Speech API,可设置语速、音调、音量、语言。
  • RandomGenerator:随机数生成器,支持种子随机(可复现的 LCG 算法)、范围整数 / 浮点、概率随机、权重抽取、洗牌、随机选择。
  • GameScoreManager:分数管理器,支持多玩家分数管理、排行榜、历史最高分、分数变更事件、自定义排序规则。
  • FrameAnimationPlayer:帧动画播放器,提供 fromFramesByDir / fromSpriteSheet / fromAnimations 三种创建方式,支持 ONCE / LOOP / PINGPONG 三种循环模式,提供位置、缩放、旋转、锚点、透明度等节点属性,可在 requestAnimationFrame 循环中以 update(deltaMs) 推进。

通用层(common)

  • EventBus:轻量事件总线,不依赖 Vue / Node,提供 on / off / once / emit / clear
  • GameError:统一错误对象,附带 ERROR_CODES 错误码枚举。
  • constants:状态、模式、消息类型、计时器类型、帧动画循环模式、版本号等枚举常量。
  • utils:UUID 生成、深度合并、防抖、节流、时间戳等通用工具函数。

入口

  • index.js:统一导出全部公开 API、类、枚举常量,便于业务侧按需引入。
  • 提供顶层便捷函数:createGameManager / getGameManager / destroyGameManager / configure / getConfig

平台与依赖

  • 单机功能(状态机、计时器、数据、音效、随机数、分数、帧动画):无第三方依赖,全平台支持(H5 / App / 小程序)。
  • 多人联机功能:依赖业务侧实现 ConnectProvider,受 WebRTC 限制仅 H5 环境可用;推荐配合 jz-webrtc-connect 插件使用。

配套示例

  • 工程同步提供 7 个 Demo 页面(基础功能、分数管理、随机数、计时器、数据存储、帧动画、剪刀石头布多人对战),覆盖全部核心能力,可直接运行查看效果。

平台兼容性

uni-app(4.74)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
-
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
- - - - - - - - - × ×

jz-gameManager

jz-gameManager 是一个面向 uni-app 的通用游戏管理器插件,提供开箱即用的游戏开发基础能力,让业务代码聚焦于「玩法」本身。

  • 版本1.0.0
  • 入口@/uni_modules/jz-gameManager
  • 平台:单机能力全平台支持;多人联机能力依赖 WebRTC,仅 H5 可用

目录


核心能力

  • 游戏状态机:内置通用状态与跳转规则,支持自定义状态与跳转路径
  • 游戏模式管理:单机 / 多人联机 / 对战 / 合作四种模式,按模式查询特性
  • 计时器管理:倒计时、正计时、回合计时、间隔触发,统一暂停/继续/停止
  • 数据管理:本地持久化(uni Storage)、运行时内存、房间数据同步、玩家数据同步、多槽位进度存档
  • 多人联机:基于自定义 ConnectProvider 适配层,可对接任意 WebRTC 方案
  • 音效 / 音乐 / 朗读:统一封装的 SoundPlayer / MusicPlayer / TextReader
  • 随机数生成:支持种子随机(可复现)与普通随机
  • 分数管理:玩家分数、排行榜、历史最高分
  • 帧动画:基于 requestAnimationFrame 的帧动画播放器,支持循环 / 乒乓 / 单次

架构

采用 分层架构 + Facade 模式 + 事件驱动 设计:

入口层 index.js
  └─ 核心层 core/        GameManager / GameStateMachine / GameModeManager
                          GameDataManager / MultiplayerManager / GameTimerManager
  ├─ 工具层 utils/       SoundPlayer / MusicPlayer / TextReader
                          RandomGenerator / GameScoreManager / FrameAnimationPlayer
  ├─ 数据层 data/        GameStoreBase / PlayerStore / RoomStore / ProgressStore / StorageDriver
  ├─ 适配层 adapters/    ConnectProvider(多人联机抽象接口)
  └─ 通用层 common/      EventBus / GameError / constants / utils

GameManager 作为单例门面,统一管理所有子模块并通过 EventBus 分发事件。

安装与依赖

将插件复制到工程的 uni_modules 目录即可:

src/uni_modules/jz-gameManager/
  • 单机能力(状态机、计时器、数据、音效、随机数、分数、帧动画):无第三方依赖,全平台可用
  • 多人联机能力:需要业务侧自行实现 ConnectProvider,并注入到 GameManager
    • 推荐基于 jz-webrtc-connect 封装(已在示例 src/pages/game/rps 中实现)
    • 仅 H5(Chrome / Safari)环境可用

快速开始

单机模式

import { createGameManager, GAME_STATE, GAME_MODE } from '@/uni_modules/jz-gameManager'

const game = await createGameManager({
  gameId: 'my-game',
  mode: GAME_MODE.SINGLE,
  initialState: GAME_STATE.IDLE,
  sounds: { click: '/static/sounds/click.mp3' },
  music: { bgm: '/static/music/bgm.mp3' }
})

// 监听状态变更
game.on('state-change', e => console.log(e.prev, '->', e.next))

// 切换状态(跳转受状态机规则约束)
game.setState(GAME_STATE.READY)
game.setState(GAME_STATE.PLAYING)

// 播放音效 / 音乐
game.playSound('click')
game.playBGM('bgm')

// 倒计时
game.startCountdown({
  duration: 60,
  onTick: remaining => console.log('剩余', remaining),
  onEnd: () => console.log('时间到')
})

// 本地数据持久化
game.setLocalData('score', 100)
game.getLocalData('score')  // 100

// 页面销毁时
await game.dispose()

多人联机模式

import { createGameManager, GAME_MODE, ConnectProvider } from '@/uni_modules/jz-gameManager'

// 1. 自行实现 ConnectProvider(示例见 src/pages/game/rps/composables/RpsConnectAdapter.js)
class MyAdapter extends ConnectProvider { /* ... */ }
const adapter = new MyAdapter(coreInstance)

// 2. 注入到 GameManager
const game = await createGameManager({
  gameId: 'my-game',
  mode: GAME_MODE.MULTIPLAYER,
  adapter
})

// 3. 房主创建房间
const { roomId } = await game.createRoom({
  playerInfo: { name: '玩家1', avatar: '' },
  roomConfig: { maxRounds: 5 }
})

// 4. 成员加入房间
await game.joinRoom({
  roomId: 'room-xxx',
  playerInfo: { name: '玩家2' }
})

// 5. 监听玩家加入 / 离开
game.on('peer-join', e => console.log('玩家加入', e.peerId))
game.on('peer-leave', e => console.log('玩家离开', e.peerId))

// 6. 广播消息(仅房主)
await game.getMultiplayerManager().broadcast('custom-event', { foo: 'bar' })

// 7. 销毁
await game.dispose()

使用指南

1. 状态机

内置通用状态:idle / ready / loading / playing / paused / round-start / round-end / intermission / waiting / game-over / error

import { GAME_STATE } from '@/uni_modules/jz-gameManager'

// 监听
game.on('state-change', ({ prev, next, ts }) => {
  console.log(`${prev} -> ${next} @ ${ts}`)
})

// 跳转
game.setState(GAME_STATE.PLAYING)

// 查询
game.getState()                              // 当前状态
game.getPreviousState()                      // 上一个状态
game.canTransitionTo(GAME_STATE.GAME_OVER)   // 是否可跳转

自定义状态与跳转规则

const game = await createGameManager({
  gameId: 'rpg',
  initialState: 'menu',
  stateTransitions: {
    menu:    ['battle', 'shop'],
    battle:  ['menu', 'game-over'],
    shop:    ['menu'],
    'game-over': ['menu']
  }
})

2. 模式管理

import { GAME_MODE } from '@/uni_modules/jz-gameManager'

game.setMode(GAME_MODE.VERSUS)
game.getMode()                        // 当前模式
game.getModeManager().supports('realtimeSync')  // 模式特性查询

支持的模式:SINGLE / MULTIPLAYER / VERSUS / COOPERATIVE,每种模式预置 realtimeSync / roomManagement / playerDataSync / voiceChat / hostAuthoritative 等能力开关。

3. 计时器

// 倒计时
const id = game.startCountdown({
  duration: 30,         // 秒
  tickInterval: 1,      // 触发频率
  onTick: (remaining, elapsed) => {},
  onEnd: () => {}
})

// 正计时
game.startCountup({
  maxDuration: 300,
  onTick: elapsed => {}
})

// 回合计时
game.startRoundTimer({
  rounds: 5,
  roundDuration: 60,
  onRoundStart: round => {},
  onRoundEnd: round => {},
  onAllRoundsEnd: () => {}
})

// 间隔触发
game.startInterval({
  interval: 2,
  onTick: count => {}
})

// 控制
game.stopTimer(id)
game.pauseAllTimers()
game.resumeAllTimers()
game.stopAllTimers()

4. 数据管理

维度 方法 说明
运行时(内存) setData / getData / removeData / clearData 速度最快,重启丢失
本地持久化 setLocalData / getLocalData 落地到 uni.setStorage
多槽位存档 getDataManager().saveProgress(progress) / loadProgress(slotId) 适合关卡进度
房间数据 getDataManager().setRoomData / getRoomData 房主写入并广播给成员
玩家数据 getDataManager().setPlayerData(peerId, key, value) 各成员独立数据
game.setLocalData('coin', 1000)
game.setData('runtime.combo', 3)
game.on('data-change', e => console.log(e.scope, e.key, e.value))

// 自动保存
game.getDataManager().startAutoSave(5000)  // 5s 持久化一次

// 导入 / 导出
const snapshot = game.getDataManager().exportData()
game.getDataManager().importData(snapshot)

5. 音效 / 音乐 / 朗读

// 在 createGameManager() 时预注册资源别名
sounds: { click: '/static/click.mp3', win: '/static/win.mp3' },
music:  { bgm: '/static/bgm.mp3' }

// 音效
const playId = game.playSound('click', { volume: 0.8, loop: false })
game.stopSound(playId)
game.stopAllSounds()

// 背景音乐(自动渐入 / 切换)
game.playBGM('bgm', { fadeIn: 800, loop: true })
game.pauseBGM()
game.resumeBGM()
game.switchBGM('/static/boss.mp3', { fadeOut: 500, fadeIn: 500 })
game.stopBGM()

// 文字朗读(Web Speech API)
game.speakText('恭喜你获胜', { rate: 1, pitch: 1, lang: 'zh-CN' })
game.stopAllSpeaking()

6. 随机数生成

const rng = game.getRandomGenerator()

rng.setSeed(20260624)              // 设定种子
rng.randomWithSeed()               // 可复现序列
rng.randint(1, 100)                // [1, 100]
rng.randfloat(0, 1)                // [0, 1)
rng.choice(['rock', 'paper', 'scissors'])
rng.shuffle([1, 2, 3, 4, 5])       // 洗牌
rng.byProbability(0.3)             // 30% 命中
rng.byWeight([['SSR', 1], ['SR', 9], ['R', 90]])  // 权重抽取

7. 分数管理

const score = game.getScoreManager()

score.registerPlayer('p1', { name: '玩家1' })
score.registerPlayer('p2', { name: '玩家2' })

score.addScore(10, 'p1')
score.addScore(-5, 'p2')
score.setScore('p1', 100)
score.getScore('p1')

const top = score.getLeaderboard()       // 排行榜
const high = score.getHighScore()        // 历史最高

8. 帧动画

import { FrameAnimationPlayer, FRAME_LOOP_MODE } from '@/uni_modules/jz-gameManager'

// 1) 按目录加载序列帧
const node = FrameAnimationPlayer.fromFramesByDir({
  dir: '/static/anim/run',
  count: 8,
  ext: 'png',
  fps: 12,
  loop: FRAME_LOOP_MODE.LOOP
})

// 2) 雪碧图
const node2 = FrameAnimationPlayer.fromSpriteSheet({
  src: '/static/sheet.png',
  frameWidth: 64,
  frameHeight: 64,
  count: 10,
  fps: 24,
  loop: FRAME_LOOP_MODE.PINGPONG
})

// 3) 多动画集合
const hero = FrameAnimationPlayer.fromAnimations({
  defaultAnimation: 'idle',
  animations: {
    idle: { frames: [/* ... */], fps: 8 },
    run:  { frames: [/* ... */], fps: 12 },
    attack: { frames: [/* ... */], fps: 16, loop: false }
  }
})
hero.play()
hero.switchAnimation('run')
hero.update(deltaMs)                 // 在 requestAnimationFrame 循环中调用
hero.getCurrentSrc()                 // 取当前帧资源

9. 多人联机

多人联机走 依赖注入 模式:你需要自行实现 ConnectProvider 接口,再传给 GameManager

9.1 实现 ConnectProvider

ConnectProvider 定义了一组与传输层无关的契约:

import { ConnectProvider } from '@/uni_modules/jz-gameManager'

class MyAdapter extends ConnectProvider {
  async init(options)                                    // 初始化,返回 peerId
  async send(peerId, channel, data, options)             // 点对点发送
  async broadcast(channel, data, options)                // 广播(host)
  async request(peerId, channel, data, options)          // 请求-响应
  async kick(peerId, reason)                             // 踢人(host)
  getPeerId()
  getPeers()
  on(event, handler)        // ready / peer-join / peer-leave / message / request / error
  off(event, handler)
  async dispose()
}

完整可工作的参考实现:src/pages/game/rps/composables/RpsConnectAdapter.js,基于 jz-webrtc-connect 包装。

9.2 注入到 GameManager

const adapter = new MyAdapter(coreInstance)
const game = await createGameManager({
  gameId: 'rps',
  mode: GAME_MODE.MULTIPLAYER,
  adapter,
  multiplayer: {
    maxPlayers: 2,
    minPlayersToStart: 2,
    syncRoomData: true
  }
})

9.3 房间与消息

// 房主
await game.createRoom({ playerInfo: { name: 'Host' }, roomConfig: { rounds: 3 } })

// 成员
await game.joinRoom({ roomId, playerInfo: { name: 'Guest' } })

// 查询
game.getRoomInfo()
game.getPlayers()

const mp = game.getMultiplayerManager()

// 自定义消息
mp.registerMessageHandler('action', ({ from, payload }) => {})
await mp.broadcast('action', { type: 'jump' })
await mp.sendTo(peerId, 'action', { type: 'attack' })
await mp.sendToHost('action', { type: 'ready' })

// 离开
await game.leaveRoom()

API 总览

入口(顶层导出)

import {
  createGameManager,         // 创建并初始化单例
  getGameManager,            // 获取已创建的单例
  destroyGameManager,        // 销毁单例
  configure,                 // 配置全局默认选项(create 前调用)
  getConfig,
  // 类
  GameManager, GameStateMachine, GameModeManager, GameTimerManager,
  GameDataManager, MultiplayerManager,
  ConnectProvider,
  GameStoreBase, PlayerStore, RoomStore, ProgressStore,
  MemoryDriver, UniStorageDriver,
  SoundPlayer, MusicPlayer, TextReader,
  RandomGenerator, GameScoreManager, FrameAnimationPlayer,
  EventBus, GameError,
  // 常量
  GAME_STATE, DEFAULT_STATE_TRANSITIONS,
  GAME_MODE, MODE_FEATURES,
  MULTIPLAYER_STATE, PLAYER_STATE, PLAYER_ROLE,
  GAME_MESSAGE_TYPE, TIMER_TYPE,
  FRAME_LOOP_MODE,
  ERROR_CODES, VERSION
} from '@/uni_modules/jz-gameManager'

GameManager(门面)

分类 方法
生命周期 createGameManager(options) / getGameManager() / destroyGameManager() / dispose()
状态机 setState(state, options) / getState() / getPreviousState() / canTransitionTo(state) / getStateMachine()
模式 setMode(mode, config) / getMode() / getModeManager()
多人联机 createRoom(opts) / joinRoom(opts) / leaveRoom() / getRoomInfo() / getPlayers() / getMultiplayerManager()
数据 setLocalData(k,v) / getLocalData(k) / setData(k,v) / getData(k) / saveData() / loadData() / hasData(k) / removeData(k) / clearData() / getDataManager()
音效 playSound(name, opts) / stopSound(id) / stopAllSounds() / getSoundPlayer()
音乐 playBGM / stopBGM / pauseBGM / resumeBGM / switchBGM 及别名 playMusic / stopMusic / pauseMusic / resumeMusic / switchMusicgetMusicPlayer()
朗读 speakText(text, opts) / stopSpeaking(id) / stopAllSpeaking() 及别名 speak / stopSpeak / stopAllSpeakgetTextReader()
计时器 startCountdown / startCountup / startRoundTimer / startInterval / stopTimer(id) / stopAllTimers / pauseAllTimers / resumeAllTimers / getTimerManager()
工具 getRandomGenerator() / getScoreManager()
事件 on(event, handler) / off(event, handler) / once(event, handler)

事件

通过 GameManager.on(event, handler) 统一订阅:

事件 触发时机
init 初始化完成
state-change 游戏状态变更
mode-change 游戏模式变更
data-change 任意数据域(local / memory / room / player)发生变更
room-created / room-joined 房间创建 / 加入成功
peer-join / peer-leave 玩家加入 / 离开
message 收到多人消息
sync 状态同步
disconnect / reconnect 网络断开 / 重连
error 发生错误(含 GameError 实例)

枚举常量

  • GAME_STATE:游戏状态
  • DEFAULT_STATE_TRANSITIONS:默认状态跳转规则
  • GAME_MODE / MODE_FEATURES:游戏模式与特性矩阵
  • MULTIPLAYER_STATE:联机状态
  • PLAYER_STATE / PLAYER_ROLE:玩家状态与角色
  • GAME_MESSAGE_TYPE:多人消息类型
  • TIMER_TYPE:计时器类型
  • FRAME_LOOP_MODE:帧动画循环模式(ONCE / LOOP / PINGPONG
  • ERROR_CODES:错误码
  • VERSION:插件版本号(1.0.0

平台支持

平台 单机功能 多人联机
H5 (Chrome / Safari)
App (Vue / nvue) ×
小程序 ×

多人联机依赖 WebRTC,仅 H5 可用;其余能力(状态机、计时器、数据、音效、随机数、分数、帧动画)全平台可用。

演示页面

工程内置 7 个 Demo 页面,覆盖全部核心能力,可直接运行查看效果:

路径 内容
/pages/index/index 插件首页与功能总览
/pages/game/basic/index 基础功能:状态机 + 音效 + 音乐 + 计时器
/pages/game/score/index 分数管理:多玩家分数 + 排行榜
/pages/game/random/index 随机数:种子 / 概率 / 权重 / 洗牌
/pages/game/timer/index 计时器:倒计时 / 正计时 / 回合 / 间隔
/pages/game/data/index 数据存储:本地持久化 + 运行时 + 监听
/pages/game/animation/index 帧动画:序列帧 / 雪碧图 / 多动画 / 乒乓
/pages/game/rps/lobby/index 剪刀石头布:多人联机 + 三局两胜的综合示例

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

暂无用户评论。