注释文档完善
This commit is contained in:
parent
68378f2c58
commit
5ca21409cf
26
README.md
26
README.md
|
@ -41,6 +41,32 @@ $ go get -u github.com/kercylan98/minotaur
|
|||
- 更多的 **[示例](./examples)** 参考可在 [examples](./examples) 目录查阅;
|
||||
- 项目文档可访问 **[pkg.go.dev](https://pkg.go.dev/github.com/kercylan98/minotaur)** 进行查阅;
|
||||
|
||||
### 本地文档
|
||||
可使用 `godoc` 搭建本地文档服务器
|
||||
#### 安装 godoc
|
||||
```shell
|
||||
git clone golang.org/x/tools
|
||||
cd tools/cmd
|
||||
go install ...
|
||||
```
|
||||
#### 使用 `godoc` 启动本地文档服务器
|
||||
```shell
|
||||
godoc -http=:9998 -play
|
||||
```
|
||||
#### Windows
|
||||
```shell
|
||||
.\local-doc.bat
|
||||
```
|
||||
|
||||
#### Linux or MacOS
|
||||
```shell
|
||||
chmod 777 ./local-doc.sh
|
||||
./local-doc.sh
|
||||
```
|
||||
|
||||
#### 文档地址
|
||||
**[http://localhost:9998/pkg/github.com/kercylan98/minotaur/](http://localhost:9998/pkg/github.com/kercylan98/minotaur/)**
|
||||
|
||||
### 简单示例
|
||||
创建一个基于Websocket的回响服务器。
|
||||
```go
|
||||
|
|
|
@ -34,6 +34,13 @@ func NewLockstep[ClientID comparable, Command any](options ...LockstepOption[Cli
|
|||
}
|
||||
|
||||
// Lockstep 锁步(帧)同步默认实现
|
||||
// - 支持最大帧上限 WithLockstepFrameLimit
|
||||
// - 自定逻辑帧频率,默认为每秒15帧(帧/66ms) WithLockstepFrameRate
|
||||
// - 自定帧序列化方式 WithLockstepSerialization
|
||||
// - 从特定帧开始追帧
|
||||
// - 兼容各种基于TCP/UDP/Unix的网络类型,可通过客户端实现其他网络类型同步
|
||||
//
|
||||
// 可在 examples 目录下找到示例,示例项目:simple-server-lockstep
|
||||
type Lockstep[ClientID comparable, Command any] struct {
|
||||
clients *synchronization.Map[ClientID, component.LockstepClient[ClientID]] // 接受广播的客户端
|
||||
frames *synchronization.Map[int, []Command] // 所有帧指令
|
||||
|
@ -73,6 +80,8 @@ func (slf *Lockstep[ClientID, Command]) LeaveClient(clientId ClientID) {
|
|||
}
|
||||
|
||||
// StartBroadcast 开始广播
|
||||
// - 在开始广播后将持续按照设定的帧率进行帧数推进,并在每一帧推进时向客户端进行同步,需提前将客户端加入广播队列 JoinClient
|
||||
// - 广播过程中使用 AddCommand 将该帧数据追加到当前帧中
|
||||
func (slf *Lockstep[ClientID, Command]) StartBroadcast() {
|
||||
if slf.running.Swap(true) {
|
||||
return
|
||||
|
@ -82,7 +91,7 @@ func (slf *Lockstep[ClientID, Command]) StartBroadcast() {
|
|||
slf.frameMutex.Lock()
|
||||
currentFrame := slf.currentFrame
|
||||
if slf.frameLimit > 0 && currentFrame >= slf.frameLimit {
|
||||
slf.Stop()
|
||||
slf.StopBroadcast()
|
||||
return
|
||||
}
|
||||
slf.currentFrame++
|
||||
|
@ -100,8 +109,8 @@ func (slf *Lockstep[ClientID, Command]) StartBroadcast() {
|
|||
})
|
||||
}
|
||||
|
||||
// Stop 停止广播
|
||||
func (slf *Lockstep[ClientID, Command]) Stop() {
|
||||
// StopBroadcast 停止广播
|
||||
func (slf *Lockstep[ClientID, Command]) StopBroadcast() {
|
||||
if !slf.running.Swap(false) {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Package component 通用组件的接口定义
|
||||
// - lockstep.go 帧同步组件接口定义
|
||||
// - lockstep_client.go 帧同步组件客户端接口定义
|
||||
// Package component 定义了通用组件的接口
|
||||
// - lockstep.go:帧同步组件接口定义
|
||||
// - lockstep_client.go:帧同步组件客户端接口定义
|
||||
package component
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
package component
|
||||
|
||||
// Lockstep 帧同步组件接口定义
|
||||
// Lockstep 定义了帧同步组件的接口,用于处理客户端之间的同步操作。
|
||||
// 每个客户端需要拥有可比较的ID,同时需要定义帧数据的数据格式。
|
||||
// - ClientID:客户端ID类型
|
||||
// - Command:帧数据类型
|
||||
//
|
||||
// 客户端ID类型通常为玩家ID类型,即通常将玩家作为帧同步客户端使用。
|
||||
// - 内置实现:components.Lockstep
|
||||
// - 构建函数:components.NewLockstep
|
||||
type Lockstep[ClientID comparable, Command any] interface {
|
||||
// JoinClient 加入客户端
|
||||
JoinClient(client LockstepClient[ClientID])
|
||||
|
@ -10,8 +17,8 @@ type Lockstep[ClientID comparable, Command any] interface {
|
|||
LeaveClient(clientId ClientID)
|
||||
// StartBroadcast 开始广播
|
||||
StartBroadcast()
|
||||
// Stop 停止广播
|
||||
Stop()
|
||||
// StopBroadcast 停止广播
|
||||
StopBroadcast()
|
||||
// AddCommand 增加指令
|
||||
AddCommand(command Command)
|
||||
// GetCurrentFrame 获取当前帧
|
||||
|
|
|
@ -33,7 +33,7 @@ func main() {
|
|||
players.Delete(conn.GetID())
|
||||
lockstep.LeaveClient(conn.GetID())
|
||||
if players.Size() == 0 {
|
||||
lockstep.Stop()
|
||||
lockstep.StopBroadcast()
|
||||
}
|
||||
})
|
||||
srv.RegConnectionReceiveWebsocketPacketEvent(func(srv *server.Server, conn *server.Conn, packet []byte, messageType int) {
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
package game
|
||||
|
||||
// Actor 表示游戏中的对象,具有唯一标识符
|
||||
// Actor 表示游戏中的可以放到游戏场景中的游戏对象的基本类型
|
||||
// - 需要注意 Actor 不等于 Player
|
||||
// - 在 Minotaur 中,每个网络连接可以表示一个 Player,而每个玩家可以拥有多个 Actor
|
||||
// - Actor 并非 Player 独有,场景中也可包含各类无主的 Actor
|
||||
// - 内置实现:builtin.Actor
|
||||
// - 构建函数:builtin.NewActor
|
||||
type Actor interface {
|
||||
// SetGuid 设置对象的唯一标识符
|
||||
// - 需要注意的是该函数不应该主动执行,否则可能产生意想不到的情况
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package game
|
||||
|
||||
// AOI2D 感兴趣的领域(Area Of Interest)接口定义
|
||||
// AOI2D 基于2D定义的AOI功能接口
|
||||
// - AOI(Area Of Interest)翻译过来叫感兴趣的区域,是大型多人在线的游戏服务器中一个非常重要的基础模块,用于游戏对象在场景中的视野管理
|
||||
// - 透过 AOI 系统可以在其他玩家或怪物进入视野时得到感知,从而进行相应处理
|
||||
// - 内置实现:builtin.AOI2D
|
||||
// - 构建函数:builtin.NewAOI2D
|
||||
type AOI2D interface {
|
||||
// AddEntity 添加对象
|
||||
AddEntity(entity AOIEntity2D)
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package game
|
||||
|
||||
// AOIEntity2D 基于2D定义的AOI对象功能接口
|
||||
// - AOI 对象提供了 AOI 系统中常用的属性,诸如位置坐标和视野范围等
|
||||
type AOIEntity2D interface {
|
||||
Actor
|
||||
// GetPosition 获取对象位置
|
||||
|
|
|
@ -2,7 +2,8 @@ package game
|
|||
|
||||
import "github.com/kercylan98/minotaur/utils/huge"
|
||||
|
||||
// Attrs 属性
|
||||
// Attrs 游戏属性接口定义
|
||||
// - 属性通常为直接读取配置,是否合理暂不清晰,目前不推荐使用
|
||||
type Attrs interface {
|
||||
SetAttrInt(id int, value int)
|
||||
SetAttrInt8(id int, value int8)
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
// Package game 定义了通用游戏相关的接口
|
||||
// - actor.go:游戏通用对象接口定义
|
||||
// - aoi2d.go:基于2D的感兴趣领域(Area Of Interest)接口定义
|
||||
// - aoi2d_entity.go:基于2D的感兴趣领域(Area Of Interest)对象接口定义
|
||||
// - attrs.go:游戏属性接口定义,属性通常为直接读取配置,是否合理暂不清晰,目前不推荐使用
|
||||
// - fsm.go:有限状态机接口定义
|
||||
// - fsm_state.go:有限状态机状态接口定义
|
||||
//
|
||||
// 其中 builtin 包内包含了内置的实现
|
||||
package game
|
18
game/fsm.go
18
game/fsm.go
|
@ -1,10 +1,26 @@
|
|||
package game
|
||||
|
||||
// FSM 有限状态机
|
||||
// FSM 有限状态机接口定义
|
||||
// - 有限状态机(Finite State Machine,简称FSM),它将系统看做一系列状态,而每个状态都有其对应的行为和转换条件
|
||||
// - 在游戏中,可以将各种游戏对象和游戏系统抽象为状态和转移,使用有限状态机来描述它们之间的关系,来实现游戏的逻辑和行为
|
||||
//
|
||||
// 使用场景
|
||||
// - 角色行为控制:游戏角色的行为通常会根据不同状态来变化,例如走、跑、跳、攻击等。通过使用有限状态机来描述角色的状态和状态之间的转移,可以实现角色行为的流畅切换和控制
|
||||
// - NPC行为控制:游戏中的 NPC 通常需要有一定的 AI 行为,例如巡逻、追击、攻击等。通过使用有限状态机来描述 NPC 的行为状态和转移条件,可以实现 NPC 行为的智能控制
|
||||
// - 游戏流程控制:游戏的各个流程可以看做状态,例如登录、主界面、游戏场景等。通过使用有限状态机来描述游戏的流程状态和转移条件,可以实现游戏流程的控制和管理
|
||||
//
|
||||
// 在服务端中使用 FSM 可以使游戏状态管理更加清晰和简单,清晰各状态职责
|
||||
// - 内置实现:builtin.FSM
|
||||
// - 构建函数:builtin.NewFSM
|
||||
type FSM[State comparable, Data comparable] interface {
|
||||
// Update 执行当前状态行为
|
||||
Update()
|
||||
// Register 注册一个状态到当前状态机中
|
||||
Register(state FSMState[State, Data])
|
||||
// Unregister 取消一个状态的注册
|
||||
Unregister(state State)
|
||||
// HasState 检查是否某状态已注册
|
||||
HasState(state State) bool
|
||||
// Change 改变当前状态为输入的状态
|
||||
Change(state State)
|
||||
}
|
||||
|
|
|
@ -6,10 +6,19 @@ type (
|
|||
FSMStateExitHandle[Data any] func(data Data)
|
||||
)
|
||||
|
||||
// FSMState 有限状态机状态
|
||||
// FSMState 有限状态机状态接口定义
|
||||
// - 描述了 FSM 中的状态行为
|
||||
//
|
||||
// 需要一个可比较的状态类型及相应的数据类型,数据类型在无需使用时支持传入 nil
|
||||
// - 内置实现:builtin.FSMState
|
||||
// - 构建函数:builtin.NewFSMState
|
||||
type FSMState[State comparable, Data any] interface {
|
||||
// GetState 获取当前状态
|
||||
GetState() State
|
||||
// Enter 状态开始行为
|
||||
Enter(data Data)
|
||||
// Update 当前状态行为
|
||||
Update(data Data)
|
||||
// Exit 状态退出行为
|
||||
Exit(data Data)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue