Skip to content

基本 (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]
          }
        }
      ]
    }
  ]
}

基于 LGPL 协议发布