timeline

package
v0.9.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 28, 2026 License: Apache-2.0 Imports: 1 Imported by: 0

Documentation

Overview

Package timeline 提供帧索引事件时间线原语,解决"逻辑计算瞬间完成、表现播放 需要时间"的表现与逻辑分离问题。

解决的问题:回合制/策略战斗中,服务器 1ms 算完"英雄 A 造成 500 伤害 → 目标 B 死亡 → 胜利结算",但客户端播放技能动画 + 受击特效 + 死亡动画需要 5 秒。如果 服务器算完就下一步,前端还在播第一步的动画;如果服务器硬等客户端播完,浪费资源 且容易被外挂利用。

框架方案:服务器一次算完所有结果,但打上**时间偏移**(offset ticks),组成一条 有序的事件时间线下发。客户端按时间线顺序消费,策划调整动画时长时不需要改服务端。

核心机制:

  • Timeline[E]:事件时间线,事件按 offset(相对起始的帧偏移)排序;
  • Append(offset, event):添加事件,可指定"在第 N 帧播放";
  • After(prevDuration):自动累加偏移,实现"上一步播完后再开始下一步";
  • Drain(tick):推进时间线到 tick,返回到期的事件(客户端消费);
  • Snapshot():导出整条时间线(一次性下发给客户端)。

与相邻原语的关系:

  • ability 管理"施法阶段"(蓄力→释放→命中),timeline 管理"计算结果的播放时序";
  • delayqueue/timerqueue 是墙钟定时器(cron 任务、超时踢人),timeline 是游戏帧 时间线(战斗回放);
  • eventbus 是发布-订阅(异步解耦),timeline 是有序时序(同步播放)。

并发安全:Timeline 不加锁(由单个计算 goroutine 构造,构造完后只读下发)。 零值可用:直接声明即可使用。

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Entry

type Entry[E any] struct {
	// Offset 相对时间线起始的帧偏移(tick 数)。0 = 立即生效。
	Offset int
	// Event 事件内容(由业务定义:伤害结果、buff 变化、表现提示等)。
	Event E
}

Entry 是时间线上的一个事件条目。

type Player

type Player[E any] struct {
	// contains filtered or unexported fields
}

Player 按帧推进消费时间线事件(客户端侧或服务端延迟生效)。 非并发安全。

func NewPlayer

func NewPlayer[E any](tl *Timeline[E]) *Player[E]

NewPlayer 从 Timeline 的快照创建播放器。

func NewPlayerFromEntries

func NewPlayerFromEntries[E any](entries []Entry[E]) *Player[E]

NewPlayerFromEntries 从已排序的条目列表创建播放器(如从网络反序列化)。

func (*Player[E]) Advance

func (p *Player[E]) Advance() []E

Advance 推进一帧(tick++),返回本帧到期的事件。

func (*Player[E]) AdvanceTo

func (p *Player[E]) AdvanceTo(tick int) []E

AdvanceTo 推进到指定 tick(不回退),返回 (prevTick, tick] 之间到期的所有事件。

func (*Player[E]) Done

func (p *Player[E]) Done() bool

Done 是否所有事件已消费完。

func (*Player[E]) Remaining

func (p *Player[E]) Remaining() int

Remaining 返回剩余未消费的事件数。

func (*Player[E]) Tick

func (p *Player[E]) Tick() int

Tick 返回当前帧。

type Timeline

type Timeline[E any] struct {
	// contains filtered or unexported fields
}

Timeline 是一条帧索引事件时间线。E 是事件类型。 零值可用。构造完成后通常一次性下发客户端,或由 Player 逐帧消费。

func (*Timeline[E]) After

func (t *Timeline[E]) After(duration int, event E)

After 在"当前累计偏移 + duration"处添加事件,并推进内部光标。 用于链式构造:"第一步 → 等 30 帧 → 第二步 → 等 20 帧 → 第三步"。

tl.After(0, hitA)     // offset=0
tl.After(30, hitB)    // offset=30
tl.After(20, victory) // offset=50

func (*Timeline[E]) Append

func (t *Timeline[E]) Append(offset int, event E)

Append 在偏移 offset(帧数)处添加事件。offset 可乱序添加,Drain/Snapshot 时排序。

func (*Timeline[E]) At

func (t *Timeline[E]) At(offset int, event E)

At 在固定帧偏移处添加事件(Append 的别名,语义更清晰)。

func (*Timeline[E]) Duration

func (t *Timeline[E]) Duration() int

Duration 返回时间线总长度(最大 offset)。

func (*Timeline[E]) Len

func (t *Timeline[E]) Len() int

Len 返回事件总数。

func (*Timeline[E]) Snapshot

func (t *Timeline[E]) Snapshot() []Entry[E]

Snapshot 返回排好序的事件列表(一次性下发客户端)。首次调用排序,后续调用 如果没有新增事件则复用排序结果。

func (*Timeline[E]) Stagger

func (t *Timeline[E]) Stagger(interval int, events ...E)

Stagger 在当前 After 光标位置,以固定间隔 interval 添加多个事件(群体技能、 连续弹幕)。不推进 After 光标。

tl.After(0, castStart)
tl.Stagger(5, hit1, hit2, hit3) // offset: cursor, cursor+5, cursor+10
tl.After(20, castEnd)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL