基本 (Primitive) 谱面格式
基本谱面格式是一种最小化的 Phigros 谱面格式,使用 JSON 格式表示
基本谱面格式与官谱完全兼容,仅包含支持谱面所需的基本要素,不包含任何高阶功能
简单来说,基本谱面格式在官谱的基础上增加了缓动与 BPM 列表,并移除了 floorPosition
作用
借助基本谱面格式,Phichain 可以在所有支持的格式间转换 Phigros 谱面
官谱
\
Primitive -- Phichain
/
RPE
由于该格式定义了一种足够简单的格式,在不同格式间转换谱面的的复杂度会显著降低
格式版本
基本谱面格式通常不会更新,但为了兼容性考虑,存在格式版本
当前基本谱面格式的版本为 1
结构
基本谱面格式的结构可以用 TypeScript 类型表示为:
typescript
// 谱面根节点
type PrimitiveChart = {
// 谱面的格式版本,目前恒定为 1
format: number
// 以毫秒为单位的谱面偏移
offset: number
// BPM 列表
bpm_list: BpmList
// 判定线列表
lines: Line[]
}
// 拍数,[a, b, c] 代表 a+b/c 拍
type Beat = [number, number, number]
// 单个 BPM 点,代表一次 BPM 的变化
type BpmPoint = {
// BPM 点所在的拍数
beat: Beat
// BPM 值
bpm: number
}
// BPM 列表
type BpmList = BpmPoint[]
// 判定线
type Line = {
// 判定线的所有音符
notes: Note[]
// 判定线的所有事件
events: Event[]
}
// 事件缓动
type Easing =
| 'linear'
| 'ease_in_sine'
| 'ease_out_sine'
| 'ease_in_out_sine'
| 'ease_in_quad'
| 'ease_out_quad'
| 'ease_in_out_quad'
| 'ease_in_cubic'
| 'ease_out_cubic'
| 'ease_in_out_cubic'
| 'ease_in_quart'
| 'ease_out_quart'
| 'ease_in_out_quart'
| 'ease_in_quint'
| 'ease_out_quint'
| 'ease_in_out_quint'
| 'ease_in_expo'
| 'ease_out_expo'
| 'ease_in_out_expo'
| 'ease_in_circ'
| 'ease_out_circ'
| 'ease_in_out_circ'
| 'ease_in_back'
| 'ease_out_back'
| 'ease_in_out_back'
| 'ease_in_elastic'
| 'ease_out_elastic'
| 'ease_in_out_elastic'
| 'ease_in_bounce'
| 'ease_out_bounce'
| 'ease_in_out_bounce'
// 自定义缓动,元组中的四个数分别代表三次贝塞尔曲线的两个控制点的坐标
// https://cubic-bezier.com
| { custom: [number, number, number, number] }
// 判定线事件
type Event = {
// 事件的类型
kind: 'x' | 'y' | 'rotate' | 'alpha' | 'speed'
// 事件的开始值
start: number
// 事件的结束值
end: number
// 事件开始的拍数
start_beat: Beat
// 事件结束的拍数
end_beat: Beat
// 若 kind 为 speed,该字段将被忽略
easing: Easing
}
// 音符的类型
type NoteKind =
| 'tap'
| 'drag'
| 'flick'
// Hold 音符,包含 Hold 持续时间
| {
hold: { hold_beat: Beat }
}
// 音符
type Note = {
// 音符的类型
kind: NoteKind
// 音符判定的拍数
beat: Beat
// 音符的 x 坐标,画布最左为 -0.5, 最右为 0.5
x: number
// 音符是否在判定线上方
above: boolean
// 音符的速度因子
speed: number
}
示例
下面是一个基本谱面格式的示例:
json
{
"format": 1,
"offset": 0.0,
"bpm_list": [
{
"beat": [0, 0, 1],
"bpm": 120.0
}
],
"lines": [
{
"notes": [
{
"kind": "tap",
"above": true,
"beat": [0, 1, 1],
"x": 0.0,
"speed": 3.0
},
{
"kind": {
"hold": {
"hold_beat": [1, 0, 1]
}
},
"above": true,
"beat": [0, 1, 1],
"x": 0.0,
"speed": 3.0
},
{
"kind": "tap",
"above": true,
"beat": [1, 0, 1],
"x": 337.5,
"speed": 1.0
}
],
"events": [
{
"kind": "x",
"start_beat": [0, 0, 1],
"end_beat": [1, 0, 1],
"start": 0.0,
"end": 0.0,
"easing": "linear"
},
{
"kind": "y",
"start_beat": [0, 0, 1],
"end_beat": [1, 0, 1],
"start": -300.0,
"end": -300.0,
"easing": {
"custom": [0.5, 0.0, 0.5, 1.0]
}
}
]
}
]
}