Skip to content

节点编辑器

TIP

🧪 Working in Progress

基于 Vue Flow 定制。

节点编辑器是一个新的设想,通过编辑节点来搭建游戏流程。

而 Fountain/AdvScript 用于描述每个节点中的内容。

计划

  • [ ] 节点会话流程

功能

  • 自动布局
  • 操作节点
    • 拖拽
    • 缩放
    • 选择
    • 复制
    • 删除
    • 连接
  • 修改节点
    • 节点类型
    • 节点内容

Flow 格式

Flow 是一个节点与边的集合,可在节点编辑器中描述节点信息。

对于最终的游戏来说,会对节点编辑中的 Flow 数据进行简化。

ts
import type { AdvFlowEdge } from './edge'
import type { AdvFlowNode } from './node'

export * from './edge'
export * from './node'

/**
 * import type { FlowExportObject } from '@vue-flow/core'
 */
export interface AdvFlow {
  nodes: AdvFlowNode[]
  edges: AdvFlowEdge[]
}

节点格式

一组节点构成一个流程,作为一个游戏场景。

一个游戏章节可包含多个场景。

场景即将结束时,根据选择预加载下一个场景。

基础节点格式

ts
/**
 * 考虑到需要通过节点编辑器进行编辑
 *
 * 结构参考 React/Vue Flow 的节点结构
 */

export interface AdvBaseNode {
  id: string
  /**
   * 节点类型
   */
  type: string
  /**
   * 目标节点
   *
   * @runtime
   */
  target?: string
}

export type AdvFlowNode = AdvBaseNode & Node

export interface AdvBackgroundNode extends AdvBaseNode {
  type: 'background'
  /**
   * 背景名称
   *
   * 场景 ID:sceneId
   */
  name: string
  /**
   * 背景图片地址
   *
   * - url
   * - base64
   */
  src: string
}

export interface AdvTachieNode extends AdvBaseNode {
  type: 'tachie'
  /**
   * 角色名称
   */
  name: string
  /**
   * 角色状态
   *
   * @default 'default'
   */
  status: string
  /**
   * 动作
   */
  action: 'enter' | 'exit'

  enter?: string | string[]
  exit?: string | string[]
}

export interface AdvDialogNode {
  type: 'dialog'
  /**
   * 对话内容
   */
  text: string
  /**
   * 对话角色 ID
   */
  speaker?: string
}

export interface AdvDialoguesNode extends AdvBaseNode {
  type: 'dialogues'
  /**
   * 对话列表
   */
  dialogues: AdvDialogNode[]

  /**
   * 场景 ID
   */
  sceneId?: string
  /**
   * 背景音乐 ID
   */
  bgmThemeId?: string
}

/**
 * 结束节点
 *
 * @runtime
 */
export interface AdvEndNode extends AdvBaseNode {
  type: 'end'
}

/**
 * adv node
 */
export type AdvNode = AdvBaseNode | AdvBackgroundNode | AdvTachieNode | AdvDialoguesNode | AdvEndNode

所有节点继承自基础节点格式。

会话节点

  • 自动 TTS
  • Fountain 文本包含多段人物对话

选择节点

  • 选项
  • 跳转不同节点

事件节点

  • 设置/修改背景图片
  • 设置/修改背景音乐

代码节点

  • 执行自定义代码

其他节点

未来扩展

Edge 格式

ts
import type { DefaultEdge } from '@vue-flow/core'

/**
 * Edge
 */
export interface AdvFlowEdge extends DefaultEdge {
  id: string
  source: string
  target: string
}

设计想法

我们希望最终的节点信息可以通过节点编辑器编辑与定制。

对于,xyflow 节点库来说,他们将 nodesedges 分开描述。

ts
export const initialNodes = [
  {
    id: '1',
    type: 'input',
    data: { label: 'Input Node' },
    position: { x: 250, y: 25 },
  },
  {
    id: '2',
    // you can also pass a React component as a label
    data: { label: 'Default Node' },
    position: { x: 100, y: 125 },
  },
  {
    id: '3',
    type: 'output',
    data: { label: 'Output Node' },
    position: { x: 250, y: 250 },
  },
]

export const initialEdges = [
  { id: 'e1-2', source: '1', target: '2' },
  { id: 'e2-3', source: '2', target: '3', animated: true },
]

对于 Flow 的复杂案例,他们需要满足多对多的情况。 且还可能包含节点的位置、缩放、样式等信息,而这部分信息在最终的游戏数据(JSON)中通常是不需要的。

在我们的场景中,节点流通常是一对一的,从 A 节点跳转到 B 节点,而不会从 A 节点同时跳转至 B 和 C 节点。 存在特殊的选择节点,它可能因不同选择而跳转至不同节点,但跳转的目标节点仍是单个。

因此必然仍旧存在一个从节点信息转化为最终游戏 JSON 的过程,以对数据进行压缩。 类似于 PSDJPG 的转化。

在拿到 JSON 后我们还需一个运行时函数处理,读取 JSON 加载上下文(节点列表),生成相关 Map 和操作函数,方便直接跳转映射节点。

也就是会有三种格式。

  1. 原始节点数据
  2. 游戏 JSON 数据
  3. 游戏运行时节点树(上下文)

对于用户来说,需要关心的通常只有 2

格式 1(节点编辑器生成) 与 3(游戏运行时生成) 通常是不可见的。

可使用 AI 生成数据格式 2,在需要编辑时转化成 1,运行时会转化成 3