85 Commits
Author SHA1 Message Date
obugs 4463ba1b87 Merge branch 'check' into main 2026-01-29 19:43:28 +08:00
OLDREDSTONE 46fbe848d3 Merge branch 'check' 2026-01-24 18:01:51 +08:00
OLDREDSTONE 5555e612b3 添加对文档编撰的说明 2026-01-24 18:00:59 +08:00
OLDREDSTONE e23b6000c4 制作人员表增加了 2026-01-24 17:41:28 +08:00
T_Terrenceandobugs c8bc990412 做了窗口相关的动画的教程 2026-01-24 17:33:04 +08:00
obugs aedf303e89 Merge pull request 'main' (#47) from kuanpan/rd.rdlevel.cn:main into check
Reviewed-on: RDCNWebs/rd.rdlevel.cn#47
2026-01-24 17:32:16 +08:00
kuanpan 6a433657f6 更新 pages/moverow.md 2026-01-22 11:41:05 +08:00
kuanpan 64fe405d2e 更新 pages/oneshotbeat.md 2026-01-22 09:17:07 +08:00
kuanpan f18d0974ac 更新 pages/moverow.md 2026-01-22 09:16:05 +08:00
kuanpan 4d7e2961f8 更新 pages/appendix_gimmicks.md 2026-01-20 22:13:50 +08:00
kuanpan a26095bea2 merge upstream 2026-01-20 21:59:52 +08:00
kuanpan a6711f859f 更新 pages/moreoneshotbeats.md 2026-01-20 21:57:10 +08:00
obugs d6e5ff39e3 Merge pull request '添加启用高级编辑器功能教程' (#46) from dev_mode into main
Reviewed-on: RDCNWebs/rd.rdlevel.cn#46
2026-01-20 15:44:49 +08:00
23333 f315aa9f2e 添加启用高级编辑器功能教程 2026-01-20 15:36:11 +08:00
kuanpan 7300fbfa16 更新 pages/classicbeat.md 2026-01-17 13:16:32 +08:00
kuanpan 8486bd807e 更新 pages/moreoneshotbeats.md 2026-01-17 13:01:21 +08:00
obugs 41ada2cf46 Merge pull request 'main' (#43) from kuanpan/rd.rdlevel.cn:main into main
Reviewed-on: RDCNWebs/rd.rdlevel.cn#43
2026-01-17 11:11:25 +08:00
kuanpan 8ee381909f 更新 pages/moreoneshotbeats.md 2026-01-17 10:58:29 +08:00
kuanpan ae9c93deb2 merge upstream 2026-01-17 10:55:59 +08:00
kuanpan d922a6fae6 上传文件至 images 2026-01-17 10:31:20 +08:00
kuanpan 006e2f2ff1 删除 images/hold.jpg 2026-01-17 10:29:45 +08:00
kuanpan c14a85c464 上传文件至 images 2026-01-17 09:46:28 +08:00
OLDREDSTONE 5aedbbfbe0 [RDView] 修复 hsb 属性读取异常和渲染异常 2026-01-16 23:31:09 +08:00
OLDREDSTONE a14b4436f5 [RDView] 啊草我 degug 怎么还在里面( 2026-01-16 20:14:42 +08:00
OLDREDSTONE 4e1e57b08e [RDView] 现已可用,在 pages/classicbeat 可查看第一个用例 2026-01-16 20:07:12 +08:00
OLDREDSTONE 51e8b1f449 [RDView2] 更新 2026-01-15 19:01:12 +08:00
OLDREDSTONE 758645041b [RDView2] DOM 渲染基本完工,进入可行性测试阶段 2026-01-14 22:20:06 +08:00
OLDREDSTONE fb2e0e124b 修复 json 解析异常未捕获的错误 2026-01-14 00:55:38 +08:00
OLDREDSTONE 006a5fe4f5 changelog 2026-01-14 00:46:21 +08:00
OLDREDSTONE 1e4e94cce7 [rdview2] 性能测试 2026-01-14 00:43:51 +08:00
OLDREDSTONE 55c53278ea [RDView]修复事件组内的单发拍长按不显示的异常 2026-01-12 21:10:13 +08:00
OLDREDSTONE 089f4c551d Merge branch 'main' of https://git.obugs.cn/RDCNWebs/rd.rdlevel.cn 2026-01-12 20:58:30 +08:00
OLDREDSTONE 9a060eb6ff [RDView] 更新细分拍的图像,添加长按二拍设置 2026-01-12 20:58:25 +08:00
obugs 6b0da44786 Merge pull request '更新 pages/appendix_audios.md' (#42) from Xiaolvjun/rd.rdlevel.cn:main into main
Reviewed-on: RDCNWebs/rd.rdlevel.cn#42
2026-01-12 19:51:46 +08:00
Xiaolvjun 50bef7ba6d 更新 pages/credits.md 2026-01-12 19:51:00 +08:00
Xiaolvjun 6f8e88b93d 更新 pages/appendix_audios.md 2026-01-12 18:32:36 +08:00
OLDREDSTONE 0fecdf5b19 优化渲染流程(虽然还是很卡 2025-12-31 22:11:33 +08:00
OLDREDSTONE f51785f649 Merge branch 'main' of https://git.obugs.cn/RDCNWebs/rd.rdlevel.cn 2025-12-12 15:25:00 +08:00
OLDREDSTONE c1b00aa34d 【实验】rdview2 样例 2025-12-12 15:24:52 +08:00
OLDREDSTONE a01042af6a 【实验】添加对 rdview2 的支持 2025-12-12 15:24:30 +08:00
OLDREDSTONE 9d14a88a98 取消群号的缩放 2025-12-12 15:23:35 +08:00
obugs 9714689690 Merge pull request '事件列表与特效列表更新' (#41) from 0x4D2/rd.rdlevel.cn:main into main
Reviewed-on: RDCNWebs/rd.rdlevel.cn#41
2025-12-05 11:19:45 +08:00
0x4D2 dca868ac71 气球
Signed-off-by: 0x4D2 <1706119930@qq.com>
2025-12-04 23:21:41 +08:00
0x4D2 81b54f7fbd 更新附录中的事件列表
Signed-off-by: 0x4D2 <1706119930@qq.com>
2025-12-04 23:16:12 +08:00
0x4D2 c467825ec1 更新附录中的事件列表
Signed-off-by: 0x4D2 <1706119930@qq.com>
2025-12-04 23:15:22 +08:00
OLDREDSTONE 91fed78ce1 更新日志 2025-11-29 16:46:38 +08:00
OLDREDSTONE 9becdf3f88 更改了页面右侧功能区的样式 2025-11-29 16:45:51 +08:00
OLDREDSTONE 547181bff1 修改目录样式 2025-11-29 16:42:42 +08:00
OLDREDSTONE 052463645b 更新日志 2025-11-29 15:27:39 +08:00
OLDREDSTONE 2d6125b082 Merge branch 'new' 2025-11-29 15:05:47 +08:00
OLDREDSTONE 69165da834 更正部分文字 2025-11-29 14:38:43 +08:00
OLDREDSTONE 90a764dd7f 第三方工具添加 AserDeco 介绍页面 2025-11-29 14:30:41 +08:00
OLDREDSTONE 7c888f5249 修改暗色主题部分颜色 2025-11-29 14:14:54 +08:00
OLDREDSTONE 214b7856bd 更改了群号 2025-11-29 14:14:35 +08:00
OLDREDSTONE d83cc5a829 删除 banner 2025-11-29 11:53:07 +08:00
OLDREDSTONE 837336a321 添加网页简介 2025-11-02 19:14:24 +08:00
OLDREDSTONE 62c9b8517f 添加 0x4D2 更新的 credit - OLDREDSTONE 2025-11-02 12:58:49 +08:00
OLDREDSTONE 7921ecc981 Merge branch 'new' of https://git.obugs.cn/RDCNWebs/rd.rdlevel.cn into new 2025-11-02 12:47:05 +08:00
OLDREDSTONE 745dbaee3e 添加 0x4D2 更新的 credit 2025-11-02 12:46:54 +08:00
obugs e28eea0a77 Merge pull request 'main' (#37) from main into new
Reviewed-on: RDCNWebs/rd.rdlevel.cn#37
2025-11-02 11:03:10 +08:00
obugs 517c75bb66 Merge pull request '添加屏幕朗读事件的描述' (#36) from 0x4D2/rd.rdlevel.cn:main into main
Reviewed-on: RDCNWebs/rd.rdlevel.cn#36
2025-11-02 11:02:06 +08:00
0x4D2 10db121ad7 添加屏幕朗读事件
Signed-off-by: 0x4D2 <1706119930@qq.com>
2025-11-01 21:13:35 +08:00
0x4D2 d51204985f 上传文件至 images
Signed-off-by: 0x4D2 <1706119930@qq.com>
2025-11-01 20:53:33 +08:00
0x4D2 bc7518ba0b 上传文件至 images 2025-11-01 20:53:31 +08:00
OLDREDSTONE a0d296a818 目录变动 #30 2025-11-01 19:46:42 +08:00
OLDREDSTONE bb0cb7de3a 大致修改内容布局 #30 2025-11-01 19:30:36 +08:00
OLDREDSTONE ae32b0e7aa 双人模式措辞更改 #26 2025-11-01 18:03:36 +08:00
OLDREDSTONE dca2f87b4b 添加检索功能脚本 #35 2025-11-01 18:02:27 +08:00
OLDREDSTONE 7aa95ab0ba 删除 banner 2025-11-01 18:02:06 +08:00
OLDREDSTONE 7a2e16d714 添加检索功能接口 #35 2025-11-01 18:00:52 +08:00
OLDREDSTONE f588b3ce92 调整目录结构 #30 2025-11-01 17:56:34 +08:00
OLDREDSTONE 5d7d99b24c 更新侧边栏顺序 2025-11-01 16:49:14 +08:00
obugs fdad67efee Merge pull request 'webhoop' (#17) from others into main
Reviewed-on: RDCNWebs/rd.rdlevel.cn#17
2025-10-27 19:21:48 +08:00
obugs 1884e5097e Merge pull request '1026' (#16) from others into main
Reviewed-on: RDCNWebs/rd.rdlevel.cn#16
2025-10-26 22:32:57 +08:00
obugs 718be9e9bf Merge pull request '样式更新:表格行颜色交替显示优化,提升可读性' (#15) from others into main
Reviewed-on: RDCNWebs/rd.rdlevel.cn#15
2025-10-21 22:03:52 +08:00
obugs 4d37019e1a Merge pull request '添加精灵相关内容' (#14) from others into main
Reviewed-on: RDCNWebs/rd.rdlevel.cn#14
2025-10-18 14:11:32 +08:00
obugs 9114b1664b Merge pull request '日常维护' (#13) from others into main
Reviewed-on: RDCNWebs/rd.rdlevel.cn#13
2025-10-18 11:41:22 +08:00
obugs 56e78752b2 Merge pull request '更新字体' (#12) from others into main
Reviewed-on: RDCNWebs/rd.rdlevel.cn#12
2025-10-16 11:58:26 +08:00
obugs 7c35d418c0 Merge pull request 'banner 又加回来了' (#11) from others into main
Reviewed-on: RDCNWebs/rd.rdlevel.cn#11
2025-10-11 23:17:47 +08:00
obugs 520f68be8f Merge pull request '添加了 7th beat games 授权' (#10) from others into main
Reviewed-on: RDCNWebs/rd.rdlevel.cn#10
2025-09-27 16:51:00 +08:00
obugs 4e92254eb8 Merge pull request '删除 Banner' (#9) from others into main
Reviewed-on: RDCNWebs/rd.rdlevel.cn#9
2025-08-31 19:23:40 +08:00
obugs 5e92f750a6 Merge pull request '对不起巧麦(' (#5) from others into main
Reviewed-on: RDCNWebs/rd.rdlevel.cn#5
2025-08-01 22:12:12 +08:00
obugs 1d9514bd7b Merge pull request '添加了本地状态记录' (#4) from others into main
Reviewed-on: RDCNWebs/rd.rdlevel.cn#4
2025-07-21 00:49:43 +08:00
obugs c323edf184 Merge pull request 'others' (#3) from others into main
Reviewed-on: RDCNWebs/rd.rdlevel.cn#3
2025-07-19 21:18:47 +08:00
obugs a702602ef5 Merge pull request '0719 更新' (#2) from others into main
Reviewed-on: RDCNWebs/rd.rdlevel.cn#2
2025-07-19 18:56:04 +08:00
69 changed files with 3431 additions and 633 deletions
+33 -11
View File
@@ -1,12 +1,32 @@
# 节奏医生中文编辑器教程网站
## 预览和编辑
## 预览
### [Visual Studio Code](https://code.visualstudio.com/)
此项目基于 [docsify](https://docsify.js.org/#/) 编辑,并使用 [RDView](https://github.com/OLDRedstone/RDView) 显示编辑器可交互模块。
此项目基于 [docsify](https://docsify.js.org/#/) 编辑,并使用 [RDView](https://github.com/OLDRedstone/RDView) 和 [RhythmBase.View(RDTKView)](https://github.com/OLDRedstone/RhythmBase.View) 显示编辑器可交互模块。
可以参考以下多种方案预览编辑效果。
- 确保 [安装 markdown-rdview-support](https://github.com/OLDRedstone/markdown-rdview-support) 即可预览 RDView 内容。
- [安装 docsify](https://docsify.js.org/#/quickstart) 以实时预览页面。
```bash
npm i docsify-cli -g
```
- 运行以下命令以启动本地服务器实时预览。
```bash
docsify s
```
- 在 Visual Studio Code 插件商店[安装 Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) 以预览。
### RDView
> ### 此条目即将废弃。
> 请优先使用 RhythmBase.View 格式。
- [安装 markdown-rdview-support](https://github.com/OLDRedstone/markdown-rdview-support) 以预览 RDView 内容。
如果成功安装,那么以下内容的 markdown 预览应当是一个事件栏。
```rdview 7 5 1
@@ -15,16 +35,18 @@ es.SetCrotchetsPerBar_4 0 1[];
eb.AddClassicBeat 0 2[tick=6];
```
- 确保 [安装 docsify](https://docsify.js.org/#/quickstart) 以实时预览页面。
### RhythmBase.View
```bash
npm i docsify-cli -g
```
RDView 的替代。
可以直接使用关卡文件内格式进行展示。
暂无计划支持 Visual Studio Code 内预览。(~~感觉没必要支持~~)
可以访问[此处](https://view.obugs.cn/)以预览效果和获得额外属性说明。
- 运行以下命令以启动本地服务器实时预览。
## 编辑
```bash
docsify s
```
请尽量使用 [RhythmBase.View(RDTKView)](https://github.com/OLDRedstone/RhythmBase.View) 格式展示事件。
本教程后期将会逐步迁移模块指此格式。
## 其他
Game assets courtesy of [7th Beat Games](https://7thbe.at/). Game assets are excluded from this site's license.
+15 -16
View File
@@ -4,6 +4,7 @@
margin: 0;
& img{
image-rendering: pixelated;
width: 64px;
height: 32px;
}
}
@@ -11,23 +12,22 @@
- [<img src="/indexicon/Intro.png"/><p>序</p>](/pages/intro.md)
- [<img src="/indexicon/changelog.png"/><p>更新信息</p>](/pages/changelog.md)
- 入门:基础
- [<img src="/indexicon/changegameversion.png"/><p>修改游戏版本</p>](/pages/changegameversion.md)
- [<img src="/indexicon/importandexport.png"/><p>导入与导出</p>](/pages/importandexport.md)
- [<img src="/indexicon/createbuiltincharacter.png"/><p>创建游戏内置角色</p>](/pages/createbuiltincharacter.md)
- 基础:熟悉编辑器
- [<img src="/indexicon/changegameversion.png"/><p>修改游戏配置</p>](/pages/changegameversion.md)
- [<img src="/indexicon/editorinterface.png"/><p>编辑器界面与快捷键</p>](/pages/editorinterface.md)
- 入门:基础机制
- [<img src="/indexicon/importandexport.png"/><p>导入与导出</p>](/pages/importandexport.md)
- 基础:游戏机制
- [<img src="/indexicon/createbuiltincharacter.png"/><p>创建游戏内置角色</p>](/pages/createbuiltincharacter.md)
- [<img src="/indexicon/classicbeat.png"/><p>普通拍子</p>](/pages/classicbeat.md)
- [<img src="/indexicon/oneshotbeat.png"/><p>单发拍子</p>](/pages/oneshotbeat.md)
- [<img src="/indexicon/holdbeat.png"/><p>长按</p>](/pages/holdbeat.md)
- 基础:文字
- [<img src="/indexicon/floatingtext.png"/><p>浮动文字</p>](/pages/floatingtext.md)
- [<img src="/indexicon/captions.png"/><p>其他文字事件</p>](/pages/captions.md)
- 基础:轨道特效
- 基础:基本特效
- [<img src="/indexicon/moverow.png"/><p>轨道移动</p>](/pages/moverow.md)
- [<img src="/indexicon/settheme.png"/><p>场景与主题</p>](/pages/settheme.md)
- [<img src="/indexicon/rowfx.png"/><p>轨道视效</p>](/pages/rowfx.md)
- 进阶:节奏设计
- [<img src="/indexicon/settheme.png"/><p>场景与主题</p>](/pages/settheme.md)
- [<img src="/indexicon/captions.png"/><p>文字事件</p>](/pages/captions.md)
- [<img src="/indexicon/vfx.png"/><p>视觉效果</p>](/pages/vfx.md)
- 进阶:关卡设计
- [<img src="/indexicon/moreclassicbeats.png"/><p>普通拍的衍生节奏型</p>](/pages/moreclassicbeats.md)
- [<img src="/indexicon/moreoneshotbeats.png"/><p>单发拍的衍生节奏型</p>](/pages/moreoneshotbeats.md)
- [<img src="/indexicon/beatpatterndesign.png"/><p>采音和节奏设计</p>](/pages/beatpatterndesign.md)
@@ -36,15 +36,13 @@
- [<img src="/indexicon/twoplayers.png" width="64px"/><p>双人模式设计</p>](/pages/twoplayers.md)
- [<img src="/indexicon/accessibledesign.png"/><p>无障碍设计</p>](/pages/accessibledesign.md)
- 进阶:视觉特效
- [<img src="/indexicon/room.png"/><p>房间</p>](/pages/room.md)
- [<img src="/indexicon/camera.png"/><p>镜头移动</p>](/pages/camera.md)
- [<img src="/indexicon/roomfx.png"/><p>房间视效</p>](/pages/roomfx.md)
- [<img src="/indexicon/camerafx.png"/><p>镜头带来的额外视效</p>](/pages/camerafx.md)
- [<img src="/indexicon/vfxpro.png"/><p>视觉干扰</p>](/pages/vfxpro.md)
- [<img src="/indexicon/camerafx.png"/><p>摄像机视效</p>](/pages/camerafx.md)
- [<img src="/indexicon/hallofmirror.png"/><p>镜厅</p>](/pages/hallofmirror.md)
- [<img src="/indexicon/vfx.png"/><p>视觉干扰</p>](/pages/vfx.md)
- [<img src="/indexicon/windowmove.png"/><p>窗口移动</p>](/pages/windowmove.md)
- [<img src="/indexicon/windowmove.png"/><p>窗口相关的动画</p>](/pages/WindowDance.md)
- [<img src="/indexicon/hand.png"/><p>手</p>](/pages/hand.md)
- 进阶:自制素材
- [<img src="/indexicon/character.png"/><p>自制角色与精灵资源</p>](/pages/spritesheet.md)
- [<img src="/indexicon/decoration.png"/><p>使用精灵</p>](/pages/decoration.md)
- [<img src="/indexicon/assets.png"/><p>场景资源</p>](/pages/assets.md)
@@ -56,6 +54,7 @@
- 高级:第三方工具
- [<img src="/indexicon/3rdparty_coderd.png"/><p>[Python]CodeRD</p>](/pages/3rdparty_coderd.md)
- [<img src="/indexicon/3rdparty_rdtk.png"/><p>[C#]RhythmBase</p>](/pages/3rdparty_rdtk.md)
- [<img src="/indexicon/3rdparty_aserdeco.png" width="64px"/><p>[lua]AserDeco插件</p>](/pages/3rdparty_aserdeco.md)
- 附录
- [<img src="/indexicon/events.png"/><p>事件列表</p>](/pages/appendix_events.md)
- [<img src="/indexicon/vfxs.png"/><p>预设特效列表</p>](/pages/appendix_vfxs.md)
Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 701 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 639 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 609 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

+106 -80
View File
@@ -1,29 +1,31 @@
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>节奏医生编辑器教程</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta
name="description"
content="这里是关于节奏医生编辑器的中文完全指南!"
>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
<link rel="stylesheet" href="/style/light.css">
<link rel="stylesheet" href="/style/dark.css">
<link rel="stylesheet" href="/style/color.css">
<link rel="stylesheet" href="/style/rdview.css">
<link rel="stylesheet" href="/style/otto.css">
<link rel="stylesheet" href="/style/special.css">
</head>
<head>
<meta charset="UTF-8">
<title>节奏医生编辑器教程</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="description" content="Description">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
<link rel="stylesheet" href="/style/light.css">
<link rel="stylesheet" href="/style/dark.css">
<link rel="stylesheet" href="/style/color.css">
<link rel="stylesheet" href="/style/rdview.css">
<link rel="stylesheet" href="/style/otto.css">
<link rel="stylesheet" href="/style/special.css">
</head>
<body>
<div id="app">加载中...</div>
<script>
$docsify = {
name: '节奏医生编辑器教程',
<body>
<div id="app">加载中...</div>
<script>
$docsify = {
name: "节奏医生编辑器教程",
notFoundPage: "/404.md",
homepage: '/pages/intro.md',
homepage: "/pages/intro.md",
loadSidebar: true,
loadNavbar: true,
coverpage: false,
@@ -31,62 +33,86 @@
subMaxLevel: 4,
mergeNavbar: true,
};
</script>
<script type="module">
import '/script/rdview.js';
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
loadRDView()
const originalCodeRenderer = $docsify.markdown?.renderer?.code;
$docsify = {
...$docsify,
...{
markdown: {
renderer: {
code: function (code, lang) {
if (lang.trim().startsWith('rdview')) {
return RDViewRender(lang, code);
}
return originalCodeRenderer ? originalCodeRenderer(code, lang) : `<pre data-lang="${lang}"><code>${escapeHtml(code)}</code></pre>`;
},
image: function (src, title, alt) {
return `<div class="image-tip"><img class="medium-zoom-image" src="${src}" alt="${alt}">${alt ? `<p>${alt}</p>` : ""}</div>`;
},
}
},
switchLightDarkMode: {
useSwitchMode: true,
top: 130,
right: 26,
svgColor: '#7d7b75',
},
search: {
noData: {
'/': '没有找到结果!'
},
paths: 'auto',
placeholder: {
'/': '搜索'
},
hideOtherSidebarContent: true,
},
</script>
<script type="module">
import "./script/rdview.js";
import {render} from "./script/rdtkview_render.js";
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
};
</script>
<script src="/script/docsify.min.js"></script>
<script src="/script/zoom-image.min.js"></script>
<script src="/script/search.min.js"></script>
<script src="/script/emoji.min.js"></script>
<script src="/script/docsify-copy-code.min.js"></script>
<script src="/script/switchLightDarkMode.js"></script>
<script src="/script/otto.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-yaml.js"></script>
<script type="module" src="/script/special.js"></script>
</body>
</html>
loadRDView();
const originalCodeRenderer = $docsify.markdown
?.renderer?.code;
function codeblockRender(code, lang) {
if (lang.trim().startsWith("rdview")) {
return RDViewRender(lang, code);
}
// else if (lang.trim().startsWith("rdtkview")) {
// const args = lang.slice(8).trim().split(" ");
// const width = parseInt(args[0]) || 8;
// const height = parseInt(args[1]) || 4;
// const scale = parseFloat(args[2]) || 2.0;
// const result = render(code, width, height, scale);
// result.toString = () => result;
// return result;
// }
return originalCodeRenderer
? originalCodeRenderer(code, lang)
: `<pre data-lang="${lang}"><code>${
escapeHtml(code)
}</code></pre>`;
}
$docsify = {
...$docsify,
...{
markdown: {
renderer: {
code: (code, lang) => {
return codeblockRender(code, lang);
},
image: function (src, title, alt) {
return `<div class="image-tip"><img class="medium-zoom-image" src="${src}" alt="${alt}">${
alt ? `<p>${alt}</p>` : ""
}</div>`;
},
},
},
switchLightDarkMode: {
useSwitchMode: true,
top: 130,
right: 26,
svgColor: "#7d7b75",
},
search: {
noData: {
"/": "没有找到结果!",
},
paths: "auto",
placeholder: {
"/": "搜索",
},
hideOtherSidebarContent: true,
},
},
};
</script>
<script type="module" src="./script/special.js"></script>
<!-- <script src="/script/docsify.min.js"></script> -->
<script src="/script/zoom-image.min.js"></script>
<script src="/script/search.min.js"></script>
<script src="/script/emoji.min.js"></script>
<!-- <script src="/script/docsify-copy-code.min.js"></script> -->
<script src="/script/switchLightDarkMode.js"></script>
<script src="/script/otto.js"></script>
<script src="/script/custommethod-search.js"></script>
<!-- <script
src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-yaml.js"
></script> -->
</body>
</html>
+29
View File
@@ -0,0 +1,29 @@
# AserDeco
AserDeco 是一个 [Aseprite](https://www.aseprite.org/) 插件,用于将已有的 Aseprite 工程文件导出为节奏医生可以使用的精灵图文件。
## 下载
可以在[这里](https://github.com/OLDRedstone/Aserdecoration/releases/)下载到最新版的 AserDeco 插件。
## 安装:
**双击 .aseprite-extension 文件**或**依次点击**`编辑-首选项-扩展-添加扩展`以安装。
若需要更改语言,依次点击`窗口-更改 Aserdecoration 的语言`,之后以上述方法重启插件。
## 使用
在 Aseprite 里制作精灵图时,
1. 选择需要导出的 Aseprite 工程文件,
1. 调整帧持续时间(可选)
1. 创建循环节,
1. 选择多个帧,
1. 右键帧序号,
1. 选择`设置循环节`
1. 将循环节名称设置为精灵图表情名称,
1. 调整循环节参数,
1. 保存文件,
1. 依次点击`文件-导出...-导出节奏医生精灵图`以弹出导出对话框,
插件将会以**循环节名称**创建精灵表情,并以**循环节的动画方向**、**帧的持续时(可选)**和**对话框内的参数**在**已打开的 Aseprite 工程文件同一位置**处创建与工程文件同名的精灵图 .png 和 .json 文件。
+92
View File
@@ -0,0 +1,92 @@
# 窗口相关的动画
在1.0正式版更新后,窗口被单独提取成了一个独立的板块:**窗口板块**。为了避免剧透,这个板块默认是隐藏的,要让这个板块显示出来,我们需要在动作板块先放一个窗口动效事件,或者在编辑器设置中的显示窗口标签栏设置为**总是报告**,这个板块才会显示出来。
![“总是报告”设置](../images/Window_Dance_Always_Active.png)
我们可以看到,窗口事件比以前多了很多。而且4个窗口都像房间板块一样每个窗口都占了一行。所有事件都只会对其所在行对应的窗口生效。接下来将会介绍这些事件的作用和使用方法。
## 隐藏窗口
窗口的显示和隐藏都在这个事件中,窗口默认只有窗口1是显示,其他窗口默认都是隐藏的,所以如果你需要操作其他窗口,需要把窗口显示出来再进行操作。
窗口板块中隐藏状态的窗口会显示灰色,可以通过这个判断你的窗口有没有忘记显示出来。
![默认状态下只有窗口1是显示的,其他窗口都是隐藏的,所以呈现灰色](../images/Window_Dance_Window_Hidden.png)
## 窗口动效
(谁会,来补充一下,我只用过移动2333)
## 窗口大小重置
想要让窗口大小发生变化,或调整窗口的轴点,都需要借助**窗口大小重置**事件。这个事件的设置项目是这样的:
![](../images/Window_Dance_Window_Resize.gif)
**大小:** 窗口的目标大小,最大可以设置为`200% 200%`,如果`x``y`同时被设置为了0,则窗口会立刻被重置为初始的大小(即`100% 100%`)。
**缩放模式:** 窗口大小发生变化时内容的缩放模式,具体如下:
<ul>
<li><strong>填充:</strong>将画面中的内容尽可能的填满窗口</li>
<li><strong>适应:</strong>将画面中的内容尽可能放进窗口</li>
<li><strong>无:</strong>保持窗口中原来内容的大小不变</li>
</ul>
![填充模式](../images/Window_Dance_fill.gif)
![适应模式](../images/Window_Dance_fit.gif)
![无模式](../images/Window_Dance_none.gif)
> 如果你的窗口在大小发生变化前后长宽比不变,那么**填充**和**适应**在效果上没有区别。
**轴点模式:** 有**默认**和**锚点边缘**两种模式,选择**默认**即和房间移动的轴点没有区别,选择**锚点边缘**则表示选择一条边缘固定不动的情况下进行大小的缩放。
> 实际上选择锚点边缘的情况下就是由系统计算轴点的位置,因此在锚点边缘选择左或右时不要把`x`设置为`0%`,在锚点边缘选择上或下时不要把`y`设置为`0%`,否则会出现bug,表现为对应窗口会消失且**无法被任何方式**移动回来,即使通过事件恢复了窗口的大小和轴点。
**轴点:** 设置位置和缩放的基准点,类似于精灵图和房间的轴点,此处不再赘述。
**动画时长和缓速:** 见过多次了,不再赘述。
> 如果你想直观地看看各种移动方式的速度区别,可以[看看这里](https://easings.net/zh-cn)。
### 轴点的使用技巧
我们知道,在窗口大小发生变化时,调整轴点可以改变其缩放的中心。但是实际上,即使窗口不需要缩放,我们也可以通过调整轴点来改变窗口的位置,那么这种操作从效果上看和直接使用窗口移动看似没有什么区别,实际上在一些特殊的需求中,这个方法可以被很巧妙地使用。
窗口在移动时,使用的坐标是相对整个屏幕的,而由于不同设备的屏幕分辨率不同,导致有些效果如果用窗口移动来做会在不同分辨率下有不同效果,尤其是当多个窗口之间的位置有配合的时候(如两个窗口紧贴的效果)。
如在16:9的分辨率下制作的两个窗口紧挨着的效果:
![16:9分辨率下两个窗口紧贴](../images/Window_Dance_169ratio.png)
在其他分辨率下,即使不改变窗口的位置,也可能会有不同的效果(如在22:9分辨率下):
![在更宽的屏幕下,两个窗口无法紧贴](../images/Window_Dance_229ratio.png)
如果想要做出在类似`2-XN`中两个窗口相撞的效果,窗口中间有距离会导致表演效果大打折扣。这时我们可能会想,能不能不以屏幕为基准定位,而是以窗口的大小为基准定位,是不是就可以做到了呢?事实上,**轴点**就解决了这样的问题。
试想,如果两个窗口在同一个位置,而一个窗口的轴点在左边缘,另一个窗口在右边缘,就可以保证无论在什么样的分辨率下,这两个窗口都一定是紧挨着的。
![](../images/Window_Dance_169ratio_pivot.png)
![使用轴点后,无论在哪个分辨率下两个窗口都是紧挨的](../images/Window_Dance_229ratio_pivot.png)
所以当你的动画需要多个窗口之间的位置配合时,不妨试试用轴点的移动来代替直接移动窗口。
## 设置窗口数量
首先需要纠正一个翻译问题,这个事件的正确翻译应为**设置窗口内容**(英文原文: Set Window Content)。真正可以设置窗口数量的事件是前面提到的**隐藏窗口**事件(显示或者隐藏窗口),请大家不要搞错了。
这个事件的设置项目是这样的:
![](../images/Window_Content.png)
**内容模式:** 可以选择**一个房间**或**全部房间**,在选择**一个房间**时,下面会出现**房间目录**选项,可以从4个房间里面选择一个,随后这个窗口中只会显示这个房间的内容。在选择全部房间时,这个窗口将会像平常一样显示全部4个房间的内容。
> 注意,在选择**一个房间**时,这个房间中的所有房间事件都不会在这个窗口中生效,包括房间移动,淡入淡出房间,房间遮罩等。
![左侧窗口是全部房间,右侧房间是一个房间(房间1),可以发现房间移动和房间遮罩在右侧房间都没有生效](../images/Window_Dance_All_or_One.png)
**位置,缩放和角度:** 类似于摄像头移动的对应参数。在内容模式为**一个房间**时,位置是对应房间区域的对应坐标(左下角是`(0%, 0%)`,右上角是`(100%, 100%)`),在选择**全部房间**时,位置是在一个**长宽均为一个房间默认长宽的2倍的大区域**中的位置(如果需要定位到一个处于默认位置和默认大小的房间的左下角,位置是`(25%, 25%)`,右上角则是`(75%75%)`,正中心依然是`(50%, 50%)`),但是由于窗口默认大小和一个窗口的默认大小是相同的,因此如果不改变窗口的大小,依然只能显示一个房间大小的区域。
![上图中黄色区域是一个处于默认位置和默认大小的房间,蓝色区域是全部房间的坐标区域](../images/Window_Dance_Coordinate_of_All_Room.png)
无论选择哪种内容模式,超出区域范围的内容都会被裁剪。
**时长和缓速:**
## 重新排列窗口
类似于房间板块的**重新排列房间**,可以设置窗口的上下关系。
## 设置主窗口
将对应的窗口设置为主窗口,对话,顶部护士灯光,状态牌等内容将在主窗口显示。
## 设置窗口名称
修改窗口的标题。在动作选择**设置**的时候,会直接设置窗口的标题;在动作选择**增补**的时候,会在原来标题的后面增加内容;在动作选择**重置**的时候,会将标题重置为`Rhythm Doctor`
## 设置桌面颜色
修改模拟移动时桌面的颜色,如果不打开起始颜色,则表示从当前颜色渐变为结束颜色,如果打开起始颜色,效果将类似于**自定义闪烁**。
+51
View File
@@ -44,3 +44,54 @@
举个例子,假如你的设备输入延迟比较大,又或者你用的是蓝牙耳机,更甚至是Steam远程畅玩或是和好友远程玩双人关卡,此时你会发现,你按下空格键,会等大概一秒钟才会听到空拍音效,节奏点也会因为网络延迟延后判断,通常这时候我们会通过调整输入偏移来解决,但即使是调整了输入偏移,你在按空拍的时候还是会因为网络延迟等原因延后一秒钟才会播放空拍音效。
这也就是为什么说空拍音效的响起会对后续节奏判断产生影响了,偏移量小的玩家还没什么,无非就是多响一声而已,但偏移量大的玩家呢?所以制作过程中尽量不要让玩家在没有节拍的位置误认为有节拍并按了一个空拍,毕竟如果延迟比较大的话,这种误导性影响还是挺大的。
### *7、 使用屏幕朗读事件
官方在v0.19.0无障碍更新中加入了屏幕朗读事件,以为视障玩家群体提供更多支持。
> 为你的关卡添加屏幕朗读事件是可选的,但是请确保你正确使用了事件。同时,你**不应该**:
>
> - 添加会干扰正常游玩的屏幕朗读事件(如场景描述与画面不符、对轨道的错误提示等);
> - 将屏幕朗读事件作为谱面玩法的一部分(除非在关卡描述中特别说明)。
在继续之前,请确保在`设置>易用性设置>朗读设置`中启用了`朗读`
阅读[关卡屏幕阅读器的适配测试指南](https://docs.qq.com/doc/DUVJVc1pjam1uT1R6)以了解如何配置屏幕朗读。
另外,推荐在启用朗读的情况下先游玩官谱以作参考。
#### 朗读轨道信息
![](../images/narraterowinfo.png)
**轨道**:选择要朗读哪条轨道的信息。
**类型**:“**患者上线**”表示新的轨道被引入;“**患者更新**”表示某条轨道的行为模式改变;“**患者离线**”表示某条轨道在当前谱面不再被使用。
“**医生上线**”“**医生离线**”与“**患者上线**”“**患者离线**”类似,只不过由电脑操控。
**仅声音提示**:启用该选项时,游戏将不会朗读该提示的类型。
**朗读X字拍子**:选择**开启**时,游戏将会朗读该轨道当前的X字拍子。选择**自定义**时,将会朗读玩家自定义的X字拍子,而不是轨道当前的X字拍子。例如,对于`----xx ---♥`,游戏会朗读“X拍56”;而当轨道没有X字拍子时,游戏会朗读“无X拍”。
**紊乱**:用于提示X字拍子连续变化的节拍(例如`X-WOT`)。
**玩家**:选择在双人模式下,该轨道由哪位玩家接管。
一般情况下,游戏会按以下的顺序来朗读:
`[玩家][类型][轨道角色][X字拍子]`
#### 朗读口述
**口述内容**:游戏朗读的内容。
**朗读分类**:该朗读事件的类别。下面是官方对朗读分类的说明:
- 提示:适用于常规屏幕文字提示,“状态标识”信息默认归入此类。
- 描述:“朗读口述”事件的默认分类,专用于呈现纯视觉信息(如角色动画、背景环境等)。玩家可按`F6`键切换此类播报。
- 字幕:"浮动文字"事件的默认分类,适用于语音内容字幕(如歌词字幕),支持多语言翻译。玩家可按`F7`键切换此类播报。
- 说明:专用于游戏控制说明。播报后,玩家可随时按`F1`键重复听取当前指引(直至下一条指引信息覆盖)。
+74
View File
@@ -262,6 +262,24 @@
| sndTutorialDubstep | <code>MD-1</code>的教程音乐 | 114 |
| sndTutorialDubstep_Bassless | <code>MD-1</code>的教程音乐,无贝斯 | 114 |
| sndTutorialDubstep_Dotted | <code>MD-1</code>的教程音乐,有附点 | 114 |
| sndTutorialHouse_Base | <code>5-2</code>和<code>5-2N</code>的教程音乐 | 120 |
| sndTutorialHouse_AmenFill | <code>5-2</code>和<code>5-2N</code>的教程音乐开始练习前摇(镲声) | 120 |
| sndTutorialHouse_FreezeCPU | <code>5-2</code>的教程音乐(伊恩演示) | 120 |
| sndTutorialHouse_Freeze1 | <code>5-2</code>教程音乐的第一阶段 | 120 |
| sndTutorialHouse_Freeze2 | <code>5-2</code>教程音乐的第二阶段 | 120 |
| sndTutorialHouse_BurnCPU | <code>5-2N</code>的教程音乐(伊恩演示) | 120 |
| sndTutorialHouse_Burn1 | <code>5-2N</code>教程音乐的第一阶段 | 120 |
| sndTutorialHouse_Burn2 | <code>5-2N</code>教程音乐的第二阶段 | 120 |
| sndTutorialHouse_Rest | <code>5-2</code>和<code>5-2N</code>的教程音乐(休息) | 120 |
| sndTutorialHouse_Riser | <code>5-2</code>和<code>5-2N</code>的教程音乐开始练习前摇(鼓声) | 120 |
| sndTutorialSyncopation | <code>6-1</code>的教程音乐开头 | 110 |
| sndTutorialSyncopation | <code>6-1</code>的教程音乐开头,无开头空白 | 110 |
| sndTutorialSyncopation_Phase1 | <code>6-1</code>教程音乐第一阶段 | 110 |
| sndTutorialSyncopation_Phase2 | <code>6-1</code>教程音乐第二阶段 | 110 |
| sndTutorialHoldshot | <code>7-1</code>的教程音乐 | 95 |
| sndTutorialHoldshot_Phase1 | <code>7-1</code>的教程音乐第一阶段 | 95 |
| sndTutorialHoldshot_Phase2 | <code>7-1</code>的教程音乐第二阶段 | 95 |
| sndTutorialHoldshot_Phase3 | <code>7-1</code>的教程音乐第三阶段 | 95 |
| sndOrientalTechno | <code>1-1</code>东方电舞曲 | 100 |
| sndOrientalTechnodown | <code>1-1N</code>东方回响贝斯的开头部分 | |
| sndOrientalDubstep | <code>1-1N</code>东方回响贝斯 | 130 |
@@ -271,14 +289,70 @@
| sndOrientalInsomniac2 | <code>1-X</code> 东方不眠夜 第二部分 | |
| sndOrientalInsomniac3 | <code>1-X</code> 东方不眠夜 第三部分 | |
| sndOrientalInsomniacHardRep | <code>1-XN</code>超东方不眠夜 | 160~180 |
| sndGongXi | <code>1-CNY</code>春节贺岁片 | 145 |
| sndHalloween | <code>1-BOO</code>恐怖鸟主题 | 100 |
| sndLofi | <code>2-1</code>Lo-fi Hip-Hop Beats To Treat Patients To | 75 |
| sndCareless | <code>2-1N</code>wish i could care less | 75~81 |
| sndCarelessCN | <code>2-1N</code>wish i could care less中文版 | 75~81 |
| sndSupraventricular88 | <code>2-2</code>室上性心动过速 | 88 |
| sndUnreachable | <code>2-2N</code>Unreachable | 180 |
| sndPuffPiece | <code>2-3</code>缭绕 | 127 |
| Pomeranian | <code>2-3N</code>嗅炸弹的博美犬 | 127.2 |
| song_of_the_sea | <code>2-4</code>与<code>2-4N</code>的背景音乐 | 60 |
| sndAllTheTimes | <code>2-X</code>All The Times 咖啡之歌 | 145 |
| sndAllTheTimesCN | <code>2-X</code>All The Times 咖啡之歌中文版 | 145 |
| sndBitterness | <code>2-XN</code>Bitter Times 爱情是苦和甜的交错前半段 | 112~195 |
| sndBitternessCutscene | <code>2-XN</code>Bitter Times 爱情是苦和甜的交错后半段 | 112->195->264->195 |
| sndTutorialBeans | <code>2-B1</code>武士豆子跳 | 110 |
| sndSleepyGarden | <code>3-1</code>沉睡花园 | 158 |
| sndLounge | <code>3-1N</code>休息室 | 75 |
| sndBarbra | <code>3-2</code>典雅 | 115 |
| sndDistantDuet | <code>3-3</code>分离二重唱 | 194 |
| sndDistantDuetNight | <code>3-3</code>分离二重唱·夜 | 194 |
| sndDistantDuet | <code>3-3</code>分离二重唱 | 194 |
| sndDistantDuetNight | <code>3-3</code>分离二重唱·夜 | 194 |
| sndLesMisBar1 | <code>3-X</code>轮班之歌 | 100 |
| sndLesMisBar39 | <code>3-X</code>轮班之歌 从第39小节开始 | |
| sndMinersong | <code>4-1</code>实习医生培训演练表现评估 | 128->225.9->140~110? |
| sndRollerdisco | <code>4-1N</code>滑板迪斯科震颤 | 125.5 |
| sndInvisible | <code>4-2</code>和<code>4-2N</code> | 190 |
| sndSteinway | <code>4-3</code>斯坦威 | 80 |
| sndKnowYou | <code>4-4</code>懂你 | 157 |
| sndMurmurs | <code>4-4N</code>喃喃细语 | 65 |
| sndLuckyBreak | <code>5-1</code>路吉摔了一跤 | 156 |
| sndOSTL | <code>5-2</code>One Slip Too Late 创伤之歌 | 175~150 |
| sndOSTLCN | <code>5-2</code>One Slip Too Late 创伤之歌中文版 | 175~150 |
| sndFreezeshot | <code>5-2</code>Lo-fi Beats For Patients To Chill To | 140 |
| sndFreezeshotH | <code>5-2N</code>无以为继的伤心欲绝 | 176->100->80 |
| sndTherapy1 | <code>5-3</code>七局伸展操第一部分 | 128 |
| sndTherapy2 | <code>5-3</code>七局伸展操第二部分 | 124 |
| sndTherapy3 | <code>5-3</code>七局伸展操第三部分 | 136 |
| sndTherapyEnding | <code>5-3</code>七局伸展操结尾 | 136 |
| sndCorazonesViejos | <code>5-3N</code>偕老 | 249? |
| sndDDS | <code>5-X</code>梦想永不歇 | 95->62.6->102.5 |
| sndDDSCN | <code>5-X</code>梦想永不歇中文版 | 95->62.6->102.5 |
| sndHaileyDuet | <code>6-1</code>想把心事和你说 | 94.5->190->220->181->206? |
| sndHaileyDuetCN | <code>6-1</code>想把心事和你说中文版 | 94.5->190->220->181->206? |
| sndEdegaRave | <code>6-2</code>欢迎回来 | 200->85->200 |
| sndBossStage_Main | <code>6-X</code>Boss战(包括埃德加批评佩奇的一段) | 150~255 |
| sndBossStage_NoCutscene | <code>6-X</code>Boss战(不包括埃德加批评佩奇的一段) | 150~255 |
| sndBossStage_EndingShort | <code>6-X</code>Boss战结尾(包括埃德加批评佩奇的一段) | 165 |
| sndBossStage_EndingLong | <code>6-X</code>Boss战结尾(不包括埃德加批评佩奇的一段) | 165 |
| sndBlurred | <code>7-1</code>模糊 | 70 |
| sndMontage | <code>7-X</code>奇迹除颤器 | 160 |
| sndMontageIntro | <code>7-X</code>奇迹除颤器前奏 | |
| sndColeSongLeaves | <code>7-X2</code>奇迹除颤器安可版(佩奇离职分支) | 91->121.2->182-->156->240?->228?-->360 |
| sndColeSongStays | <code>7-X2</code>奇迹除颤器安可版(佩奇在职分支) | 91->121.2->182-->156->240?->228?-->360 |
| sndArtExercise | <code>X-1</code>美术练习 | 140 |
| sndHelpingHands | <code>X-0</code>伸出援手 | 178 |
| sndHelpingHandsCN | <code>X-0</code>伸出援手中文版 | 178 |
| sndBlackestLuxuryCar | <code>MD-1</code>BlackestLuxuryCar | 178 |
| sndTapeStopNight | <code>MD-2</code>Tape/Stop/Night | 115 |
| sndThe90sDecision | <code>MD-3</code>The90sDecision | 128 |
| sndMeetAndTweet | <code>X-MAT</code>Meet And Tweet | 110 |
| sndWornOutTapes | <code>X-WOT</code>Worn Out Tapes | 149 |
| sndSparkLine | <code>X-KOB</code>气球王国 | 124 |
| sndVividStasis | <code>X-FTS</code>恋恋群星 | 150 |
| sndOsmBluesRadio | 夜间的病房内过剧情 | 98? |
| SoftPianoIntimate | 第一章末尾的过剧情 | 88 |
+46 -37
View File
@@ -4,79 +4,75 @@
| 功能 | 快捷键 | 章节 | 内容 |
| :--- | :--- | :--- | :--- |
| 播放音乐 | `P` | [导入与导出](../pages/importandexport.md#导入音乐)  | 设置谱面的音乐 |
| 播放音乐 | `P` | [导入与导出](../pages/importandexport.md#导入音乐) | 设置谱面的音乐 |
| 设置音节长度 | `C` | | 设置每个小节的拍子数量 |
| 播放音效 | `S` | [音效设计](../pages/audiodesign.md#播放音效) | 播放游戏内置的音效或是导入的音效 |
| 设置BPM | `B` | [导入与导出](../pages/importandexport.md#调整曲速和偏移) | 设置音乐的BPM |
| 设置按拍音效 | `L` | [音效设计](../pages/audiodesign.md#设置按拍音效) | 设置玩家正确击中拍子时的音效 |
| 设置心跳音量 | `H` | [音效设计](../pages/audiodesign.md#心爆) | 设置正确击中拍子时心跳的音效音量    |
| 设置心跳音量 | `H` | [音效设计](../pages/audiodesign.md#心爆) | 设置正确击中拍子时心跳的音效音量 |
| 设置心爆间隔 | `I` | [音效设计](../pages/audiodesign.md#心爆) | 设置心爆效果的延迟方式与间隔 |
| 护士语音设置 | `R` | [音效设计](../pages/oneshotbeat.md#护士节奏提示) | 添加用于提示单发拍子的护士语音 |
| 设置游戏音效 | `G` | [音效设计](../pages/audiodesign.md#设置游戏音效) | 设置玩家按键时的各种音效声 |
| 设置节拍音效 | `T` | [音效设计](../pages/audiodesign.md#设置节拍音效) | 重新设置替换指定轨道的节拍音效 |
| 设置数拍音效   | `U` | [普通拍子](../pages/classicbeat.md#护士节奏提示) | 设置普通拍子的数拍音效 |
| 设置数拍音效 | `U` | [普通拍子](../pages/classicbeat.md#护士节奏提示) | 设置普通拍子的数拍音效 |
| 朗读口述 | `N` | [无障碍设计](../pages/accessibledesign.md#朗读口述) | 添加用于文字说明的屏幕朗读事件 |
| 朗读轨道信息 | `F` | [无障碍设计](../pages/accessibledesign.md#朗读轨道信息) | 添加用于轨道提示的屏幕朗读事件 |
| 注释 | `M` | [标签](../pages/tag.md#让事件摆放更有条理) | 添加注释内容或插入注释型自定义方法 |
## 蓝色版块(轨道)
| 功能 | 快捷键 | 章节 | 内容 |
| :--- | :--- | :--- | :--- |
| 设置波    | | [单发拍子](../pages/oneshotbeat.md#单发拍子视觉效果) | 设置单发拍子脉冲的形状和大小   |
| 设置单发波形 | | [单发拍子](../pages/oneshotbeat.md#单发拍子视觉效果) | 设置单发拍子脉冲的形状和大小 |
## 紫色版块(动作)
| 功能 | 快捷键 | 章节 | 内容 |
| :--- | :--- | :--- | :--- |
| **玩法类** | | | |
| 隐藏轨道 | `X` | [轨道移动](../pages/moverow.md#轨道的显示与隐藏) | 改变轨道的显示和隐藏状态 |
| 切换玩家轨道 | `Y` | [采音和节奏设计](../pages/beatpatterndesign.md) | 切换轨道的游玩者:1P,2P或是CPU |
| 结束关卡 | `L` | [导入与导出](../pages/importandexport.md#导出关卡) | 制作关卡必需的特效,放置三个来结束关卡 |
| 设置播放模式   | `9` | | 设置播放头的运动方式 |
| 显示手 | `U` | [](../pages/hand.md#显示手) | 显示或者隐藏手 |
| 手分配 | `Shift+Y` | [](../pages/hand.md#手分配) | 为手设置所属角色 |
| 设置播放方式 | `Shift+Z` | | 设置播放头的运动方式 |
| **环境类** | | | |
| 设置主题 | `T` | [场景与主题](../pages/settheme.md) | 给房间添加游戏内置的主题效果 |
| 设置背景 | `B` | [房间](../pages/room.md#背景图片) | 给房间添加纯色背景或是导入自制背景图片 |
| 设置前景 | `G` | [房间](../pages/room.md#前景图片) | 给房间导入自制的前景图片 |
| **轨道类** | | | |
| 设置前景 | `Shift+B` | [房间](../pages/room.md#前景图片) | 给房间导入自制的前景图片 |
| 设置速度 | `S` | [轨道视效](../pages/vfx.md#设置速度) | 改变整个画面中物件及特效的运行速度 |
| 自定义闪烁 | `F` | [轨道视效](../pages/rowfx.md#适合配合轨道或节拍一起使用的特效) | 自定义屏幕闪烁的图层位置,颜色,透明度 |
| 闪烁 | `Shift+F` | [轨道视效](../pages/rowfx.md#适合配合轨道或节拍一起使用的特效) | 简单地屏幕闪烁 |
| **轨道特效类** | | | |
| 隐藏轨道 | `X` | [轨道移动](../pages/moverow.md#轨道的显示与隐藏) | 改变轨道的显示和隐藏状态 |
| 移动轨道 | `O` | [轨道移动](../pages/moverow.md#轨道的移动) | 让轨道在画面中移动,缩放,旋转等 |
| 重排序:行 | `Shift+O` | | 将轨道移动到不同房间,或是重新对轨道进行排序 |
| 播放表情 | `J` | [自制角色与精灵资源](../pages/spritesheet.md#播放表情) | 改变轨道中角色的表情 |
| 轨道涂色 | `R` | [轨道视效](../pages/rowfx.md#轨道涂色) | 设置轨道的边框、涂色、透明度 |
| 切换轨道 | `Y` | [采音和节奏设计](../pages/beatpatterndesign.md) | 切换轨道的游玩者:1P,2P或是CPU |
| **镜头类** | | | |
| **摄像头特效类** | | | |
| 移动摄像头 | `C` | [镜头移动](../pages/camera.md) | 设置摄像头动画 |
| 屏幕震动 | `H` | [轨道视效](../pages/rowfx.md#适合配合轨道或节拍一起使用的特效) | 添加屏幕震动效果,可指定震动幅度 |
| 翻转屏幕 | `N` | [视觉干扰](../pages/vfx.md) | 上下,左右,或是中心反转屏幕 |
| 脉冲摄像机 | `P` | [轨道视效](../pages/rowfx.md#和轨道相关的特效) | 添加一个按一定时间和频次缩放画面的效果 |
| **视效类** | | | |
| 脉冲摄像机 | `Shift+C` | [轨道视效](../pages/rowfx.md#和轨道相关的特效) | 添加一个按一定时间和频次缩放画面的效果 |
| 自定义震动 | `H` | [轨道视效](../pages/rowfx.md#适合配合轨道或节拍一起使用的特效) | 自定义屏幕震动的震动类型,时长,增幅 |
| 屏幕震动 | `Shift+H` | [轨道视效](../pages/rowfx.md#适合配合轨道或节拍一起使用的特效) | 简单地屏幕震动,可指定震动幅度 |
| 屏幕翻转 | `Shift+I` | [视觉干扰](../pages/vfx.md) | 上下,左右,或是中心反转屏幕 |
| **视觉特效类** | | | |
| 预设特效 | `V` | [ex2](../pages/appendix_vfxs.md) | 插入编辑器预置的特效 |
| 设置速度 | `S` | [轨道视效](../pages/vfx.md#设置速度) | 改变整个画面中物件及特效的运行速度 |
| 闪烁 | `F` | [轨道视效](../pages/rowfx.md#适合配合轨道或节拍一起使用的特效) | 简单地屏幕闪烁 |
| 自定义闪烁 | `U` | [轨道视效](../pages/rowfx.md#适合配合轨道或节拍一起使用的特效) | 自定义屏幕闪烁的图层位置,颜色,透明度 |
| 自定义闪烁 | `F` | [轨道视效](../pages/rowfx.md#适合配合轨道或节拍一起使用的特效) | 自定义屏幕闪烁的图层位置,颜色,透明度 |
| 闪烁 | `Shift+F` | [轨道视效](../pages/rowfx.md#适合配合轨道或节拍一起使用的特效) | 简单地屏幕闪烁 |
| 重低音震动 | `K` | [轨道视效](../pages/rowfx.md#适合配合轨道或节拍一起使用的特效) | 添加一次大幅度的色像差加大幅度屏幕缩放 |
| 反转颜色 | `I` | [镜厅](../pages/hallofmirror.md) | 给画面添加反色效果 |
| 卡带效果 | `0` | [视觉干扰](../pages/vfx.md#卡带效果) | 反复重现某个画面造成卡顿错觉 |
| 颜色反转 | `I` | [镜厅](../pages/hallofmirror.md) | 给画面添加反色效果 |
| 卡带效果 | `E` | [视觉干扰](../pages/vfx.md#卡带效果) | 反复重现某个画面造成卡顿错觉 |
| 手涂色 | `Shift+U` | [](../pages/hand.md#手涂色) | 改变手的颜色 |
| 窗口动效 | `W` | [窗口移动](../pages/windowmove.md) | 把关卡变成窗口模式,并设置窗口的移动 |
| **文本类** | | | |
| 弹幕效果 | `E` | [其他文字事件](../pages/captions.md#弹幕效果) | 添加一个从右至左的弹幕飘过效果 |
| 显示对话 | `D` | [其他文字事件](../pages/captions.md#显示对话) | 添加一个悬浮在屏幕上方或下方的对话窗口 |
| 显示状态 | `Q` | [其他文字事件](../pages/captions.md#显示状态牌) | 在画面左上角显示一个状态 |
| 显示状态标识 | `Shift+D` | [其他文字事件](../pages/captions.md#显示状态牌) | 在画面左上角显示一个状态标识 |
| 浮动文字 | `A` | [浮动文字](../pages/floatingtext.md) | 在画面中显示一段文字 |
| **手 类** | | | |
| 显示手 | `5` | [](../pages/hand.md#显示手) | 显示或者隐藏手 |
| 手涂色 | `6` | [](../pages/hand.md#手涂色) | 改变手的颜色 |
| 手分配 | `7` | [](../pages/hand.md#手分配) | 为手设置所属角色 |
| 弹幕效果 | `Shift+A` | [其他文字事件](../pages/captions.md#弹幕效果) | 添加一个从右至左的弹幕飘过效果 |
| **组件类** | | | |
| 标签动作 | `8` | [标签](../pages/tag.md#设置标签事件) | 运行/禁用指定标签带有的事件 |
| 自定义方法 | `Z` | [自定义方法](../pages/custommethod.md) | 运行指令,执行无法用常规手段达成的效果 |
| 注释 | `M` | [标签](../pages/tag.md#让事件摆放更有条理) | 添加注释内容或插入注释型自定义方法 |
## 绿色版块(精灵)
| 功能 | 快捷键 | 章节 | 内容 |
| :--- | :--- | :--- | :--- |
| 移动精灵图    | `O` | [自制角色与精灵资源](../pages/decoration.md#移动精灵图) | 设置精灵的位置、大小、角度、轴点    |
| 绘制精灵图 | `T` | [使用精灵](../pages/decoration.md#绘制精灵图) | 设置精灵的边框、涂色、透明度 |
| 播放表情 | `P` | [使用精灵](../pages/decoration.md#播放表情) | 播放精灵的表情 |
| 显示/隐藏 | `V` | [使用精灵](../pages/decoration.md#显示/隐藏) | 显示或隐藏精灵 |
| 平铺精灵图 | `V` | [使用精灵](../pages/decoration.md#平铺精灵图) | 显示或隐藏精灵 |
| 标签动作 | `O` | [标签](../pages/tag.md#设置标签事件) | 运行/禁用指定标签带有的事件 |
| 调用自定义方法 | `Z` | [自定义方法](../pages/custommethod.md) | 运行指令,执行无法用常规手段达成的效果 |
| 注释 | `M` | [标签](../pages/tag.md#让事件摆放更有条理) | 添加注释内容或插入注释型自定义方法 |
## 黄色版块(房间)
@@ -90,4 +86,17 @@
| 房间遮罩 | `K` | [房间视效](../pages/roomfx.md#房间遮罩) | 为房间设置遮罩 |
| 淡入淡出房间 | `F` | [镜头移动](../pages/camera.md) | 设置房间的透明度 |
| 设置房间视角 | `P` | [房间视效](../pages/roomfx.md#设置房间视角) | 设置房间的四个角的位置 |
| 注释 | `M` | [标签](../pages/tag.md#让事件摆放更有条理) | 添加注释内容或插入注释型自定义方法 |
| 注释 | `T` | [标签](../pages/tag.md#让事件摆放更有条理) | 添加注释内容或插入注释型自定义方法 |
## 绿色版块(精灵)
| 功能 | 快捷键 | 章节 | 内容 |
| :--- | :--- | :--- | :--- |
| 移动精灵图 | `O` | [自制角色与精灵资源](../pages/decoration.md#移动精灵图) | 设置精灵的位置、大小、角度、轴点 |
| 绘制精灵图 | `R` | [使用精灵](../pages/decoration.md#绘制精灵图) | 设置精灵的边框、涂色、透明度 |
| 播放表情 | `J` | [使用精灵](../pages/decoration.md#播放表情) | 播放精灵的表情 |
| 显示/隐藏 | `X` | [使用精灵](../pages/decoration.md#显示/隐藏) | 显示或隐藏精灵 |
| 重排序:精灵图 | `Shift+O` | | 将精灵移动到不同房间,或是重新对精灵进行排序 |
| 平铺精灵图 | `I` | [使用精灵](../pages/decoration.md#平铺精灵图) | 显示或隐藏精灵 |
| 混合精灵图 | `B` | | 设置精灵的颜色混合模式 |
| 注释 | `M` | [标签](../pages/tag.md#让事件摆放更有条理) | 添加注释内容或插入注释型自定义方法 |
+6
View File
@@ -98,6 +98,12 @@
`5-2N 无以为继的伤心欲绝`中被首次引入。
### 长按单发拍子
当听到咻噗的声音时,说明下一次击拍需要长按到下一个出拍点。
`7-1 模糊`中被首次引入。
### 冲击拍子
单发拍子根据哨声提示在脉冲和按拍时全都按拍。
+70
View File
@@ -20,4 +20,74 @@ g 1 1 5 4 #0ff{
};
</textarea></div></div>
---
完整功能支持请前往[此处](https://view.obugs.cn)。
<div class="rdview2"><div class="canvas"></div><div class="editor"><div class="number"></div><textarea class="area" spellcheck="false" placeholder="Enter code here">
{ "bar": 1, "beat": 1, "y": 0, "type": "MoveRoom", "if": "1d0", "roomPosition": [50, 50], "scale": [70, 100], "angle": 20, "pivot": [0, 0], "duration": 1, "ease": "Linear" },
{ "bar": 1, "beat": 1, "y": 6, "type": "AddOneshotBeat", "pulseType": "Triangle", "tick": 2, "subdivisions": 2, "subdivSound": true },
{ "bar": 1, "beat": 2, "y": 0, "type": "AddClassicBeat", "tick": 0.5, "swing": 0, "hold": 0 },
{ "bar": 1, "beat": 2, "y": 1, "type": "ReorderRooms", "order": [1, 3, 2, 0] },
{ "bar": 1, "beat": 2, "y": 5, "type": "SetSpeed", "speed": 1, "duration": 0, "ease": "Linear" },
{ "bar": 1, "beat": 3, "y": 3, "type": "AddOneshotBeat", "pulseType": "Wave", "tick": 2 },
{ "bar": 1, "beat": 4, "y": 4, "type": "AddOneshotBeat", "pulseType": "Wave", "freezeBurnMode": "Burnshot", "interval": 2, "tick": 1 },
{ "bar": 1, "beat": 5, "y": 1, "type": "SetBeatsPerMinute", "if": "~3d0", "beatsPerMinute": 100 },
{ "bar": 1, "beat": 5, "y": 2, "type": "SetBackgroundColor", "rooms": [0], "backgroundType": "Color", "color": "FFFFFFFF", "filter": "NearestNeighbor" },
{ "bar": 1, "beat": 5, "y": 5, "type": "SetGameSound", "soundType": "SmallMistake", "filename": "" },
{ "bar": 1, "beat": 5, "y": 6, "type": "SetHeartExplodeInterval", "intervalType": "GatherAndCeil", "interval": 1 },
{ "bar": 1, "beat": 7, "y": 0, "type": "AddClassicBeat", "tag": "1", "tick": 0.5, "hold": 1, "swing": 0.5, "setXs": "NoChange" },
{ "bar": 1, "beat": 7, "y": 6, "type": "AddOneshotBeat", "pulseType": "Wave", "freezeBurnMode": "Freezeshot", "interval": 2, "tick": 1, "delay": 0.5, "skipshot": true },
{ "bar": 1, "beat": 8, "y": 1, "type": "SetVisible", "visible": true },
{ "bar": 1, "beat": 8, "y": 2, "type": "ShowStatusSign", "if": "1d0", "text": "RhythmBase.View!", "duration": 5, "useBeats": true, "narrate": true },
{ "bar": 1, "beat": 8, "y": 3, "type": "Tint", "border": "Glow", "borderColor": "FF0000FF", "tint": true, "tintColor": "001BFFFF", "opacity": 100, "duration": 3, "ease": "Linear" },
{ "bar": 1, "beat": 8, "y": 4, "type": "SetCountingSound", "voiceSource": "JyiCount", "enabled": true, "volume": 100, "subdivOffset": 0.5 },
{ "bar": 1, "beat": 8, "y": 5, "type": "TextExplosion", "rooms": [0], "text": "Explosion", "color": "000000", "mode": "OneColor", "direction": "Left", "speed": 100, "ease": "Linear" },
{ "bar": 2, "beat": 2, "y": 5, "type": "SayReadyGetSetGo", "tag": "1", "rooms": [4], "phraseToSay": "JustSayRea", "voiceSource": "Nurse", "tick": 1, "volume": 100 },
{ "bar": 2, "beat": 3, "y": 1, "type": "Move", "position": [50, 50], "duration": 1, "ease": "Linear" },
{ "bar": 2, "beat": 3, "y": 2, "type": "NewWindowDance", "tab": "Windows", "preset": "Move", "position": [50, 50], "reference": "Center", "easingDuration": 1, "ease": "Linear" },
{ "bar": 2, "beat": 3, "y": 3, "type": "PlayAnimation", "expression": "neutral" },
{ "bar": 2, "beat": 3, "y": 4, "type": "SetOneshotWave", "waveType": "BoomAndRush", "height": 100, "width": 100 },
{ "bar": 2, "beat": 5, "y": 0, "type": "BassDrop", "if": "1&~2d0", "rooms": [0], "strength": "High" },
{ "bar": 2, "beat": 5, "y": 1, "type": "ShowDialogue", "rooms": [4], "text": "Samurai_Happy: SAMURAI!", "speed": 1, "panelSide": "Bottom", "portraitSide": "Left", "playTextSounds": true },
{ "bar": 2, "beat": 5, "y": 2, "type": "FloatingText", "rooms": [0], "id": 0, "text": "等/呀/等/得/好/心/慌……", "times": "", "color": "00F4FFFF", "outlineColor": "0011FFFF", "textPosition": [50, 50], "font": "Default", "size": 8, "angle": 0, "showChildren": true, "fadeOutRate": 3, "mode": "FadeOut", "anchor": "MiddleCenter", "narrate": true, "narrationCategory": "Subtitles" },
{ "bar": 2, "beat": 6, "y": 3, "type": "SetRoomPerspective", "cornerPositions": [[0, 0], [100, 0], [0, 100], [100, 100]], "duration": 1, "ease": "Linear" },
{ "bar": 2, "beat": 6, "y": 4, "type": "SetPlayStyle", "PlayStyle": "Normal", "NextBar": 1, "Relative": true },
{ "bar": 2, "beat": 7, "y": 5, "type": "SetCrotchetsPerBar", "crotchetsPerBar": 7, "visualBeatMultiplier": 1 },
{ "bar": 2, "beat": 7, "y": 6, "type": "SetHandOwner", "rooms": [0], "hand": "Right", "character": "Player" },
{ "bar": 2, "beat": 8, "y": 3, "type": "SetBeatSound", "row": 0, "sound": {"filename": "Shaker"} },
{ "bar": 2, "beat": 8, "y": 4, "type": "TintRows", "if" : "1&~2d1", "rooms": [0], "border": "Outline", "borderColor": "2BFF00FF", "tint": true, "tintColor": "007E0EFF", "opacity": 100, "duration": 0, "ease": "Linear", "effect": "None" },
{ "bar": 3, "beat": 1, "y": 0, "type": "MoveCamera", "rooms": [0], "cameraPosition": [50, 50], "duration": 1, "ease": "Linear" },
{ "bar": 3, "beat": 1, "y": 1, "type": "ShowHands", "rooms": [0], "hand": "Right", "action": "Show", "extent": "Full", "forceRaise": true, "align": false, "instant": false },
{ "bar": 3, "beat": 1, "y": 2, "type": "PulseCamera", "rooms": [0], "strength": 1, "count": 1, "frequency": 1 },
{ "bar": 3, "beat": 3, "y": 2, "type": "SayReadyGetSetGo", "if": "1d0", "rooms": [4], "phraseToSay": "SayGetSetOne", "voiceSource": "Nurse", "tick": 1, "volume": 100 },
{ "bar": 3, "beat": 3, "y": 6, "type": "FlipScreen", "rooms": [0], "flipX": false, "flipY": true },
{ "bar": 3, "beat": 4, "y": 6, "type": "InvertColors", "rooms": [0], "enable": true },
{ "bar": 3, "beat": 5, "y": 3, "type": "DesktopColor", "endColor": "00ffff", "duration": 2, "ease": "Linear" },
{ "bar": 3, "beat": 6, "y": 6, "type": "SayReadyGetSetGo", "rooms": [4], "phraseToSay": "JustSayAndStop", "voiceSource": "Nurse", "tick": 1, "volume": 100 },
{ "bar": 3, "beat": 5, "y": -1, "type": "AdvanceText", "id": 0, "text": "text 字段不存在于原事件中,但是 RDView 提供了支持。" },
{ "bar": 3, "beat": 5.5, "y": -1, "type": "PulseFreeTimeBeat", "row": 0, "action": "Increment", "hold": 0 },
{ "bar": 3, "beat": 8, "y": 3, "type": "HideWindow", "show": false },
{ "bar": 3, "beat": 8, "y": 4, "type": "NarrateRowInfo", "row": 0, "infoType": "Connect", "soundOnly": false, "narrateSkipBeats": "On", "skipsUnstable": false, "customPlayer": "AutoDetect" },
{ "bar": 3, "beat": 8, "y": 5, "type": "Comment", "tab": "Actions", "text": "五彩斑斓的黑", "color": "8C00FF", "show": false },
{ "bar": 4, "beat": 1, "y": 2, "type": "PaintHands", "rooms": [0], "hands": "Right", "border": "Outline", "borderColor": "AFFF00FF", "tint": true, "tintColor": "4FAF00FF", "opacity": 100, "duration": 0 },
{ "bar": 4, "beat": 1, "y": 4, "type": "CallCustomMethod", "methodName": "", "executionTime": "OnBar", "sortOffset": 0 },
{ "bar": 4, "beat": 1, "y": 6, "type": "SetWindowContent", "contentMode": "OnTop" },
{ "bar": 4, "beat": 2, "y": 2, "type": "FadeRoom", "opacity": 100, "duration": 2, "ease": "Linear" },
{ "bar": 4, "beat": 2, "y": 4, "type": "PlaySong", "song": {"filename": "sndOrientalTechno"}, "bpm": 100, "loop": false },
{ "bar": 4, "beat": 2, "y": 6, "type": "SetRowXs", "pattern": "-x--x-", "syncoBeat": 3, "syncoSwing": 0, "syncoVolume": 70, "syncoPitch": 100, "syncoStyle": "Chirp", "syncoPlayModifierSound": true, "syncoPlayModifierOffSound": true },
{ "bar": 4, "beat": 3, "y": 3, "type": "ChangeCharacter", "row": 0, "character": "Samurai", "transition": "Instant" },
{ "bar": 4, "beat": 5, "y": 2, "type": "ShowRooms", "rooms": [1, 3], "heights": [0, 0, 0, 0], "transitionTime": 1, "ease": "InOutSine" },
{ "bar": 4, "beat": 6, "y": 6, "type": "RenameWindow", "action": "Set", "text": "Minecraft 1.21.1 NeoForge" },
{ "bar": 4, "beat": 7, "y": 2, "type": "SetVFXPreset", "rooms": [0], "preset": "Vignette", "enable": true },
{ "bar": 4, "beat": 7, "y": 3, "type": "PlaySound", "sound": {"filename": "Shaker"}, "customSoundType": "CueSound" },
{ "bar": 4, "beat": 7, "y": 4, "type": "SetTheme", "rooms": [0], "preset": "None", "skipPaintEffects": false },
{ "bar": 4, "beat": 7, "y": 5, "type": "SetRoomContentMode", "mode": "Center" },
{ "bar": 4, "beat": 8, "y": 6, "type": "TagAction", "Action": "Run", "Tag": "Nothing" },
{ "bar": 5, "beat": 1, "y": 2, "type": "PulseCamera", "rooms": [0], "strength": 1, "count": 1, "frequency": 1 },
{ "bar": 5, "beat": 1, "y": 3, "type": "SetClapSounds", "rowType": "Classic", "p1Sound": {"filename": "ClapHit"} },
{ "bar": 5, "beat": 1, "y": 4, "type": "ChangePlayersRows", "playerMode": "OneOrTwoPlayers", "players": ["NoChange", "NoChange", "NoChange", "NoChange", "NoChange", "NoChange", "NoChange", "NoChange", "NoChange", "NoChange", "NoChange", "NoChange", "NoChange", "NoChange", "NoChange", "NoChange"], "cpuMarkers": ["Otto", "Otto", "Otto", "Otto", "Otto", "Otto", "Otto", "Otto", "Otto", "Otto", "Otto", "Otto", "Otto", "Otto", "Otto", "Otto"] },
{ "bar": 5, "beat": 1, "y": 5, "type": "ReadNarration", "text": "一名身穿红色盔甲的武士跟着音乐节拍点头。", "category": "Description" }
</textarea></div></div>
---
+1
View File
@@ -54,6 +54,7 @@
| 雪花 | 屏幕上方开始落下快速的雪花,短时间内充满屏幕,可以和前景背景叠加起来显示 |
| 暴风雪 | 屏幕上方开始落下暴风雪,可以和前景背景叠加起来显示 |
| 钻石 | 屏幕上出现很多方块 |
| 气球 | 屏幕下方飘出很多气球 |
| 教程音符 | 屏幕铺满剧情模式教程中的音符背景,可以自定义颜色等 |
| | |
| **轨道类** | |
-39
View File
@@ -1,44 +1,5 @@
# 场景资源
## 背景和前景图片
在房间的前后关系里我们提到了背景图片和前景图片这两个概念,也就是说,除了使用编辑器内自带的一些主题之外,其实自己也是可以自定义画面的背景和前景图案的。这个功能同样十分灵活,但是如果想要完全靠自己来原创或是临摹背景图片的话,可能需要对画像素画有一些掌握。
选择紫色的版块,放置一个**设置背景**的事件,发现里面有两种形式,一种是纯色,这个比较好理解,唯独要注意的是**纯色的默认值是黑色而不是透明**,另一种是插入图片。
> 插入的图片必须是.png格式,如果你是自己画背景图,建议使用画布大小为352\*198像素。
颜色选项,看似意义不明,但其实也有一定的用处。如果你导入的图片只有纯白和透明两种颜色,这个功能就可以为纯白的部分染色,染成你自己设置的颜色。但是因为一次只能设置一种颜色,使用起来也有些限制。
缩放功能其实类似于操作系统里壁纸的填充方式,具体效果点开小箭头查看。
<details><summary><strong>填充方式</strong></summary>
<img src="../images/assets-fillmode.png" alt="填充方式图例" />
<ul>
<li><strong>填满:</strong>将画面拉伸到横纵全部填满屏幕。要注意的是,如果你塞进去一张高清图,编辑器也会把它缩小到352\*198像素来适应画面,而且这个缩放机制是像素化的,画面会变得非常模糊。</li>
<li><strong>拉伸:</strong>将画面等比拉伸直到左右垂直线对齐屏幕。</li>
<li><strong>等比拉伸:</strong>将画面等比拉伸直到上下水平线对齐屏幕。</li>
<li><strong>居中:</strong>就是按原画面大小放在正中间。</li>
<li><strong>平铺:</strong>像铺瓷砖一样铺满屏幕。</li>
</ul>
</details>
> 如果你想做一个动图效果,需要把.gif拆解成一连串的.png图片,在选择图片时同时选择所有的图点击确定。接下来就会多出一个设置帧数的选项,来确定动图的播放速度。帧数 = \(背景图总画面数 / 一个循环占节拍数量\) \* 曲速/60。
设置背景一样,但使用这个功能的主要目的还是为了能产生一个图片覆盖轨道和手的效果,这样在画面效果的处理上可以更加灵活。
## 平铺背景
唯独平铺选项会多冒出来一个速度设置,它可以让背景图片始终保持设置的速度移动。
* 在滚屏模式下,效果类似于<code>4-2</code>的天空在慢慢移动,速度和缓速则是调整背景从静止到目标速度的变化过程。
* 在脉冲模式下,背景的移动速度变化就是周期性的,用<code>间隔</code>来调整周期。另外,如果你想设计这样的移动背景,在作画的时候也需要考虑画面左右两端和上下两端的连续,否则画面运动起来会感觉到割裂。
举个例子,公路,山坡,白云,蓝天的运动速度都不一样,毕竟在画面中的远近关系不一样,把他们分别画在四个背景图片里,放在四个房间,然后设置四个移动房间事件,把位置都改为`(50%, 50%)`,把大小都改为`(100%, 100%)`,设置四个背景图片,使用平铺的方式,设置不同的水平移动速度,就得到了在公路上慢慢前进的效果。
![灵 魂 公 路](../images/assets-road.gif)
另外,使用小图片像地砖一样平铺才是更为原本的用法。
## 还原PV效果
有些音乐是自带PV/MV/BGA的,直接将原视频的风格或内容搬运到节奏医生中也不失为一种选择。但编辑器也有其自己的像素风格,有节奏医生自己的游戏特色,还原时也要讲究融合。
+85 -6
View File
@@ -1,4 +1,88 @@
# 镜头移动
# 房间与镜头
完全掌握了节奏医生的节奏设计之后,我们要把目光放在谱面的视觉呈现上了,这一节我们就从理解“房间”的概念开始。
编辑器总共支持四个房间,你可以想象成一栋房子有四层楼,每层楼最多住四个人,同时,每层楼的装修可以随意摆设互不干扰。这四层楼不一定刚刚好叠在一起,可以随时移动,互不交叠,只是高度不同。我们飞在空中从上往下看,就能看到目视所及范围内的大楼景象。同时,如果空中飘扬着其他物件,也会被我们的眼睛捕捉到,如果大楼的天花板和地板是透明的,那么地基里有什么东西也会被看到。
当我们使用**排列显示房间**事件时,房间就只能从上到下地排列在屏幕上,而如果使用**移动房间**事件,则可以随便移动。
## 排列显示房间
![排列房间设置(左)与实际效果(右)](../images/room-visible.png)
将左边的可见房间点亮为黄色,屏幕上就会显示这个房间,高度可以自定义,填写数据后房间高度将自动分配。详细的分配规则点击下方箭头展开。如果你懒得理解分配规则,只需永远保证 **不点亮多余的房间,并且将存在的房间高度总和设置到100%** 即可。
### 房间分配规则
- 如果全部不填,那么
所有房间高度为 `25%`
- 否则
- 计算已填房间高度的总和 `Sum`
- 如果 `Sum = 100%`,那么
按实际数据设置房间高度,未填写的视为 `0%`
- 如果 `Sum < 100%`,那么
- 如果有未填写房间高度的房间,设个数为 `n`,那么
未填写高度的房间高度 `height = (100% - Sum) / n`,即均分未分配的房间高度;
- 否则
每个房间的房间高度 `height = height * 100% / Sum`,即等比例拉伸房间高度至高度总和为 `100%`
- 如果 `Sum > 100%`,那么
每个房间的房间高度 `height = height * 100% / Sum`,即等比例缩小房间高度至高度总和为 `100%`
下面还留有一个时长和缓速的选项,这个和轨道移动的时所介绍的设置规律是完全相同的。如果填写0拍就是瞬间完成房间分配。
> 如果你想直观地看看各种移动方式的速度区别,可以[看看这里](https://easings.net/zh-cn)。
## 房间的前后关系
但实际上很多时候我们并不想就让房间这样死板地上下排布,甚至想让这些房间交叠在一起。要做到这一点,我们得先明确各个房间叠在一起的时候,它们的前后关系是怎样的。
![](../images/room-animation.gif)
首先看一个房间内,各种事件的由前往后关系是:
> [浮动文字]
[弹幕效果]
[前景图片]
[轨道4]
[轨道3]
[轨道2]
[轨道1]
[背景图片(图片)]
[背景图片(颜色)]
它们的前后顺序是不可改变的。
各个房间整体之间又有前后顺序,默认由前往后关系是:
> [显示状态牌]
[应用到:顶部]
[房间1]
[房间2]
[房间3]
[房间4]
四个房间的顺序是可以改变的,只需要在黄色版块内添加一个**重新排序房间**事件,把前后顺序拖动到想要的即可。
![](../images/room-layer.png)
## 激活其他房间
在刚打开编辑器的状态下,实际上只能看到房间1。并不是另外三个房间不存在,而是房间大小被设置成了`0%`。在黄色版块中找到**移动房间**事件,事件放置在工作区的哪一行,就是对应的哪个房间被移动。创建三个移动房间事件置于234行,将“大小”设置为`(100%,100%)`,这样所有的房间都以屏幕大小叠在一起了。
还记得[这里](../pages/settheme.md)提到了**设置主题**事件吗,我们再添加一个“花房·昼”。由于黄色版块不再是空白的,设置主题的事件的右上角出现了新的按钮,这是将事件设置到具体房间的功能。
![](../images/room-theme.png)
将带有花房·昼主题的事件选择房间4,预览效果会发现我们看到的依然是武士电子,因为现在不透明的房间1完全遮住了房间4。删掉武士电子主题,会发现背景全黑,依然看不到花房。这是因为默认状态下房间并不是透明背景,而是纯黑背景。
在紫色的版块找到**设置背景**事件,将背景颜色选择为纯透明,应用到123房间。再次预览,终于能看到房间4了。“应用到”选项是可以多选的。
![](../images/room-eventselectroom.png)
有时还会有第五个按钮“顶部”,如果你理解了本节最开头的比喻的话,应用到顶部的事件是直接在大楼与你之间的空中生效的。房间怎么移动都不会影响到顶部。
![](../images/room-eventsettings.png)
经此示例,相信你已经能理解房间的基本运作原理了。
## 概述
移动房间应该是整个编辑器内灵活性最高的功能之一了。它的灵活性本身并不是基于对编辑器功能的理解的,而是更类似于对摄影或是视频制作手法的理解。我们观看电影也总是会说“镜头语言”,这话同样适用于作谱。合理的镜头运用可以极大程度提升谱面的视觉观感。
@@ -54,11 +138,6 @@
![4-1N 的转场](../images/camera-minercutscene.gif)
**3、房间透明度**
**淡入淡出房间**事件倒是没有太多可说的,调节的是房间整体的透明度。同样也可以选择时长和缓速模式。
最基本的用法就是把一个房间的透明度从`0`调到`100`,另一个从`100`调到`0`,完成淡入淡出的转场。
**4、排列显示房间**
在[这一节](../pages/room.md)我们介绍过这个功能,但是使用这个软件自带的排列显示房间有一个略显僵硬的限制:房间的上下关系是不可变更的。如果想要自己定义谁在上谁在下,那就不能再使用这个默认功能了,需要我们添加移动房间功能来实现。
+148 -1
View File
@@ -1,4 +1,151 @@
# 其他文字事件
# 文字事件
## 浮动文字基本设置
如果我们要制作一首歌曲的谱面,一般而言都会考虑将歌词显示在画面中,这是一种简单粗暴,但能快速提升整体观感的做法。要在画面中加上字幕,我们需要在紫色的版块中找到**浮动文字**事件。
选择这个事件后,我们可以发现最开始的两行很有Word的感觉。
![](../images/floatingtext-fontslyle.png)
**aA**:可以调整字号大小,字号基本上没有上限,如果设置太大的话,文字就会**超出屏幕**。
**旋转**:可以旋转浮动文字框,注意是**整个文本框的旋转**,而不是每个字单独旋转。
**AB**:两个颜色分别是字的颜色和字符描边的颜色,刚才所说的字号里面,**只会包含字符本体的大小**,描边是没有算在里面的。
**↔**:指定浮动文字横向的基准位置。
**↕**:指定浮动文字纵向的基准位置。
![](../images/floatingtext-position.png)
**位置**:指的是基准的位置。可以按一下准星符号再在预览画面窗口中点选位置。有条件精准找到位置的话还是建议在`X``Y`栏中输入具体数值。**点击右边的`%`按键可以切换屏幕像素点和屏幕百分比两种输入方式**。
![不同基准在同一位置下的不同效果](../images/floatingtext-align.png)
**文字**:就是输入文本的地方了。纯英文文本是使用的像素字体,带有中文字符的情况下会全部变成矢量字体,如果你想要纯英文文本也显示矢量字体的话,可以回车键再在第二行输入一些中文,如下图所示。当文字框里没有中文时就无法输入中文,需在游戏外部打好要插入的文本,并通过复制粘贴的方式输入。
![](../images/floatingtext-example.png)
另外,目前已知中文繁体以及日语假名都可以在画面中正常显示。
![二次元歌曲狂喜](../images/floatingtext-jp.png)
**创建文本递进**:如果想要把一整句歌词按歌词节奏一个一个地显示出来,就需要在文本中使用“`/`”将它们隔开。如果想要一个一个地覆盖掉之前显示的内容,就需要在文本中使用`回车键`将他们隔开。之后点击下面的“创建文本递进”,在工作区里面可以拖动右箭头事件来调整时机。如果你做好了又不想要了,那么再把下面的开启改成关闭即可,无需手动删除。如果你又反悔了,还是想要,再改成开启,又会恢复记录。
```rdview 8 3
ea.FloatingText 1 1;
ea.AdvanceText 2 1;
ea.AdvanceText 3 1;
ea.AdvanceText 4 1;
ea.AdvanceText 5 1;
ea.AdvanceText 6 1;
ea.AdvanceText 7 1;
```
音节的消失方式选择**淡出**就是慢慢消失,**立即**就是瞬间消失,音节显示的时长是按创建文本递进的最后一个事件往后数拍子的。
```rdview 13 3
ea.FloatingText 1 1;
g 3 1 4 1;
g 7 1 0 1 #f80;
ea.AdvanceText 3 1;
g 8 1 4 1;
g 12 1 0 1 #f80;
ea.AdvanceText 8 1;
```
## 更丰富的效果和技巧
这个模块的基本功能就是上面那些,但是实际使用起来其实非常灵活。如果想要制作视觉效果更为丰富的字幕,就需要我们打开脑洞,多去深挖这些基础功能。下面我举几个例子给大家做一些启发。
**1、**如果想一次性显示多行,需要在换行的地方加上`\n`。输入`\/`才能打出“/”。
**2、**文本旋转效果是整个文本框的旋转,如果想要做到每个字都旋转,那么同样需要添加多个浮动文字模块,添加相同的旋转角度。如果想要让文本围绕一个中心旋转,那么直接用准星功能去找位置会方便一些。
**3、**如果在同一时刻同一位置有多个不同的浮动文字,那么字在屏幕中的上下层顺序只和你添加事件的先后顺序有关,先加入的事件在下层,后加入的事件在上层。这个机制无法进行修改。
**4、**如果想要给文本做颜色渐变的效果,可以在相同时间相同位置添加两个浮动文字,其中一个消失方式选择淡出,另一个选择立即,这样就获得了渐变效果。
**5、**把文字递进里面添加很多错误的文字,然后全部一个字一个字回车,就可以做到文字在同一位置的乱码效果。
**6、**在文本的最后放一个竖线“\|”或者下划线“\_”就可以做出打字的效果了。
![](../images/floatingtext-typing.gif)
```
ぼ|
ぼく|
僕|
僕の|
僕のゆ|
僕のゆめ|
僕の夢|
僕の夢
そ|
そう、|
そう、わ|
そう、わた|
そう、わたし|
そう、私|
そう、私の|
そう、私のゆ|
そう、私のゆめ|
そう、私の夢|
```
**7、**创建了一组文本递进之后,只需要双击浮动文字事件本身,整组字幕都会被选中。不需要一个个手动去点选了。
**8、**基准的左中右会影响文本递进效果。靠左时从左向右出现文本递进;靠中时从中间挤向两侧出现文本递进;靠右时从右向左出现文本递进。
**9、**在文本框的最后加一个空行,就可以通过文本递进的方式设置文本的结束时间,避免了一点点数格子的烦恼。
**10、**在文字中的个别字符前面加上`<color=#RRGGBBAA>`,后面加上`</color>`可以改变这几个字的颜色和透明度。关于颜色的介绍由于篇幅关系将放在下一小节。
![](../images/floatingtext-rainbow.png)
对应文本框内容为:
```html
<color=red>Wel</color><color=orange>come </color><color=yellow>to </color><color=green>Won</color><color=aqua>der</color><color=blue>land</color><color=purple>!</color>`<br>
<color=red>同</color><color=orange>赏</color><color=yellow>这</color><color=green>世</color><color=aqua>外</color><color=blue>景</color><color=purple>色</color>
```
## 演示关卡
你以为这里会有一个我们制作的关卡?其实并不。在这里我想介绍的是官方联动关卡`MD-2`,不知道你们在游玩这关感受爆炸难度的同时有没有注意到字幕的表现?如果你没有什么印象的话可以先看看下面这个视频:
<div class="bv"><iframe src="https://player.bilibili.com/player.html?aid=374450491&page=55&autoplay=0" title="BPM 与偏移的校对教程" width="100%" height="100%" scrolling="no" frameborder="no" framespacing="0" allowfullscreen="true"></iframe></div>
看完之后我们再来回忆一下其中一段歌词的表现:
> `夜深了 月光也换了颜色`<br>
> 【换了颜色】字体为黑色
>
> `要更迷幻更鲜艳眩目得赤裸`<br>
> 【鲜艳炫目】字体为亮蓝色
>
> `我也将披上褪浅的音色`<br>
> 【褪浅的音色】消失更早
>
> `逃离这个现实的现在时分的陷落`<br>
> 这句意外的正常
>
> `像逆行在通往大人的公路`<br>
> 【像逆行在】四个字是从右往左出现的,也就是位置基准改成了靠右
>
> `粉红的喇叭裤 墨镜里装星空`<br>
> 【粉红】两字为粉红色,【星空】两字为蓝色和紫色
>
> `忽闪忽灭的影子中`<br>
> 【忽】字反复出现和淡出了几次,【影子】是黑色
>
> `撞见了另一个我`<br>
> 【另一个我】有两份文字略微偏移重叠在一起
有没有发现不管是颜色效果还是显示效果,在设计上都和歌词本身有着些许联系,也就让平淡无奇的歌词字幕一下子变得生动起来。
## 显示对话
+19 -3
View File
@@ -1,4 +1,4 @@
# 修改游戏版本
# 修改游戏配置
## 说明
@@ -13,7 +13,7 @@
最后说明的是,不论你使用的是哪个版本,由于近期官方对编辑器的更新极为频繁,请务必将游戏更新设置为**始终保持此游戏为最新**,否则真的是……脑壳痛。
## 进入方式
## 修改游戏版本
接下来介绍进入Beta版本的方法:
@@ -31,4 +31,20 @@
第四步,直接打开游戏即可。
> 一切准备就绪,那么开始我们的节奏医生编辑器中文教程吧!
> 一切准备就绪,那么开始我们的节奏医生编辑器中文教程吧!
## 启用高级编辑器功能
从 v1.0.4 版本开始,高级编辑器功能被加入。其中包含一些在剧情关卡中使用,但之前不能在编辑器直接使用的功能。
要启用高级编辑器功能,首先按住 `tab`,然后你就会看到这个界面:
![没错,右下角的凹兔在盯着你](../images/changegameversion-tab.png)
然后狂点右下角的凹兔,直到弹出这个窗口:
![启用高级编辑器功能的窗口](../images/changegameversion-advanced-feature.png)
点击接受,此时高级编辑器功能就启用了。
如果你想关闭高级编辑器功能,只需要点一下 `tab` 界面右下角的凹兔即可。
+38
View File
@@ -1,5 +1,43 @@
# 更新信息
#### 2026-01-24
- 制作人员表增加了
#### 2026-01-16
- RDTKView(~~RDView2~~) 已完成部署
#### 2026-01-14
- 制作人员表增加了
- RDView 对正式版编辑器新特性的部分适配
- 正在逐步同步 RDView2(RhythmBase.View) 的适配
#### 2025-11-29
- 调整目录结构
- 双人模式措辞更改
- 移除 banner
- 修改暗色主题部分颜色
- 添加一项第三方工具介绍页面
- 更改了群号
- 添加了网页简介
- 添加了制作人员名单
- 更改了页面右侧功能区的样式
- 大量修改内容布局,这包括
- 场景资源
- 房间与镜头
- 文字事件
- 镜厅
- 轨道移动
- 房间视效
- 轨道视效
- 基础 vfx 效果
- 视觉干扰
- 部分页面处于未完成状态,如
- 基础 vfx 效果
- 旧版教程已归档至[这里](https://2025.rd.rdlevel.cn)
#### 2025-11-02
- [无障碍设计](../pages/accessibledesign.md)添加了屏幕朗读事件相关说明
#### 2025-10-27
- 添加 Webhook
+10 -8
View File
@@ -10,14 +10,14 @@
第二个选项“**摇摆**”就是剧情模式里老奶奶那样的摇摆普通拍子,可以使用拖动条来调节,对照下方绿色竖线的移动可以很直观地看到摇摆效果。不过拖动滑条你只能得到一些倍数十分规整的摇摆拍子,例如摇摆值为0.25,0.5,0.75等,如果你的音乐里真的有些更为不同寻常的摇摆幅度,那就要直接在框里填写数字了。
```rdview 8 9
eb.AddClassicBeat 1 1[swing=0.25,tick=6];
eb.AddClassicBeat 1 2[swing=0.5,tick=6];
eb.AddClassicBeat 1 3[swing=0.75,tick=6];
eb.AddClassicBeat 1 4[tick=6];
eb.AddClassicBeat 1 5[swing=1.25,tick=6];
eb.AddClassicBeat 1 6[swing=1.5,tick=6];
eb.AddClassicBeat 1 7[swing=1.75,tick=6];
```rdtkview 8 9
{"beat": 2, "y": 1, "type": "AddClassicBeat", "row": 0, "tick": 1, "swing": 0.25, "hold": 0 },
{"beat": 2, "y": 2, "type": "AddClassicBeat", "row": 0, "tick": 1, "swing": 0.5, "hold": 0 },
{"beat": 2, "y": 3, "type": "AddClassicBeat", "row": 0, "tick": 1, "swing": 0.75, "hold": 0 },
{"beat": 2, "y": 4, "type": "AddClassicBeat", "row": 0, "tick": 1, "swing": 1, "hold": 0 },
{"beat": 2, "y": 5, "type": "AddClassicBeat", "row": 0, "tick": 1, "swing": 1.25, "hold": 0 },
{"beat": 2, "y": 6, "type": "AddClassicBeat", "row": 0, "tick": 1, "swing": 1.5, "hold": 0 },
{"beat": 2, "y": 7, "type": "AddClassicBeat", "row": 0, "tick": 1, "swing": 1.75, "hold": 0 }
```
> 不要把摇摆程度拖到滑条的最右端,这样会产生一个不带`X`记号但只有2,4,6,7拍的节奏,无法读谱。
@@ -36,6 +36,8 @@ eb.AddClassicBeat 1 7[swing=1.75,tick=6];
> 尽量不要在第一拍设置`X`记号,这对纯音押玩家是不可预知的,在轨道数量多的情况下也会显得比较难理清节奏。如果你觉得你的音乐中这段节奏第一拍不放`X`就浑身难受,那也需要打开护士数拍(参考`X-WOT`这关中的`xx-----`)。
> 此外像马克的短轨道,需调用自定义方法来完成,语句为`SetRowLength(轨道编号[0索引的], 轨道长度[1~7的整数])`。如果你还不明白自定义方法是什么,需要先翻到[自定义方法](../pages/custommethod.md)看看。考虑到这玩意问的人比较多,所以就先写在此处了。
最后的选项“**分解为自由时长节拍**”较为复杂,我们放到[这里](/pages/moreclassicbeats)再介绍。
## 护士节奏提示
+3
View File
@@ -11,6 +11,9 @@
- [卢毅](https://space.bilibili.com/26101629)
- [RaYmondCheung](https://space.bilibili.com/1579208)
- [NoMathExpectation](https://space.bilibili.com/184862524)
- [0x4D2](https://space.bilibili.com/478595264)
- [正宗的小绿君](https://space.bilibili.com/1782518253)
- [kuanpan](https://space.bilibili.com/1928620300)
- 视频制作:
- [吾夜犹明](https://space.bilibili.com/29219948)
- [山不转水到渠成](https://space.bilibili.com/4870582)
+5
View File
@@ -90,6 +90,11 @@
`排位顺序`:同一时间设置多个自定义方法时,你可能需要让这些事件按一定顺序生效,这个时候就需要设置这个参数了。这个参数支持负数,数字越小,事件越早生效。
## 快捷查询
<div class="custommethods-search">
</div>
## 我知道你还想问什么
你也许会有这种疑问:为什么官方要设置一个“调用自定义方法”,像写代码一样完成一些明明是很成熟的功能和特效?为什么不把它们也做成普通的事件直接添加就好了?
-148
View File
@@ -1,148 +0,0 @@
# 浮动文字
## 浮动文字基本设置
如果我们要制作一首歌曲的谱面,一般而言都会考虑将歌词显示在画面中,这是一种简单粗暴,但能快速提升整体观感的做法。要在画面中加上字幕,我们需要在紫色的版块中找到**浮动文字**事件。
选择这个事件后,我们可以发现最开始的两行很有Word的感觉。
![](../images/floatingtext-fontslyle.png)
**aA**:可以调整字号大小,字号基本上没有上限,如果设置太大的话,文字就会**超出屏幕**。
**旋转**:可以旋转浮动文字框,注意是**整个文本框的旋转**,而不是每个字单独旋转。
**AB**:两个颜色分别是字的颜色和字符描边的颜色,刚才所说的字号里面,**只会包含字符本体的大小**,描边是没有算在里面的。
**↔**:指定浮动文字横向的基准位置。
**↕**:指定浮动文字纵向的基准位置。
![](../images/floatingtext-position.png)
**位置**:指的是基准的位置。可以按一下准星符号再在预览画面窗口中点选位置。有条件精准找到位置的话还是建议在`X``Y`栏中输入具体数值。**点击右边的`%`按键可以切换屏幕像素点和屏幕百分比两种输入方式**。
![不同基准在同一位置下的不同效果](../images/floatingtext-align.png)
**文字**:就是输入文本的地方了。纯英文文本是使用的像素字体,带有中文字符的情况下会全部变成矢量字体,如果你想要纯英文文本也显示矢量字体的话,可以回车键再在第二行输入一些中文,如下图所示。当文字框里没有中文时就无法输入中文,需在游戏外部打好要插入的文本,并通过复制粘贴的方式输入。
![](../images/floatingtext-example.png)
另外,目前已知中文繁体以及日语假名都可以在画面中正常显示。
![二次元歌曲狂喜](../images/floatingtext-jp.png)
**创建文本递进**:如果想要把一整句歌词按歌词节奏一个一个地显示出来,就需要在文本中使用“`/`”将它们隔开。如果想要一个一个地覆盖掉之前显示的内容,就需要在文本中使用`回车键`将他们隔开。之后点击下面的“创建文本递进”,在工作区里面可以拖动右箭头事件来调整时机。如果你做好了又不想要了,那么再把下面的开启改成关闭即可,无需手动删除。如果你又反悔了,还是想要,再改成开启,又会恢复记录。
```rdview 8 3
ea.FloatingText 1 1;
ea.AdvanceText 2 1;
ea.AdvanceText 3 1;
ea.AdvanceText 4 1;
ea.AdvanceText 5 1;
ea.AdvanceText 6 1;
ea.AdvanceText 7 1;
```
音节的消失方式选择**淡出**就是慢慢消失,**立即**就是瞬间消失,音节显示的时长是按创建文本递进的最后一个事件往后数拍子的。
```rdview 13 3
ea.FloatingText 1 1;
g 3 1 4 1;
g 7 1 0 1 #f80;
ea.AdvanceText 3 1;
g 8 1 4 1;
g 12 1 0 1 #f80;
ea.AdvanceText 8 1;
```
## 更丰富的效果和技巧
这个模块的基本功能就是上面那些,但是实际使用起来其实非常灵活。如果想要制作视觉效果更为丰富的字幕,就需要我们打开脑洞,多去深挖这些基础功能。下面我举几个例子给大家做一些启发。
**1、**如果想一次性显示多行,需要在换行的地方加上`\n`。输入`\/`才能打出“/”。
**2、**文本旋转效果是整个文本框的旋转,如果想要做到每个字都旋转,那么同样需要添加多个浮动文字模块,添加相同的旋转角度。如果想要让文本围绕一个中心旋转,那么直接用准星功能去找位置会方便一些。
**3、**如果在同一时刻同一位置有多个不同的浮动文字,那么字在屏幕中的上下层顺序只和你添加事件的先后顺序有关,先加入的事件在下层,后加入的事件在上层。这个机制无法进行修改。
**4、**如果想要给文本做颜色渐变的效果,可以在相同时间相同位置添加两个浮动文字,其中一个消失方式选择淡出,另一个选择立即,这样就获得了渐变效果。
**5、**把文字递进里面添加很多错误的文字,然后全部一个字一个字回车,就可以做到文字在同一位置的乱码效果。
**6、**在文本的最后放一个竖线“\|”或者下划线“\_”就可以做出打字的效果了。
![](../images/floatingtext-typing.gif)
```
ぼ|
ぼく|
僕|
僕の|
僕のゆ|
僕のゆめ|
僕の夢|
僕の夢
そ|
そう、|
そう、わ|
そう、わた|
そう、わたし|
そう、私|
そう、私の|
そう、私のゆ|
そう、私のゆめ|
そう、私の夢|
```
**7、**创建了一组文本递进之后,只需要双击浮动文字事件本身,整组字幕都会被选中。不需要一个个手动去点选了。
**8、**基准的左中右会影响文本递进效果。靠左时从左向右出现文本递进;靠中时从中间挤向两侧出现文本递进;靠右时从右向左出现文本递进。
**9、**在文本框的最后加一个空行,就可以通过文本递进的方式设置文本的结束时间,避免了一点点数格子的烦恼。
**10、**在文字中的个别字符前面加上`<color=#RRGGBBAA>`,后面加上`</color>`可以改变这几个字的颜色和透明度。关于颜色的介绍由于篇幅关系将放在下一小节。
![](../images/floatingtext-rainbow.png)
对应文本框内容为:
```html
<color=red>Wel</color><color=orange>come </color><color=yellow>to </color><color=green>Won</color><color=aqua>der</color><color=blue>land</color><color=purple>!</color>`<br>
<color=red>同</color><color=orange>赏</color><color=yellow>这</color><color=green>世</color><color=aqua>外</color><color=blue>景</color><color=purple>色</color>
```
## 演示关卡
你以为这里会有一个我们制作的关卡?其实并不。在这里我想介绍的是官方联动关卡`MD-2`,不知道你们在游玩这关感受爆炸难度的同时有没有注意到字幕的表现?如果你没有什么印象的话可以先看看下面这个视频:
<div class="bv"><iframe src="https://player.bilibili.com/player.html?aid=374450491&page=55&autoplay=0" title="BPM 与偏移的校对教程" width="100%" height="100%" scrolling="no" frameborder="no" framespacing="0" allowfullscreen="true"></iframe></div>
看完之后我们再来回忆一下其中一段歌词的表现:
> `夜深了 月光也换了颜色`<br>
> 【换了颜色】字体为黑色
>
> `要更迷幻更鲜艳眩目得赤裸`<br>
> 【鲜艳炫目】字体为亮蓝色
>
> `我也将披上褪浅的音色`<br>
> 【褪浅的音色】消失更早
>
> `逃离这个现实的现在时分的陷落`<br>
> 这句意外的正常
>
> `像逆行在通往大人的公路`<br>
> 【像逆行在】四个字是从右往左出现的,也就是位置基准改成了靠右
>
> `粉红的喇叭裤 墨镜里装星空`<br>
> 【粉红】两字为粉红色,【星空】两字为蓝色和紫色
>
> `忽闪忽灭的影子中`<br>
> 【忽】字反复出现和淡出了几次,【影子】是黑色
>
> `撞见了另一个我`<br>
> 【另一个我】有两份文字略微偏移重叠在一起
有没有发现不管是颜色效果还是显示效果,在设计上都和歌词本身有着些许联系,也就让平淡无奇的歌词字幕一下子变得生动起来。
+33 -6
View File
@@ -1,18 +1,45 @@
# 镜厅
> 预警放在最前面:观看本节教程图片可能会引发光敏性癫痫,在编辑器中使用此功能也请慎重处理。
游戏的画面是一帧一帧地播放的。为了确保游戏的画面一直在更新,在绘制一帧画面之前,游戏会将已经绘制过的画面重置为全黑。
**但是如果不重置呢?**
> 本节动图较多,如遇加载卡顿,请耐心等待。
## 基础效果
所谓的镜厅效果,就是画面在变化的时候并不清除变化过程中产生的效果,画面效果会一直叠加,然后逐渐变得混乱。
相信你已经有了初步的感觉。镜厅就是这样,原来一帧的画面仍然保留在屏幕上,只是游戏重新绘制的画面直接覆盖在了原画面之上,从而造成一种“拖影”的效果。
这本是一种“bug”,但如果稍加利用,或许会有出其不意的效果。
<div class="bv"><iframe src="https://player.bilibili.com/player.html?bvid=BV1vW411t7NF&page=18&autoplay=0" title="BPM 与偏移的校对教程" width="100%" height="100%" scrolling="no" frameborder="no" framespacing="0" allowfullscreen="true"></iframe></div>
## 抑制方法
镜厅一共能在两个地方找到,一是设置主题中的 “镜厅”,二是预设特效中的“镜厅”。**但最好使用预设特效中的**。
### 画面的覆盖
既然画面是一层一层叠在上面,如果要“修复这个 bug”,那就得咱们手动去将整个屏幕更新。
但是如果直接覆盖一个特定的颜色或者背景,那好像和直接设置背景没什么区别,镜厅就没有存在的意义了。
那半透明呢?
画面会被覆盖,但是覆盖程度取决于透明度。
我们来做个小实验:假设现在有一个像素的亮度为 100,每一帧向右移动 1 像素,在镜厅的效果下会导致它在每一帧一直留存,但是现在有一个手段,能够在每一帧画完之前整个画面的亮度降为原来的一半,那这个像素的实际亮度是怎样的呢?
| 帧 | 亮度 ||||
|-|-:|-:|-:|-:|
|1|100|
|2|50|100|
|3|25|50|100|
|4|12.5|25|50|100|
理解了这个之后,你就可以着手做出这样的效果:
![](../images/hallofmirror-trail.gif)
### 画面的扭曲
同样的,也可以
---
镜厅一共能在两个地方找到,一是设置主题中的 “镜厅”,二是预设特效中的“镜厅”。**但最好使用预设特效中的**。
如果只是直接使用镜厅加上预设特效,效果一般只会越来越阴间,所以我们一般会使用预设特效里的“晕影”和“闪烁晕影”或者半透明的背景或半透明的后背景板闪光(由于设备性能差别,镜厅的效果显示可能每个人会有所不同,我一般使用20的透明度)来起到抑制的效果,同时这样也能直接做出最简单的拖尾效果。
![](../images/hallofmirror-trail.gif)
拖尾效果(可以注意到镜厅留下了痕迹 ,如果想去除就需要再加上其他的效果,比如-1强度的高光)。这里再附上一些特效在遮罩后的组合(默认都已经打开了镜厅)。
+5 -7
View File
@@ -1,11 +1,8 @@
<div class="intro"></div>
<div onclick="location.href='https://www.bilibili.com/opus/1095830097776082950';" class="notice">
<p>2026节奏医生拜年纪活动正在招募中!</p>
</div>
# 节奏医生中文编辑器教程
> 此网页正在维护中。
> 此网页正在活跃维护中。
网页已开源至[此处](https://git.obugs.cn/RDCNWebs/rd.rdlevel.cn),欢迎投稿。
> 页面内的大部分事件栏板块包含点击互动。尝试点击以获得更生动的演示。
@@ -16,10 +13,11 @@
编辑器视频教程点击[此链接](https://www.bilibili.com/video/BV1pr4y1k7gP)。教程内所有演示关卡下载放置于[百度网盘](https://pan.baidu.com/s/1Tb6ywVmge25ztMFnpa6q_Q),提取码:rdlv。
## 联系我们
<div class="qqgroup">
<img src="../images/intro-qqgroup2.png" data-no-zoom alt="我们的 QQ 1044116596"/><p>我们的 QQ 群号是: 1044116596</p>
</div>
![我们的 QQ 群号是:951070053](../images/intro-qqgroup.png)
如果你有做谱相关的问题,或是对本教程有什么意见和建议,可以点击链接加入 QQ 群 [951070053](https://jq.qq.com/?_wv=1027&k=nsPA09E4) 告知我们。你也可以在群里上传谱面给我们试玩,群友们都会热心为你提供谱面优化建议。真诚欢迎各位做谱萌新和大佬的加入。
如果你有做谱相关的问题,或是对本教程有什么意见和建议,可以点击链接加入 QQ 群 [1044116596](https://qm.qq.com/q/giuo0RDv4Q) 告知我们。你也可以在群里上传谱面给我们试玩,群友们都会热心为你提供谱面优化建议。真诚欢迎各位做谱萌新和大佬的加入。
(悄悄透露一句:官方也入驻了这个群哦~)
+47 -1
View File
@@ -179,7 +179,7 @@ es.SayReadyGetSetGo_Go 3 1[];
与方块单发拍的概念类似,**细分拍**也是“一次性”的单发拍,但是会产生多次等间距的心跳脉冲,按键的次数也变为多次。
细分拍最早出现于`MD-1`,当时官方谱面没有官方名称,且最多仅有两个三角拍;后来第五章更新后三角拍首次出现在`5-1`并正式更名为**细分拍**,并出现了多个细分。
细分拍最早出现于`MD-1`,当时官方谱面没有官方名称,且最多仅有两个三角拍;后来第五章更新后三角拍首次出现在`5-1`并正式更名为**细分拍**,并出现了多个细分;在关卡`5-2N`中最多涉及到了五级细分;正式版更新后,在关卡`7-X2`中甚至有了八细分
在修饰符中选择方块后,将细分数量设为大于 1 的值或者点击细分符号``,即可创建细分拍。特殊音效的添加与方块单发拍类似。最多可以将细分数量设置为 10 。
@@ -338,6 +338,52 @@ g 0 -1 3 2 #0000[offset=0 1]{
};
```
## 长按单发拍
长按单发拍第一次出现在`7-1`
当听到`咻噗`的声音时,说明下一次击拍需要长按到下一个出拍点。
在修饰符中选中进度条符号就创建了一个长按单发拍,会多出`间隔`与`长按提示选项`选项。
![](../images/moreoneshothold.png)
对于长按单发拍,一共有四个关键的时间点:十字,出拍点(绿线),按拍点(黄线),长按(紫色格子)。
```rdtkview 5 3
{ "bar": 1, "beat": 3, "y": 2, "type": "AddOneshotBeat","interval": 2, "tick": 1, "hold": true }
```
- **十字**显示长按单发拍子的提示音。
- **绿线**代表单发拍会在此响一次。
- **黄线**表示长按的起始点,也就是说玩家应当从这里开始长按。
- **紫格**就是此次长按所需的时间。
- **绿线**与**黄线**之间的间隔就是`拍长`的时间。
- **十字**与**黄线**或者**绿线**与**紫格**末端之间的间隔就是`间隔`的时间。
在`长按提示`有三个选项,分别是:自动、偏早、偏晚。
- 选择**偏早**时,`十字`的位置会在`绿线`之前。
- 选择**偏晚**时,`十字`不会显示,但提示音会与`绿线`重合。
- 选择**自动**时:
- 若**拍长**小于或等于1,则像`偏早`一样,长按单发拍子的提示音会在`绿线`之前;
- 若**拍长**大于1,则像`偏晚`一样,`十字`不会显示,但提示音会与`绿线`重合。
```rdtkview 5 5
{ "bar": 1, "beat": 3, "y": 2, "type": "AddOneshotBeat","interval": 2, "tick": 1, "hold": true },
{ "bar": 1, "beat": 3, "y": 3, "type": "AddOneshotBeat","interval": 2, "tick": 1, "hold": true },
{ "bar": 1, "beat": 3, "y": 4, "type": "AddOneshotBeat","interval": 2, "tick": 1, "hold": true }
```
若设计长按单发拍,还必须满足松手音效与提示音不可重叠
如果需要在长按单发拍上叠加多个拍子来凸显鼓点,可以将他们的按拍点放在同一位置。
```rdtkview 5 3
{ "bar": 1, "beat": 1.5, "y": 2, "tick": 2.5, "type": "AddOneshotBeat" },
{ "bar": 1, "beat": 2.5, "y": 2, "tick": 1.5, "type": "AddOneshotBeat" },
{ "bar": 1, "beat": 3, "y": 2, "type": "AddOneshotBeat","interval": 2, "tick": 1, "hold": true }
```
最后我们针对细分拍、冻结拍、灼热拍做一个技术总结:
```rdview 19 7
+49 -7
View File
@@ -1,18 +1,47 @@
# 轨道移动
## 轨道的显示与隐藏
## 默认轨道位置
轨道在关卡进行的过程中是可以随时调整其显示和隐藏状态的,这个功能可在紫色版块的**隐藏轨道**中找到。打开后有三个设置项:
![](../images/moverow-wyym.png)
当我们在同一房间里设置了多个轨道的时候,角色位置会自动生成在屏幕上。不同的轨道数量下默认的位置也会不同:
**轨道**:要显示/隐藏的是哪条轨道。注意一次只能选择一个,所以如果需要大批量地显示和隐藏只能一点点加入事件了。
* 一根轨道在屏幕的`(9.94%, 50.00%)`
* 两根轨道在屏幕的`(9.94%, 60.61%)`,`(9.94%, 39.39%)`
* 三根轨道在屏幕的`(9.94%, 71.21%)`,`(9.94%, 50.00%)`,`(9.94%, 28.79%)`
* 四根轨道在屏幕的`(9.94%, 81.82%)`,`(9.94%, 60.61%)`,`(9.94%, 39.39%)`,`(9.94%, 18.18%)`
**动作**:四个选项(显示/隐藏/仅显示角色/仅显示轨道),显示和隐藏比较好理解;仅显示角色的意思是没有中间的横线和右边的心脏;仅显示轨道的意思是没有左边的人物图。
![](../images/settheme-rowposition.png)
> 如果你想要不显示心脏,最简单的办法是使用移动轨道事件将心脏移到屏幕外。如果想要隐藏所有轨道的心脏,也可以通过调用自定义方法 invisibleHeart = true 来实现,参考[自定义方法](../pages/custommethod.md)。
<div class="theme-positions" id="theme-positions">
<div class="column ccharacter"></div>
<div class="column c1"></div>
<div class="column c2"></div>
<div class="column c3"></div>
<div class="column c4"></div>
<div class="column c5"></div>
<div class="column ccenter"></div>
<div class="column c6"></div>
<div class="column c7"></div>
<div class="column cheart"></div>
<div class="row r1"></div>
<div class="row r2"></div>
<div class="row r3"></div>
<div class="row r4"></div>
<div class="row r5"></div>
<div class="row r6"></div>
<div class="row r7"></div>
<div class="selectbox"></div>
<div class="infobox">
<p class="per"><span class="x"></span>, <span class="y"></span></p>
<p class="px"><span class="x"></span>, <span class="y"></span></p>
<p class="other"></p>
</div>
</div>
**过渡方式**:顺滑(有烟雾特效);即刻(瞬间显示/隐藏);全动画(仅限“动作”中选择“显示”,有完整的出场及轨道延伸动画)。
此处的坐标原点为屏幕左下角,轨道的参考位置是人物像素画的中心点。如果任其按默认位置排布,会显得有些缺乏设计感。
![](../images/settheme-4rows.png)
## 轨道的移动
@@ -87,6 +116,19 @@
5、**移动角色和心脏:**角色和心脏的移动是以他们在轨道中的位置为原点来移动的,比如填写`x: 0, y: 20px`则角色或者心脏向上移动20个像素。你可以使用这个功能把整个轨道挪到屏幕外面去,再以此为原点把心脏挪回来,就可以做到在屏幕内只显示心脏。
## 旋转轨道
> 目前该事件还不稳定,部分动作可能与轨道移动有冲突。
如果想要实现`6-2`马克一人多轨的情况就可以使旋转轨道事件。
先准备两个轨道,使用`连接`将轨道2连接到轨道1上,此时心会自动变成裂纹状态,如果不想要这个效果,可以用下一章轨道涂色里的`心`设置回默认。
在连接后,通过`分割`可以将两个轨道都显示出来,这两个轨道都会对被连接到的轨道对应角色产生影响。
`断开`后这些轨道都会回复正常状态。
## 演示关卡
版面已经占的有些多了,更多的轨道移动脑洞我们留在演示关卡中间。
+1 -1
View File
@@ -1,4 +1,4 @@
# 05 单发拍子
# 单发拍子
## 单发拍子功能介绍
-85
View File
@@ -1,85 +0,0 @@
# 房间
完全掌握了节奏医生的节奏设计之后,我们要把目光放在谱面的视觉呈现上了,这一节我们就从理解“房间”的概念开始。
编辑器总共支持四个房间,你可以想象成一栋房子有四层楼,每层楼最多住四个人,同时,每层楼的装修可以随意摆设互不干扰。这四层楼不一定刚刚好叠在一起,可以随时移动,互不交叠,只是高度不同。我们飞在空中从上往下看,就能看到目视所及范围内的大楼景象。同时,如果空中飘扬着其他物件,也会被我们的眼睛捕捉到,如果大楼的天花板和地板是透明的,那么地基里有什么东西也会被看到。
当我们使用**排列显示房间**事件时,房间就只能从上到下地排列在屏幕上,而如果使用**移动房间**事件,则可以随便移动。
## 排列显示房间
![排列房间设置(左)与实际效果(右)](../images/room-visible.png)
将左边的可见房间点亮为黄色,屏幕上就会显示这个房间,高度可以自定义,填写数据后房间高度将自动分配。详细的分配规则点击下方箭头展开。如果你懒得理解分配规则,只需永远保证 **不点亮多余的房间,并且将存在的房间高度总和设置到100%** 即可。
### 房间分配规则
- 如果全部不填,那么
所有房间高度为 `25%`
- 否则
- 计算已填房间高度的总和 `Sum`
- 如果 `Sum = 100%`,那么
按实际数据设置房间高度,未填写的视为 `0%`
- 如果 `Sum < 100%`,那么
- 如果有未填写房间高度的房间,设个数为 `n`,那么
未填写高度的房间高度 `height = (100% - Sum) / n`,即均分未分配的房间高度;
- 否则
每个房间的房间高度 `height = height * 100% / Sum`,即等比例拉伸房间高度至高度总和为 `100%`
- 如果 `Sum > 100%`,那么
每个房间的房间高度 `height = height * 100% / Sum`,即等比例缩小房间高度至高度总和为 `100%`
下面还留有一个时长和缓速的选项,这个和轨道移动的时所介绍的设置规律是完全相同的。如果填写0拍就是瞬间完成房间分配。
> 如果你想直观地看看各种移动方式的速度区别,可以[看看这里](https://easings.net/zh-cn)。
## 房间的前后关系
但实际上很多时候我们并不想就让房间这样死板地上下排布,甚至想让这些房间交叠在一起。要做到这一点,我们得先明确各个房间叠在一起的时候,它们的前后关系是怎样的。
![](../images/room-animation.gif)
首先看一个房间内,各种事件的由前往后关系是:
> [浮动文字]
[弹幕效果]
[前景图片]
[轨道4]
[轨道3]
[轨道2]
[轨道1]
[背景图片(图片)]
[背景图片(颜色)]
它们的前后顺序是不可改变的。
各个房间整体之间又有前后顺序,默认由前往后关系是:
> [显示状态牌]
[应用到:顶部]
[房间1]
[房间2]
[房间3]
[房间4]
四个房间的顺序是可以改变的,只需要在黄色版块内添加一个**重新排序房间**事件,把前后顺序拖动到想要的即可。
![](../images/room-layer.png)
## 激活其他房间
在刚打开编辑器的状态下,实际上只能看到房间1。并不是另外三个房间不存在,而是房间大小被设置成了`0%`。在黄色版块中找到**移动房间**事件,事件放置在工作区的哪一行,就是对应的哪个房间被移动。创建三个移动房间事件置于234行,将“大小”设置为`(100%,100%)`,这样所有的房间都以屏幕大小叠在一起了。
还记得[这里](../pages/settheme.md)提到了**设置主题**事件吗,我们再添加一个“花房·昼”。由于黄色版块不再是空白的,设置主题的事件的右上角出现了新的按钮,这是将事件设置到具体房间的功能。
![](../images/room-theme.png)
将带有花房·昼主题的事件选择房间4,预览效果会发现我们看到的依然是武士电子,因为现在不透明的房间1完全遮住了房间4。删掉武士电子主题,会发现背景全黑,依然看不到花房。这是因为默认状态下房间并不是透明背景,而是纯黑背景。
在紫色的版块找到**设置背景**事件,将背景颜色选择为纯透明,应用到123房间。再次预览,终于能看到房间4了。“应用到”选项是可以多选的。
![](../images/room-eventselectroom.png)
有时还会有第五个按钮“顶部”,如果你理解了本节最开头的比喻的话,应用到顶部的事件是直接在大楼与你之间的空中生效的。房间怎么移动都不会影响到顶部。
![](../images/room-eventsettings.png)
经此示例,相信你已经能理解房间的基本运作原理了。
+5
View File
@@ -1,5 +1,10 @@
# 房间视效
## 房间透明度
**淡入淡出房间**事件倒是没有太多可说的,调节的是房间整体的透明度。同样也可以选择时长和缓速模式。
最基本的用法就是把一个房间的透明度从`0`调到`100`,另一个从`100`调到`0`,完成淡入淡出的转场。
## 房间遮罩
### 图片遮罩
+15
View File
@@ -56,6 +56,21 @@
![](../images/rowfx-heighlight.gif)
## 轨道的显示与隐藏
轨道在关卡进行的过程中是可以随时调整其显示和隐藏状态的,这个功能可在紫色版块的**隐藏轨道**中找到。打开后有三个设置项:
![](../images/moverow-wyym.png)
**轨道**:要显示/隐藏的是哪条轨道。注意一次只能选择一个,所以如果需要大批量地显示和隐藏只能一点点加入事件了。
**动作**:四个选项(显示/隐藏/仅显示角色/仅显示轨道),显示和隐藏比较好理解;仅显示角色的意思是没有中间的横线和右边的心脏;仅显示轨道的意思是没有左边的人物图。
> 如果你想要不显示心脏,最简单的办法是使用移动轨道事件将心脏移到屏幕外。如果想要隐藏所有轨道的心脏,也可以通过调用自定义方法 invisibleHeart = true 来实现,参考[自定义方法](../pages/custommethod.md)。
**过渡方式**:顺滑(有烟雾特效);即刻(瞬间显示/隐藏);全动画(仅限“动作”中选择“显示”,有完整的出场及轨道延伸动画)。
## 适合配合轨道或节拍一起使用的特效
**闪烁:**屏幕白色闪烁,分为短,中,长三种。
+39 -40
View File
@@ -1,45 +1,5 @@
# 场景与主题
当我们在同一房间里设置了多个轨道的时候,角色位置会自动生成在屏幕上。不同的轨道数量下默认的位置也会不同:
* 一根轨道在屏幕的`(9.94%, 50.00%)`
* 两根轨道在屏幕的`(9.94%, 60.61%)`,`(9.94%, 39.39%)`
* 三根轨道在屏幕的`(9.94%, 71.21%)`,`(9.94%, 50.00%)`,`(9.94%, 28.79%)`
* 四根轨道在屏幕的`(9.94%, 81.82%)`,`(9.94%, 60.61%)`,`(9.94%, 39.39%)`,`(9.94%, 18.18%)`
![](../images/settheme-rowposition.png)
<div class="theme-positions" id="theme-positions">
<div class="column ccharacter"></div>
<div class="column c1"></div>
<div class="column c2"></div>
<div class="column c3"></div>
<div class="column c4"></div>
<div class="column c5"></div>
<div class="column ccenter"></div>
<div class="column c6"></div>
<div class="column c7"></div>
<div class="column cheart"></div>
<div class="row r1"></div>
<div class="row r2"></div>
<div class="row r3"></div>
<div class="row r4"></div>
<div class="row r5"></div>
<div class="row r6"></div>
<div class="row r7"></div>
<div class="selectbox"></div>
<div class="infobox">
<p class="per"><span class="x"></span>, <span class="y"></span></p>
<p class="px"><span class="x"></span>, <span class="y"></span></p>
<p class="other"></p>
</div>
</div>
此处的坐标原点为屏幕左下角,轨道的参考位置是人物像素画的中心点。如果任其按默认位置排布,会显得有些缺乏设计感。
![](../images/settheme-4rows.png)
所以在设计全程静止不动的轨道位置的时候,我们应该在一开始就让他们站在合适的位置上,并且最好能契合背景画面。下面我们拿官方自带的一些场景来举例子。使用这些场景需要在紫色版块里面添加**设置主题**,再选择“花房·昼”。然后在时间轴最开始的位置设好三个人物的轨道移动。
这样三个角色都**站在地上**并且有一定的交错。没错,这就是`3-1`沉睡花园。
@@ -57,3 +17,42 @@
甚至轨道可以大部分位置都不可见。比如制作只显示脉冲心跳部位的单发拍子,并做成纯色等。
> 调用自定义方法`invisibleHeart = true`可以让轨道上的心脏消失。如果不选择角色,那么就只剩下一根线了,在一些极简色块画风的关卡里效果拔群。
## 背景和前景图片
在房间的前后关系里我们提到了背景图片和前景图片这两个概念,也就是说,除了使用编辑器内自带的一些主题之外,其实自己也是可以自定义画面的背景和前景图案的。这个功能同样十分灵活,但是如果想要完全靠自己来原创或是临摹背景图片的话,可能需要对画像素画有一些掌握。
选择紫色的版块,放置一个**设置背景**的事件,发现里面有两种形式,一种是纯色,这个比较好理解,唯独要注意的是**纯色的默认值是黑色而不是透明**,另一种是插入图片。
> 插入的图片必须是.png格式,如果你是自己画背景图,建议使用画布大小为352\*198像素。
颜色选项,看似意义不明,但其实也有一定的用处。如果你导入的图片只有纯白和透明两种颜色,这个功能就可以为纯白的部分染色,染成你自己设置的颜色。但是因为一次只能设置一种颜色,使用起来也有些限制。
缩放功能其实类似于操作系统里壁纸的填充方式,具体效果点开小箭头查看。
<details><summary><strong>填充方式</strong></summary>
<img src="../images/assets-fillmode.png" alt="填充方式图例" />
<ul>
<li><strong>填满:</strong>将画面拉伸到横纵全部填满屏幕。要注意的是,如果你塞进去一张高清图,编辑器也会把它缩小到352\*198像素来适应画面,而且这个缩放机制是像素化的,画面会变得非常模糊。</li>
<li><strong>拉伸:</strong>将画面等比拉伸直到左右垂直线对齐屏幕。</li>
<li><strong>等比拉伸:</strong>将画面等比拉伸直到上下水平线对齐屏幕。</li>
<li><strong>居中:</strong>就是按原画面大小放在正中间。</li>
<li><strong>平铺:</strong>像铺瓷砖一样铺满屏幕。</li>
</ul>
</details>
> 如果你想做一个动图效果,需要把.gif拆解成一连串的.png图片,在选择图片时同时选择所有的图点击确定。接下来就会多出一个设置帧数的选项,来确定动图的播放速度。帧数 = \(背景图总画面数 / 一个循环占节拍数量\) \* 曲速/60。
设置背景一样,但使用这个功能的主要目的还是为了能产生一个图片覆盖轨道和手的效果,这样在画面效果的处理上可以更加灵活。
## 平铺背景
唯独平铺选项会多冒出来一个速度设置,它可以让背景图片始终保持设置的速度移动。
* 在滚屏模式下,效果类似于<code>4-2</code>的天空在慢慢移动,速度和缓速则是调整背景从静止到目标速度的变化过程。
* 在脉冲模式下,背景的移动速度变化就是周期性的,用<code>间隔</code>来调整周期。另外,如果你想设计这样的移动背景,在作画的时候也需要考虑画面左右两端和上下两端的连续,否则画面运动起来会感觉到割裂。
举个例子,公路,山坡,白云,蓝天的运动速度都不一样,毕竟在画面中的远近关系不一样,把他们分别画在四个背景图片里,放在四个房间,然后设置四个移动房间事件,把位置都改为`(50%, 50%)`,把大小都改为`(100%, 100%)`,设置四个背景图片,使用平铺的方式,设置不同的水平移动速度,就得到了在公路上慢慢前进的效果。
![灵 魂 公 路](../images/assets-road.gif)
另外,使用小图片像地砖一样平铺才是更为原本的用法。
+1 -1
View File
@@ -16,6 +16,6 @@
官方在 v0.18.0 时重新设计了大量关卡的双人模式版本。
在设计双人模式关卡时,最核心的要点就是:需要让玩家分清他所控制的轨道。这同时也适用于在关卡中将某个轨道托付给 Otto 时的情况。
在为单发拍使用护士提示时需要用两种护士音效以区分玩家,通常为 P1 使用的语音为**护士**,P2 使用的语音为**伊恩**。你也可以根据实际场景交换这两者
在为单发拍使用护士提示时需要用两种护士音效以区分玩家,通常为 P1 使用的语音为**护士**,P2 使用的语音为**伊恩**。你也可以根据实际场景灵活变通
轨道的音效使用左右声道作区分(例如左声道只播放 P1 需要操控的轨道的音效而右声道相反)也是一个不错的选择。
当 P1、P2 交换轨道控制权时,需要使用护士语音 `Switch` 以提示即将交换轨道控制权。
+6 -67
View File
@@ -1,72 +1,11 @@
# 视觉干扰
# 基础 VFX 效果
> 在关卡中出现对比度较高画面快速交替,如红蓝、黑白快速闪烁,必须开启癫痫警告。使用“放克”特效,必须开启癫痫警告。使用“干扰”特效较多,建议开启癫痫警告。一秒出现3次以上快速闪烁,建议开启癫痫警告。
## 震动
> 即使开启了癫痫警告,也不要设计出会伤害视力的干扰效果。
## 闪光
## 综述
## 预设 VFX
视觉干扰效果算是节奏医生做谱的一大特色了。因为游戏玩法本身是可以做到纯音押的,所以在视觉上对玩家进行考验不仅可以增大难度,同时又可以有很新奇的观赏效果。在剧情模式中,视觉干扰主要集中在`1-X 东方失眠夜``1-XN 超·东方失眠夜`两关,其余还有关卡的小部分环节用到了视觉干扰,效果都极具震撼。
## 反色
需要注意的是,**视觉干扰不等于读谱不能**,更不等于塞爆。这些干扰是为重复或单一的节奏增添趣味与挑战性而添加的,虽然一定意义上增加了读谱难度,但是仍应当给玩家留有恰当的反应时间。如果节奏设计本身就有难度,还刻意阻挡玩家进行识谱,效果将会是适得其反的。
另外,视觉干扰设计的主要原则依然是采音。音乐具有这样的特色,且不好转变为轨道节奏的话,就把这部分采音对应到视觉的同步变化和卡顿,完美地解决节奏设计与画面设计两个问题。
## 卡带效果
如果你对剧情关卡`1-X`东方不眠夜还有印象的话,或许能回忆起节奏配合着音乐一卡一卡的效果,这就是靠**卡带效果**做到的,它可以让心跳在某一拍卡住。
![](../images/vfx-settings.jpg)
这样看图似乎也不够直观,我们举几个实例来看看是怎么做到的:
![拍子源 2 长度 0.25 循环 3 的卡带效果](../images/vfx-witch.gif)
能看到其中一个单发拍子拍下空格之后蓝条是**反复闪烁了3次**的,这就是循环的作用;而这三次闪烁之间的**时间间隔均为0.25拍**,这就是长度的作用;循环的是该小节**第2拍起头时的画面**,这就是拍子源的作用。
![拍子源 1 长度 0.25 循环 7 的卡带效果 + 拍子源 3 长度 0.5 循环 1 的卡带效果](../images/vfx-electronicgirlrotate.gif)
这里的音乐段是一个密集的鼓点,于是就按照鼓点的节奏同步地设计了卡带效果,并且反复。这个卡带的位置刚好放置了一个轨道的旋转,进而做到了轨道卡壳转不动的效果。
这似乎也给了我们一个很好的提示:卡带效果往往都是和音乐中的配器节奏同步的,画面跟随着音乐一起卡才能卡在一个最爽的位置。密集的采音往往本身也就不适合用来做节奏,将其转化为卡带效果反而能够出奇制胜。
## 设置速度
**设置速度**事件修改的是画面的播放速度,但注意,音乐速度并不会跟着改变,改变的只有设置主题里的动画速度,平铺背景的移动速度,所有带有“动画时长”设置的事件的变化速度等。
其中带有“动画时长”设置的事件(例如轨道移动,浮动文字)是要特别注意的,例如你填写了动画时长为`2拍`,同时又设置速度为`2倍`,那么该事件就在1拍的时间里完成了。
设置速度事件可以填写小数,并且最低可以修改为`0`。当速度为0时画面就会静止,但很邪门的是轨道上的人物和节奏脉冲是对此免疫的,要注意考虑好是否隐藏这些轨道以免造成违和感。
![频繁地设置速度为 0 与正常值交替带来卡机效果](../images/vfx-electronicgirlglich.gif)
## 预设特效的多重叠合
很多预设特效都自带一点画面干扰的倾向,而将这些效果叠加就能加剧干扰效果,如果再叠加上一节所述的镜厅效果则会更加一发不可收拾。堆预设特效可以玩玩,但也要适度。
除镜厅外,放克特效也是要谨慎使用的,过大的饱和度会让眼部急剧不适,往往可以放在整个场景的最底层空区域进行一个小面积适度的铺设。
下面举几个例子:
**竖直滚屏+VHS+电影噪点+高光**
带来信号干扰、丢失的感觉
**顶部镜厅+摄像头/房间动画**
旋转,跳跃,残影,你画面拉出了完美的拖尾
**屏幕翻转+颜色反转+滚屏**
画面你别乱跑
**短暂的噪点/干扰**
默数拍子开启
**放克+落雨+灰度+慢游戏速度**
听话,别把灰度去掉
**25%白色前景闪烁+暴风雪+雪花+VHS+关闭竖直滚屏+电影噪点+JPEG失真+落雨+快游戏速度**
最后的绝望(《冰与火之舞》 “XH-X 最后的希望”类似效果)
## 镜像
+72
View File
@@ -0,0 +1,72 @@
# 视觉干扰
> 在关卡中出现对比度较高画面快速交替,如红蓝、黑白快速闪烁,必须开启癫痫警告。使用“放克”特效,必须开启癫痫警告。使用“干扰”特效较多,建议开启癫痫警告。一秒出现3次以上快速闪烁,建议开启癫痫警告。
> 即使开启了癫痫警告,也不要设计出会伤害视力的干扰效果。
## 综述
视觉干扰效果算是节奏医生做谱的一大特色了。因为游戏玩法本身是可以做到纯音押的,所以在视觉上对玩家进行考验不仅可以增大难度,同时又可以有很新奇的观赏效果。在剧情模式中,视觉干扰主要集中在`1-X 东方失眠夜``1-XN 超·东方失眠夜`两关,其余还有关卡的小部分环节用到了视觉干扰,效果都极具震撼。
需要注意的是,**视觉干扰不等于读谱不能**,更不等于塞爆。这些干扰是为重复或单一的节奏增添趣味与挑战性而添加的,虽然一定意义上增加了读谱难度,但是仍应当给玩家留有恰当的反应时间。如果节奏设计本身就有难度,还刻意阻挡玩家进行识谱,效果将会是适得其反的。
另外,视觉干扰设计的主要原则依然是采音。音乐具有这样的特色,且不好转变为轨道节奏的话,就把这部分采音对应到视觉的同步变化和卡顿,完美地解决节奏设计与画面设计两个问题。
## 卡带效果
如果你对剧情关卡`1-X`东方不眠夜还有印象的话,或许能回忆起节奏配合着音乐一卡一卡的效果,这就是靠**卡带效果**做到的,它可以让心跳在某一拍卡住。
![](../images/vfx-settings.jpg)
这样看图似乎也不够直观,我们举几个实例来看看是怎么做到的:
![拍子源 2 长度 0.25 循环 3 的卡带效果](../images/vfx-witch.gif)
能看到其中一个单发拍子拍下空格之后蓝条是**反复闪烁了3次**的,这就是循环的作用;而这三次闪烁之间的**时间间隔均为0.25拍**,这就是长度的作用;循环的是该小节**第2拍起头时的画面**,这就是拍子源的作用。
![拍子源 1 长度 0.25 循环 7 的卡带效果 + 拍子源 3 长度 0.5 循环 1 的卡带效果](../images/vfx-electronicgirlrotate.gif)
这里的音乐段是一个密集的鼓点,于是就按照鼓点的节奏同步地设计了卡带效果,并且反复。这个卡带的位置刚好放置了一个轨道的旋转,进而做到了轨道卡壳转不动的效果。
这似乎也给了我们一个很好的提示:卡带效果往往都是和音乐中的配器节奏同步的,画面跟随着音乐一起卡才能卡在一个最爽的位置。密集的采音往往本身也就不适合用来做节奏,将其转化为卡带效果反而能够出奇制胜。
## 设置速度
**设置速度**事件修改的是画面的播放速度,但注意,音乐速度并不会跟着改变,改变的只有设置主题里的动画速度,平铺背景的移动速度,所有带有“动画时长”设置的事件的变化速度等。
其中带有“动画时长”设置的事件(例如轨道移动,浮动文字)是要特别注意的,例如你填写了动画时长为`2拍`,同时又设置速度为`2倍`,那么该事件就在1拍的时间里完成了。
设置速度事件可以填写小数,并且最低可以修改为`0`。当速度为0时画面就会静止,但很邪门的是轨道上的人物和节奏脉冲是对此免疫的,要注意考虑好是否隐藏这些轨道以免造成违和感。
![频繁地设置速度为 0 与正常值交替带来卡机效果](../images/vfx-electronicgirlglich.gif)
## 预设特效的多重叠合
很多预设特效都自带一点画面干扰的倾向,而将这些效果叠加就能加剧干扰效果,如果再叠加上一节所述的镜厅效果则会更加一发不可收拾。堆预设特效可以玩玩,但也要适度。
除镜厅外,放克特效也是要谨慎使用的,过大的饱和度会让眼部急剧不适,往往可以放在整个场景的最底层空区域进行一个小面积适度的铺设。
下面举几个例子:
**竖直滚屏+VHS+电影噪点+高光**
带来信号干扰、丢失的感觉
**顶部镜厅+摄像头/房间动画**
旋转,跳跃,残影,你画面拉出了完美的拖尾
**屏幕翻转+颜色反转+滚屏**
画面你别乱跑
**短暂的噪点/干扰**
默数拍子开启
**放克+落雨+灰度+慢游戏速度**
听话,别把灰度去掉
**25%白色前景闪烁+暴风雪+雪花+VHS+关闭竖直滚屏+电影噪点+JPEG失真+落雨+快游戏速度**
最后的绝望(《冰与火之舞》 “XH-X 最后的希望”类似效果)
Binary file not shown.
Binary file not shown.
+253
View File
@@ -0,0 +1,253 @@
{ "frames": [
{
"filename": "0.ase",
"frame": { "x": 0, "y": 0, "w": 327, "h": 160 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 327, "h": 160 },
"sourceSize": { "w": 327, "h": 160 },
"duration": 100
}
],
"meta": {
"app": "https://www.aseprite.org/",
"version": "1.3.16-beta3-x64",
"image": "assets.png",
"format": "RGBA8888",
"size": { "w": 327, "h": 160 },
"scale": "1",
"slices": [
{ "name": "event_SpinningRows", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 246, "y": 56, "w": 14, "h": 14 } }] },
{ "name": "event_SetMainWindow", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 246, "y": 42, "w": 14, "h": 14 } }] },
{ "name": "event_RenameWindow", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 246, "y": 28, "w": 14, "h": 14 } }] },
{ "name": "event_DesktopColor_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 249, "y": 20, "w": 8, "h": 5 }, "pivot": {"x": -3, "y": -6 } }] },
{ "name": "event_DesktopColor", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 232, "y": 28, "w": 14, "h": 14 } }] },
{ "name": "event_HideWindow", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 232, "y": 14, "w": 14, "h": 14 } }] },
{ "name": "event_ReorderWindows_3", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 162, "y": 84, "w": 14, "h": 14 } }] },
{ "name": "event_ReorderWindows_2", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 162, "y": 70, "w": 14, "h": 14 } }] },
{ "name": "event_ReorderWindows_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 162, "y": 56, "w": 14, "h": 14 } }] },
{ "name": "event_ReorderWindows_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 162, "y": 42, "w": 14, "h": 14 } }] },
{ "name": "event_ReorderWindows", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 162, "y": 42, "w": 14, "h": 56 } }] },
{ "name": "event_ReorderRooms_3", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 148, "y": 84, "w": 14, "h": 14 } }] },
{ "name": "event_ReorderRooms_2", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 148, "y": 70, "w": 14, "h": 14 } }] },
{ "name": "event_ReorderRooms_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 148, "y": 56, "w": 14, "h": 14 } }] },
{ "name": "event_ReorderRooms_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 148, "y": 42, "w": 14, "h": 14 } }] },
{ "name": "event_CustomFlash_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 190, "y": 56, "w": 14, "h": 14 } }] },
{ "name": "event_MacroEvent", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 78, "y": 84, "w": 14, "h": 14 } }] },
{ "name": "event_ForwardEvent", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 64, "y": 84, "w": 14, "h": 14 } }] },
{ "name": "event_ForwardDecorationEvent", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 106, "y": 70, "w": 14, "h": 14 } }] },
{ "name": "event_ForwardRowEvent", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 92, "y": 70, "w": 14, "h": 14 } }] },
{ "name": "event_SetWindowContent", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 78, "y": 56, "w": 14, "h": 14 } }] },
{ "name": "event_WindowResize", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 64, "y": 56, "w": 14, "h": 14 } }] },
{ "name": "event_Tile", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 120, "y": 56, "w": 14, "h": 14 } }] },
{ "name": "event_Blend", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 56, "w": 14, "h": 14 } }] },
{ "name": "event_ReorderSprite", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 106, "y": 56, "w": 14, "h": 14 } }] },
{ "name": "event_ShakeScreenCustom", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 232, "y": 42, "w": 14, "h": 14 } }] },
{ "name": "event_ReorderRow", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 92, "y": 56, "w": 14, "h": 14 } }] },
{ "name": "event_NarrateRowInfo", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 176, "y": 84, "w": 14, "h": 14 } }] },
{ "name": "event_ReadNarration", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 190, "y": 0, "w": 14, "h": 14 } }] },
{ "name": "tab_icon_sounds", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 35, "y": 0, "w": 15, "h": 13 } }] },
{ "name": "tab_color_sounds", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 22, "y": 39, "w": 2, "h": 13 } }] },
{ "name": "content_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 80, "y": 106, "w": 5, "h": 5 }, "center": {"x": 2, "y": 2, "w": 1, "h": 1 } }] },
{ "name": "tab_icon_rows", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 0, "y": 13, "w": 15, "h": 13 } }] },
{ "name": "tab_icon_actions", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 0, "y": 26, "w": 15, "h": 13 } }] },
{ "name": "tab_icon_rooms", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 0, "y": 39, "w": 15, "h": 13 } }] },
{ "name": "tab_icon_decorations", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 0, "y": 52, "w": 15, "h": 13 } }] },
{ "name": "tab_icon_windows", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 0, "y": 65, "w": 15, "h": 13 } }] },
{ "name": "tab_color_rows", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 24, "y": 39, "w": 2, "h": 13 } }] },
{ "name": "tab_color_actions", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 26, "y": 39, "w": 2, "h": 13 } }] },
{ "name": "tab_color_rooms", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 28, "y": 39, "w": 2, "h": 13 } }] },
{ "name": "tab_color_decorations", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 30, "y": 39, "w": 2, "h": 13 } }] },
{ "name": "tab_color_windows", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 32, "y": 39, "w": 2, "h": 13 } }] },
{ "name": "tab_color_unknown", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 34, "y": 39, "w": 2, "h": 13 } }] },
{ "name": "tab_icon_unknown", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 0, "y": 78, "w": 15, "h": 13 } }] },
{ "name": "content_2", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 85, "y": 105, "w": 7, "h": 7 }, "center": {"x": 3, "y": 3, "w": 1, "h": 1 } }] },
{ "name": "event_Comment", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 84, "w": 14, "h": 14 } }] },
{ "name": "event_ReorderRooms", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 148, "y": 42, "w": 14, "h": 56 } }] },
{ "name": "event_SetCrotchetsPerBar", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 78, "y": 0, "w": 14, "h": 14 } }] },
{ "name": "event_PlaySong", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 0, "w": 28, "h": 14 } }] },
{ "name": "event_PlaySound", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 190, "y": 70, "w": 14, "h": 14 } }] },
{ "name": "event_SetBeatsPerMinute", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 218, "y": 42, "w": 14, "h": 14 } }] },
{ "name": "event_SetClapSounds", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 176, "y": 42, "w": 14, "h": 14 } }] },
{ "name": "event_SetHeartExplodeVolume", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 134, "y": 84, "w": 14, "h": 14 } }] },
{ "name": "event_SetHeartExplodeInterval", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 134, "y": 0, "w": 14, "h": 14 } }] },
{ "name": "event_SetGameSound", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 148, "y": 0, "w": 14, "h": 14 } }] },
{ "name": "event_SetBeatSound", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 162, "y": 0, "w": 14, "h": 14 } }] },
{ "name": "event_SetCountingSound", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 176, "y": 0, "w": 14, "h": 14 } }] },
{ "name": "event_SetOneshotWave", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 78, "y": 14, "w": 14, "h": 14 } }] },
{ "name": "event_AddFreeTimeBeat", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 225, "y": 0, "w": 7, "h": 14 } }] },
{ "name": "event_PulseFreeTimeBeat", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 232, "y": 0, "w": 7, "h": 12 } }] },
{ "name": "event_SetTheme", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 28, "w": 14, "h": 14 } }] },
{ "name": "event_SetVFXPreset", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 190, "y": 84, "w": 14, "h": 14 } }] },
{ "name": "event_SetForeground", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 134, "y": 70, "w": 14, "h": 14 } }] },
{ "name": "event_SetBackgroundColor", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 134, "y": 42, "w": 14, "h": 14 } }] },
{ "name": "event_SetSpeed", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 204, "y": 84, "w": 14, "h": 14 } }] },
{ "name": "event_Flash", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 190, "y": 42, "w": 14, "h": 14 } }] },
{ "name": "event_CustomFlash", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 204, "y": 42, "w": 14, "h": 14 } }] },
{ "name": "event_NewWindowDance", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 70, "w": 14, "h": 14 } }] },
{ "name": "event_MoveCamera", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 176, "y": 56, "w": 14, "h": 14 } }] },
{ "name": "event_PulseCamera", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 120, "y": 42, "w": 14, "h": 14 } }] },
{ "name": "event_TextExplosion", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 134, "y": 28, "w": 14, "h": 14 } }] },
{ "name": "event_ShowDialogue", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 148, "y": 28, "w": 14, "h": 14 } }] },
{ "name": "event_ShowStatusSign", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 162, "y": 28, "w": 14, "h": 14 } }] },
{ "name": "event_AdvanceText", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 218, "y": 0, "w": 7, "h": 14 } }] },
{ "name": "event_TintRows", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 92, "y": 0, "w": 14, "h": 14 } }] },
{ "name": "event_Tint", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 106, "y": 0, "w": 14, "h": 14 } }] },
{ "name": "event_TagAction", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 162, "y": 14, "w": 14, "h": 14 } }] },
{ "name": "event_Stutter", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 78, "y": 42, "w": 14, "h": 14 } }] },
{ "name": "event_ShowHands", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 78, "y": 70, "w": 14, "h": 14 } }] },
{ "name": "event_ShakeScreen", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 204, "y": 14, "w": 14, "h": 14 } }] },
{ "name": "event_SetVisible", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 106, "y": 42, "w": 14, "h": 14 } }] },
{ "name": "event_SetRoomPerspective", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 64, "y": 42, "w": 14, "h": 14 } }] },
{ "name": "event_SetRoomContentMode", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 120, "y": 70, "w": 14, "h": 14 } }] },
{ "name": "event_SetPlayStyle", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 148, "y": 14, "w": 14, "h": 14 } }] },
{ "name": "event_SetHandOwner", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 134, "y": 14, "w": 14, "h": 14 } }] },
{ "name": "event_PaintHands", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 120, "y": 1, "w": 14, "h": 14 } }] },
{ "name": "event_PlayExpression", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 106, "y": 84, "w": 14, "h": 14 } }] },
{ "name": "event_MoveRoom", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 42, "w": 14, "h": 14 } }] },
{ "name": "event_MaskRoom", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 78, "y": 28, "w": 14, "h": 14 } }] },
{ "name": "event_MoveRow", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 204, "y": 70, "w": 14, "h": 14 } }] },
{ "name": "event_InvertColors", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 218, "y": 14, "w": 14, "h": 14 } }] },
{ "name": "event_HideRow", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 92, "y": 42, "w": 14, "h": 14 } }] },
{ "name": "event_FlipScreen_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 218, "y": 70, "w": 14, "h": 14 } }] },
{ "name": "event_FinishLevel", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 190, "y": 28, "w": 14, "h": 14 } }] },
{ "name": "event_ChangePlayersRows", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 176, "y": 28, "w": 14, "h": 14 } }] },
{ "name": "event_BassDrop", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 190, "y": 14, "w": 14, "h": 14 } }] },
{ "name": "event_CallCustomMethod", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 176, "y": 14, "w": 14, "h": 14 } }] },
{ "name": "event_PlayAnimation", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 92, "y": 84, "w": 14, "h": 14 } }] },
{ "name": "event_Move", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 176, "y": 70, "w": 14, "h": 14 } }] },
{ "name": "event_FadeRoom", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 64, "y": 28, "w": 14, "h": 14 } }] },
{ "name": "event_Unknown", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 64, "y": 70, "w": 14, "h": 14 } }] },
{ "name": "themes", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 15, "y": 39, "w": 7, "h": 13 } }] },
{ "name": "event_beat_pulse", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 98, "w": 3, "h": 14 }, "pivot": {"x": 1, "y": 0 } }] },
{ "name": "event_beat_hit", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 53, "y": 98, "w": 5, "h": 14 }, "pivot": {"x": 2, "y": 0 } }] },
{ "name": "event_beat_x", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 84, "y": 98, "w": 9, "h": 7 } }] },
{ "name": "char_0021", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 54, "y": 112, "w": 2, "h": 8 } }] },
{ "name": "char_0022", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 56, "y": 112, "w": 4, "h": 8 } }] },
{ "name": "char_0023", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 60, "y": 112, "w": 6, "h": 8 } }] },
{ "name": "char_0024", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 66, "y": 112, "w": 5, "h": 8 } }] },
{ "name": "char_0025", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 71, "y": 112, "w": 6, "h": 8 } }] },
{ "name": "char_0026", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 77, "y": 112, "w": 6, "h": 8 } }] },
{ "name": "char_0027", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 83, "y": 112, "w": 2, "h": 8 } }] },
{ "name": "char_0028", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 85, "y": 112, "w": 3, "h": 8 } }] },
{ "name": "char_0029", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 88, "y": 112, "w": 3, "h": 8 } }] },
{ "name": "char_002a", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 91, "y": 112, "w": 4, "h": 8 } }] },
{ "name": "char_002b", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 95, "y": 112, "w": 4, "h": 8 } }] },
{ "name": "char_002c", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 99, "y": 112, "w": 3, "h": 8 } }] },
{ "name": "char_002d", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 102, "y": 112, "w": 4, "h": 8 } }] },
{ "name": "char_002e", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 106, "y": 112, "w": 2, "h": 8 } }] },
{ "name": "char_002f", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 108, "y": 112, "w": 6, "h": 8 } }] },
{ "name": "char_0030", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 120, "w": 5, "h": 8 } }] },
{ "name": "char_0031", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 55, "y": 120, "w": 3, "h": 8 } }] },
{ "name": "char_0032", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 58, "y": 120, "w": 5, "h": 8 } }] },
{ "name": "char_0033", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 63, "y": 120, "w": 5, "h": 8 } }] },
{ "name": "char_0034", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 68, "y": 120, "w": 5, "h": 8 } }] },
{ "name": "char_0035", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 73, "y": 120, "w": 5, "h": 8 } }] },
{ "name": "char_0036", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 78, "y": 120, "w": 5, "h": 8 } }] },
{ "name": "char_0037", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 83, "y": 120, "w": 5, "h": 8 } }] },
{ "name": "char_0038", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 88, "y": 120, "w": 5, "h": 8 } }] },
{ "name": "char_0039", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 93, "y": 120, "w": 5, "h": 8 } }] },
{ "name": "char_003a", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 98, "y": 120, "w": 2, "h": 8 } }] },
{ "name": "char_003b", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 100, "y": 120, "w": 2, "h": 8 } }] },
{ "name": "char_003c", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 102, "y": 120, "w": 4, "h": 8 } }] },
{ "name": "char_003d", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 106, "y": 120, "w": 4, "h": 8 } }] },
{ "name": "char_003e", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 110, "y": 120, "w": 4, "h": 8 } }] },
{ "name": "char_003f", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 114, "y": 120, "w": 5, "h": 8 } }] },
{ "name": "char_0040", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 128, "w": 6, "h": 8 } }] },
{ "name": "char_0041", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 56, "y": 128, "w": 5, "h": 8 } }] },
{ "name": "char_0042", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 61, "y": 128, "w": 5, "h": 8 } }] },
{ "name": "char_0043", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 66, "y": 128, "w": 4, "h": 8 } }] },
{ "name": "char_0044", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 70, "y": 128, "w": 5, "h": 8 } }] },
{ "name": "char_0045", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 75, "y": 128, "w": 4, "h": 8 } }] },
{ "name": "char_0046", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 79, "y": 128, "w": 4, "h": 8 } }] },
{ "name": "char_0047", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 83, "y": 128, "w": 5, "h": 8 } }] },
{ "name": "char_0048", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 88, "y": 128, "w": 5, "h": 8 } }] },
{ "name": "char_0049", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 93, "y": 128, "w": 4, "h": 8 } }] },
{ "name": "char_004a", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 97, "y": 128, "w": 5, "h": 8 } }] },
{ "name": "char_004b", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 102, "y": 128, "w": 5, "h": 8 } }] },
{ "name": "char_004c", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 107, "y": 128, "w": 4, "h": 8 } }] },
{ "name": "char_004d", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 111, "y": 128, "w": 6, "h": 8 } }] },
{ "name": "char_004e", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 117, "y": 128, "w": 5, "h": 8 } }] },
{ "name": "char_004f", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 122, "y": 128, "w": 5, "h": 8 } }] },
{ "name": "char_0050", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 136, "w": 5, "h": 8 } }] },
{ "name": "char_0051", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 55, "y": 136, "w": 5, "h": 8 } }] },
{ "name": "char_0052", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 60, "y": 136, "w": 5, "h": 8 } }] },
{ "name": "char_0053", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 65, "y": 136, "w": 5, "h": 8 } }] },
{ "name": "char_0054", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 70, "y": 136, "w": 4, "h": 8 } }] },
{ "name": "char_0055", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 74, "y": 136, "w": 5, "h": 8 } }] },
{ "name": "char_0056", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 79, "y": 136, "w": 5, "h": 8 } }] },
{ "name": "char_0057", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 84, "y": 136, "w": 6, "h": 8 } }] },
{ "name": "char_0058", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 90, "y": 136, "w": 5, "h": 8 } }] },
{ "name": "char_0059", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 95, "y": 136, "w": 5, "h": 8 } }] },
{ "name": "char_005a", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 100, "y": 136, "w": 4, "h": 8 } }] },
{ "name": "char_005b", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 104, "y": 136, "w": 3, "h": 8 } }] },
{ "name": "char_005c", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 107, "y": 136, "w": 6, "h": 8 } }] },
{ "name": "char_005d", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 113, "y": 136, "w": 3, "h": 8 } }] },
{ "name": "char_005e", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 116, "y": 136, "w": 4, "h": 8 } }] },
{ "name": "char_005f", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 120, "y": 136, "w": 5, "h": 8 } }] },
{ "name": "char_0060", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 144, "w": 3, "h": 8 } }] },
{ "name": "char_0061", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 53, "y": 144, "w": 5, "h": 8 } }] },
{ "name": "char_0062", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 58, "y": 144, "w": 5, "h": 8 } }] },
{ "name": "char_0063", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 63, "y": 144, "w": 4, "h": 8 } }] },
{ "name": "char_0064", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 67, "y": 144, "w": 5, "h": 8 } }] },
{ "name": "char_0065", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 72, "y": 144, "w": 5, "h": 8 } }] },
{ "name": "char_0066", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 77, "y": 144, "w": 4, "h": 8 } }] },
{ "name": "char_0067", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 81, "y": 144, "w": 5, "h": 8 } }] },
{ "name": "char_0068", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 86, "y": 144, "w": 5, "h": 8 } }] },
{ "name": "char_0069", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 91, "y": 144, "w": 2, "h": 8 } }] },
{ "name": "char_006a", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 93, "y": 144, "w": 3, "h": 8 } }] },
{ "name": "char_006b", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 96, "y": 144, "w": 5, "h": 8 } }] },
{ "name": "char_006c", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 101, "y": 144, "w": 2, "h": 8 } }] },
{ "name": "char_006d", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 103, "y": 144, "w": 6, "h": 8 } }] },
{ "name": "char_006e", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 109, "y": 144, "w": 5, "h": 8 } }] },
{ "name": "char_006f", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 114, "y": 144, "w": 5, "h": 8 } }] },
{ "name": "char_0070", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 152, "w": 5, "h": 8 } }] },
{ "name": "char_0071", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 55, "y": 152, "w": 5, "h": 8 } }] },
{ "name": "char_0072", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 60, "y": 152, "w": 4, "h": 8 } }] },
{ "name": "char_0073", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 64, "y": 152, "w": 5, "h": 8 } }] },
{ "name": "char_0074", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 69, "y": 152, "w": 4, "h": 8 } }] },
{ "name": "char_0075", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 73, "y": 152, "w": 5, "h": 8 } }] },
{ "name": "char_0076", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 78, "y": 152, "w": 5, "h": 8 } }] },
{ "name": "char_0077", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 83, "y": 152, "w": 6, "h": 8 } }] },
{ "name": "char_0078", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 89, "y": 152, "w": 4, "h": 8 } }] },
{ "name": "char_0079", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 93, "y": 152, "w": 5, "h": 8 } }] },
{ "name": "char_007a", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 98, "y": 152, "w": 5, "h": 8 } }] },
{ "name": "char_007b", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 103, "y": 152, "w": 4, "h": 8 } }] },
{ "name": "char_007c", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 107, "y": 152, "w": 2, "h": 8 } }] },
{ "name": "char_007d", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 109, "y": 152, "w": 4, "h": 8 } }] },
{ "name": "char_007e", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 113, "y": 152, "w": 5, "h": 8 } }] },
{ "name": "char_0020", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 112, "w": 4, "h": 8 } }] },
{ "name": "event_tag", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 239, "y": 0, "w": 6, "h": 6 } }] },
{ "name": "event_tag_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 239, "y": 6, "w": 6, "h": 6 } }] },
{ "name": "event_beat_loop", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 75, "y": 98, "w": 9, "h": 8 }, "pivot": {"x": 5, "y": 4 } }] },
{ "name": "event_beat_cross", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 92, "y": 108, "w": 3, "h": 3 }, "pivot": {"x": 1, "y": -6 } }] },
{ "name": "event_beat_hit_burn", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 63, "y": 98, "w": 7, "h": 14 }, "pivot": {"x": 3, "y": 0 } }] },
{ "name": "event_beat_synco", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 93, "y": 98, "w": 9, "h": 7 } }] },
{ "name": "event_beat_hit_freeze", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 58, "y": 98, "w": 5, "h": 14 }, "pivot": {"x": 2, "y": 0 } }] },
{ "name": "event_beat_skip", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 70, "y": 98, "w": 5, "h": 14 } }] },
{ "name": "event_beat_area", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 95, "y": 105, "w": 3, "h": 4 }, "center": {"x": 0, "y": 1, "w": 2, "h": 2 } }] },
{ "name": "event_beat_line", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 102, "y": 98, "w": 9, "h": 7 } }] },
{ "name": "event_CustomFlash_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 204, "y": 56, "w": 14, "h": 14 } }] },
{ "name": "event_FlipScreen_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 232, "y": 56, "w": 14, "h": 14 } }] },
{ "name": "event_FlipScreen", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 218, "y": 56, "w": 14, "h": 14 } }] },
{ "name": "event_FlipScreen_2", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 232, "y": 70, "w": 14, "h": 14 } }] },
{ "name": "event_FloatingText_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 204, "y": 28, "w": 14, "h": 14 } }] },
{ "name": "event_FloatingText_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 218, "y": 28, "w": 14, "h": 14 } }] },
{ "name": "event_PaintHands_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 120, "y": 14, "w": 14, "h": 14 } }] },
{ "name": "event_PaintHands_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 120, "y": 28, "w": 14, "h": 14 } }] },
{ "name": "event_SetBackgroundColor_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 134, "y": 56, "w": 14, "h": 14 } }] },
{ "name": "event_SetBackgroundColor_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 137, "y": 60, "w": 8, "h": 6 }, "pivot": {"x": -3, "y": -4 } }] },
{ "name": "event_SetForeground_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 137, "y": 74, "w": 7, "h": 5 }, "pivot": {"x": -3, "y": -4 } }] },
{ "name": "event_Tint_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 106, "y": 14, "w": 14, "h": 14 } }] },
{ "name": "event_Tint_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 106, "y": 28, "w": 14, "h": 14 } }] },
{ "name": "event_TintRows_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 92, "y": 14, "w": 14, "h": 14 } }] },
{ "name": "event_TintRows_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 92, "y": 28, "w": 14, "h": 14 } }] },
{ "name": "event_ShowRooms_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 162, "y": 98, "w": 28, "h": 28 } }] },
{ "name": "event_ShowRooms_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 134, "y": 98, "w": 28, "h": 28 } }] },
{ "name": "event_ChangeCharacter", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 120, "y": 84, "w": 14, "h": 14 } }] },
{ "name": "event_SetRowXs", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 14, "w": 28, "h": 14 } }] },
{ "name": "event_outline", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 75, "y": 106, "w": 5, "h": 5 }, "center": {"x": 2, "y": 2, "w": 1, "h": 1 } }] },
{ "name": "event_back", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 92, "y": 105, "w": 3, "h": 3 }, "center": {"x": 1, "y": 1, "w": 1, "h": 1 } }] }
]
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

+31
View File
@@ -0,0 +1,31 @@
const customMethods = [
{ type: 'mod',}
]
const editDistance = (a, b) => {
if (a.length === 0) return b.length;
if (b.length === 0) return a.length;
const matrix = [];
for (let i = 0; i <= b.length; i++) {
matrix[i] = [i];
}
for (let j = 0; j <= a.length; j++) {
matrix[0][j] = j;
}
for (let i = 1; i <= b.length; i++) {
for (let j = 1; j <= a.length; j++) {
if (b.charAt(i - 1) === a.charAt(j - 1)) {
matrix[i][j] = matrix[i - 1][j - 1];
} else {
matrix[i][j] = Math.min(
matrix[i - 1][j - 1] + 1,
Math.min(matrix[i][j - 1] + 1, matrix[i - 1][j] + 1),
);
}
}
}
return matrix[b.length][a.length];
}
+32
View File
@@ -0,0 +1,32 @@
class CustomMethods{
type: "mod"|"surgery"|"comment"|"custom_method";
}
function editDistance(a: String, b: String): number {
if (a.length === 0) return b.length;
if (b.length === 0) return a.length;
const matrix: number[][] = [];
for (let i = 0; i <= b.length; i++) {
matrix[i] = [i];
}
for (let j = 0; j <= a.length; j++) {
matrix[0][j] = j;
}
for (let i = 1; i <= b.length; i++) {
for (let j = 1; j <= a.length; j++) {
if (b.charAt(i - 1) === a.charAt(j - 1)) {
matrix[i][j] = matrix[i - 1][j - 1];
} else {
matrix[i][j] = Math.min(
matrix[i - 1][j - 1] + 1,
Math.min(matrix[i][j - 1] + 1, matrix[i - 1][j] + 1),
);
}
}
}
return matrix[b.length][a.length];
}
export { editDistance };
+1560
View File
File diff suppressed because it is too large Load Diff
+79
View File
@@ -0,0 +1,79 @@
import { createElementEvent } from "./rdtkview.js";
export function render(data, width, height, scale = 2.0) {
const canvas = document.createElement("div");
let objs = [];
try {
objs = JSON.parse(`[${data}]`);
canvas.innerHTML = "";
} catch (e) {
canvas.innerHTML =
`<div style="color: red; font-weight: bold;">JSON解析错误:${e.message}</div>`;
return canvas;
}
const eventStyle = { "scale": scale, "showDuration": false };
const elems = [];
for (let obj of objs) {
const style = { ...eventStyle, enabled: obj.active ?? true };
const elem = createElementEvent(obj, style);
if (!elem) continue;
elem.eventStyle = style;
elem.style.position = "absolute";
elem.style.left = `${
((((obj.bar ?? 1) - 1) * 8) + (obj.beat ?? 1) - 1) * 14 *
scale
}px`;
elem.style.top = `${(obj.y ?? obj.row ?? 0) * 14 * scale}px`;
elem.addEventListener("mousedown", (event) => {
const eStyle = elem.eventStyle;
eStyle.active = true;
elem.onStateChange(eStyle);
});
elem.addEventListener("mouseover", (event) => {
const eStyle = elem.eventStyle;
eStyle.hover = true;
elem.onStateChange(eStyle);
});
elem.addEventListener("mouseout", (event) => {
const eStyle = elem.eventStyle;
eStyle.hover = false;
eStyle.active = false;
elem.onStateChange(eStyle);
});
elem.addEventListener("mouseup", (event) => {
const eStyle = elem.eventStyle;
eStyle.active = false;
elem.onStateChange(eStyle);
});
elems.push(elem);
}
canvas.style.position = "relative";
canvas.style.width = `${width * 14 * scale}px`;
canvas.style.height = `${height * 14 * scale}px`;
elems.forEach((elem) => {
canvas.appendChild(elem);
});
return canvas;
}
window.$docsify.plugins = [].concat(window.$docsify.plugins, (hook) => {
hook.doneEach(() => {
const pres = document.querySelectorAll("pre");
pres.forEach((codeBlock) => {
const lang = codeBlock.getAttribute("data-lang") || "";
if (lang.startsWith("rdtkview")) {
const code = codeBlock.querySelector("code").innerText || "";
const args = lang.slice(8).trim().split(" ");
const width = parseInt(args[0]) || 8;
const height = parseInt(args[1]) || 4;
const scale = parseFloat(args[2]) || 2.0;
const result = render(code, width, height, scale);
const parent = document.createElement("div");
parent.style.width = 100 + "%";
parent.style.display = "flex";
parent.style.justifyContent = "center";
parent.appendChild(result);
codeBlock.replaceWith(parent);
}
});
});
});
+4 -1
View File
@@ -849,6 +849,9 @@ function ReadProperties(reader, event, pairs) {
if (value = FindValue(pairs, "loop")) {
event.BeatStyle.Loop = parseInt(value.Value);
}
if (value = FindValue(pairs, "hold")) {
event.BeatStyle.Hold = parseFloat(value.Value);
}
break;
default:
break;
@@ -938,7 +941,7 @@ function ConstructDivObject(obj) {
result += (((_a = obj.BeatStyle) === null || _a === void 0 ? void 0 : _a.RowXs[i]) === 'x') ? `<div class="x"></div>` : `<div></div>`;
}
return result;
}], [(obj.BeatType === BeatsSpecial.AddClassicBeat || obj.BeatType === BeatsSpecial.AddFreeTimeBeat || obj.BeatType === BeatsSpecial.PulseFreeTimeBeat) && ((_s = (_r = obj.BeatStyle) === null || _r === void 0 ? void 0 : _r.Hold) !== null && _s !== void 0 ? _s : 0) > 0, `holdbeat`, () => ''], [obj.BeatType === BeatsSpecial.AddOneshotBeat && obj.BeatStyle !== undefined && obj.BeatStyle.OneshotBeatSubType.includes(RDOneshotBeatSubType.Skipshot), `skipshot`, () => ''])}</div>`;
}], [(obj.BeatType === BeatsSpecial.AddClassicBeat || obj.BeatType === BeatsSpecial.AddFreeTimeBeat || obj.BeatType === BeatsSpecial.PulseFreeTimeBeat || obj.BeatType === BeatsSpecial.AddOneshotBeat) && ((_s = (_r = obj.BeatStyle) === null || _r === void 0 ? void 0 : _r.Hold) !== null && _s !== void 0 ? _s : 0) > 0, `holdbeat`, () => ''], [obj.BeatType === BeatsSpecial.AddOneshotBeat && obj.BeatStyle !== undefined && obj.BeatStyle.OneshotBeatSubType.includes(RDOneshotBeatSubType.Skipshot), `skipshot`, () => ''])}</div>`;
}
else if (obj instanceof RDGroup) {
return `<div class="event group"style="${ConstructCssPropertiesIfExists(new Map([
+4 -1
View File
@@ -829,6 +829,9 @@ function ReadProperties(reader: Reader, event: RDEvent | RDGroup, pairs: KeyValu
if (value = FindValue(pairs, "loop")) {
event.BeatStyle.Loop = parseInt(value.Value);
}
if (value = FindValue(pairs, "hold")) {
event.BeatStyle.Hold = parseFloat(value.Value);
}
break;
default:
break;
@@ -925,7 +928,7 @@ function ConstructDivObject(obj: RDEvent | RDGroup): string {
}
return result;
}],
[(obj.BeatType === BeatsSpecial.AddClassicBeat || obj.BeatType === BeatsSpecial.AddFreeTimeBeat || obj.BeatType === BeatsSpecial.PulseFreeTimeBeat) && (obj.BeatStyle?.Hold ?? 0) > 0, `holdbeat`, () => ''],
[(obj.BeatType === BeatsSpecial.AddClassicBeat || obj.BeatType === BeatsSpecial.AddFreeTimeBeat || obj.BeatType === BeatsSpecial.PulseFreeTimeBeat || obj.BeatType === BeatsSpecial.AddOneshotBeat) && (obj.BeatStyle?.Hold ?? 0) > 0, `holdbeat`, () => ''],
[obj.BeatType === BeatsSpecial.AddOneshotBeat && obj.BeatStyle !== undefined && obj.BeatStyle.OneshotBeatSubType.includes(RDOneshotBeatSubType.Skipshot), `skipshot`, () => ''],
)}</div>`;
}
+243 -57
View File
@@ -1,3 +1,5 @@
import { createElementEvent } from "./rdtkview.js";
let curx = 0;
let cury = 0;
let rowx;
@@ -21,7 +23,7 @@ let positions = {
"r5": { "y": 78, "name": "二轨时的第二轨/四轨时的第二轨" },
"r6": { "y": 57, "name": "三轨时的第一轨" },
"r7": { "y": 36, "name": "四轨时的第一轨" },
}
};
function themePosition() {
let theme_positions = document.getElementById("theme-positions");
@@ -61,45 +63,74 @@ function themePosition() {
rowx = null;
columny = null;
for (let key in positions) {
if (positions[key].x !== null && Math.abs(x - positions[key].x) < 5)
if (
positions[key].x !== null && Math.abs(x - positions[key].x) < 5
) {
rowx = positions[key].x;
if (positions[key].y !== null && Math.abs(y - positions[key].y) < 5)
}
if (
positions[key].y !== null && Math.abs(y - positions[key].y) < 5
) {
columny = positions[key].y;
}
}
if (rowx) {
perx.innerText = (rowx / 3.52).toFixed(2) + "%"
perx.classList.add("c")
pxx.innerText = rowx + "px"
pxx.classList.add("c")
}
else {
perx.innerText = x_percent.toFixed(2) + "%"
perx.classList.remove("c")
pxx.innerText = x + "px"
pxx.classList.remove("c")
perx.innerText = (rowx / 3.52).toFixed(2) + "%";
perx.classList.add("c");
pxx.innerText = rowx + "px";
pxx.classList.add("c");
} else {
perx.innerText = x_percent.toFixed(2) + "%";
perx.classList.remove("c");
pxx.innerText = x + "px";
pxx.classList.remove("c");
}
if (columny) {
pery.innerText = (100 - columny / 1.98).toFixed(2) + "%"
pery.classList.add("c")
pxy.innerText = 198 - columny + "px"
pxy.classList.add("c")
}
else {
pery.innerText = (100 - y_percent).toFixed(2) + "%"
pery.classList.remove("c")
pxy.innerText = 198 - y + "px"
pxy.classList.remove("c")
pery.innerText = (100 - columny / 1.98).toFixed(2) + "%";
pery.classList.add("c");
pxy.innerText = 198 - columny + "px";
pxy.classList.add("c");
} else {
pery.innerText = (100 - y_percent).toFixed(2) + "%";
pery.classList.remove("c");
pxy.innerText = 198 - y + "px";
pxy.classList.remove("c");
}
infobox.style.right = "calc(" + (100 - x_percent) + "% + 10px)";
infobox.style.top = "calc(" + (y_percent) + "% + 10px)";
selectbox.style.left = rowx ? (rowx / 3.52 - 3.41) + "%" : columny ? "0" : "calc(" + x_percent + "% - 3px";
selectbox.style.bottom = columny ? (100 - columny / 1.98 - 5.305) + "%" : rowx ? "0" : "calc(" + (100 - y_percent) + "% - 3px)";
infobox.style.top = "calc(" + y_percent + "% + 10px)";
selectbox.style.left = rowx
? (rowx / 3.52 - 3.41) + "%"
: columny
? "0"
: "calc(" + x_percent + "% - 3px";
selectbox.style.bottom = columny
? (100 - columny / 1.98 - 5.305) + "%"
: rowx
? "0"
: "calc(" + (100 - y_percent) + "% - 3px)";
selectbox.style.width = rowx ? "6.82%" : columny ? "100%" : "6px";
selectbox.style.height = columny ? "10.61%" : rowx ? "100%" : "6px";
let rowname = rowx ? positions[Object.keys(positions).find(key => positions[key].x === rowx)].name : "";
let columnname = columny ? positions[Object.keys(positions).find(key => positions[key].y === columny)].name : "";
theme_positions.querySelector(".other").innerText = rowname && columnname ? columnname + "上的" + rowname : rowname ? rowname : columnname ? columnname : "";
let rowname = rowx
? positions[
Object.keys(positions).find((key) => positions[key].x === rowx)
].name
: "";
let columnname = columny
? positions[
Object.keys(positions).find((key) =>
positions[key].y === columny
)
].name
: "";
theme_positions.querySelector(".other").innerText =
rowname && columnname
? columnname + "上的" + rowname
: rowname
? rowname
: columnname
? columnname
: "";
});
theme_positions.addEventListener("mouseleave", function (event) {
perx.innerText = "100%";
@@ -112,13 +143,12 @@ function themePosition() {
selectbox.style.bottom = "50%";
selectbox.style.width = "0";
selectbox.style.height = "0";
perx.classList.remove("c")
pery.classList.remove("c")
pxx.classList.remove("c")
pxy.classList.remove("c")
perx.classList.remove("c");
pery.classList.remove("c");
pxx.classList.remove("c");
pxy.classList.remove("c");
other.innerText = "";
});
}
function rdview() {
@@ -129,21 +159,25 @@ function rdview() {
let number = rdview.querySelector(".number");
const textareaStyles = window.getComputedStyle(textarea);
[
'fontFamily', 'fontSize', 'fontWeight',
'letterSpacing', 'lineHeight', 'padding',
].forEach(property => {
"fontFamily",
"fontSize",
"fontWeight",
"letterSpacing",
"lineHeight",
"padding",
].forEach((property) => {
number.style[property] = textareaStyles[property];
});
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
const font = `${textareaStyles.fontSize} ${textareaStyles.fontFamily}`;
context.font = font;
function calcStringLines(sentence, width) {
if (!width) return 0;
const words = sentence.split('');
const words = sentence.split("");
let lineCount = 0;
let currentLine = '';
let currentLine = "";
for (let i = 0; i < words.length; i++) {
const wordWidth = context.measureText(words[i]).width;
const lineWidth = context.measureText(currentLine).width;
@@ -154,18 +188,22 @@ function rdview() {
currentLine += words[i];
}
}
if (currentLine.trim() !== '') lineCount++;
if (currentLine.trim() !== "") lineCount++;
return lineCount;
}
function calcLines() {
const lines = textarea.value.split('\n');
const lines = textarea.value.split("\n");
const textareaWidth = textarea.getBoundingClientRect().width;
const textareaScrollWidth = textareaWidth - textarea.clientWidth;
const parseNumber = (v) => v.endsWith('px') ? parseInt(v.slice(0, -2), 10) : 0;
const parseNumber = (v) =>
v.endsWith("px") ? parseInt(v.slice(0, -2), 10) : 0;
const textareaPaddingLeft = parseNumber(textareaStyles.paddingLeft);
const textareaPaddingRight = parseNumber(textareaStyles.paddingRight);
const textareaContentWidth = textareaWidth - textareaPaddingLeft - textareaPaddingRight - textareaScrollWidth;
const numLines = lines.map(lineString => calcStringLines(lineString, textareaContentWidth));
const textareaContentWidth = textareaWidth - textareaPaddingLeft -
textareaPaddingRight - textareaScrollWidth;
const numLines = lines.map((lineString) =>
calcStringLines(lineString, textareaContentWidth)
);
let lineNumbers = [];
let i = 1;
while (numLines.length > 0) {
@@ -173,8 +211,8 @@ function rdview() {
lineNumbers.push(i);
if (numLinesOfSentence > 1) {
Array(numLinesOfSentence - 1)
.fill('')
.forEach((_) => lineNumbers.push(''));
.fill("")
.forEach((_) => lineNumbers.push(""));
}
i++;
}
@@ -184,24 +222,172 @@ function rdview() {
const lines = calcLines();
const lineDoms = Array.from({
length: lines.length,
}, (_, i) => `<div>${lines[i] || '&nbsp;'}</div>`);
number.innerHTML = lineDoms.join('');
}, (_, i) => `<div>${lines[i] || "&nbsp;"}</div>`);
number.innerHTML = lineDoms.join("");
}
function initCanvas() {
const lang = textarea.value.split('\n')[0]
const code = textarea.value.split('\n').slice(1).join('\n')
rdcanvas.innerHTML = RDViewRender(lang, code)
const lang = textarea.value.split("\n")[0];
const code = textarea.value.split("\n").slice(1).join("\n");
rdcanvas.innerHTML = RDViewRender(lang, code);
}
initCanvas()
initLineNumbers()
textarea.addEventListener('input', initLineNumbers);
textarea.addEventListener('input', initCanvas);
initCanvas();
initLineNumbers();
textarea.addEventListener("input", initLineNumbers);
textarea.addEventListener("input", initCanvas);
}
function rdview2() {
let rdview = document.getElementsByClassName("rdview2")[0];
if (!rdview) return;
let rdcanvas = rdview.querySelector(".canvas");
let textarea = rdview.querySelector("textarea.area");
let number = rdview.querySelector(".number");
const textareaStyles = window.getComputedStyle(textarea);
[
"fontFamily",
"fontSize",
"fontWeight",
"letterSpacing",
"lineHeight",
"padding",
].forEach((property) => {
number.style[property] = textareaStyles[property];
});
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
const font = `${textareaStyles.fontSize} ${textareaStyles.fontFamily}`;
context.font = font;
function calcStringLines(sentence, width) {
if (!width) return 0;
const words = sentence.split("");
let lineCount = 0;
let currentLine = "";
for (let i = 0; i < words.length; i++) {
const wordWidth = context.measureText(words[i]).width;
const lineWidth = context.measureText(currentLine).width;
if (lineWidth + wordWidth > width) {
lineCount++;
currentLine = words[i];
} else {
currentLine += words[i];
}
}
if (currentLine.trim() !== "") lineCount++;
return lineCount;
}
function calcLines() {
const lines = textarea.value.split("\n");
const textareaWidth = textarea.getBoundingClientRect().width;
const textareaScrollWidth = textareaWidth - textarea.clientWidth;
const parseNumber = (v) =>
v.endsWith("px") ? parseInt(v.slice(0, -2), 10) : 0;
const textareaPaddingLeft = parseNumber(textareaStyles.paddingLeft);
const textareaPaddingRight = parseNumber(textareaStyles.paddingRight);
const textareaContentWidth = textareaWidth - textareaPaddingLeft -
textareaPaddingRight - textareaScrollWidth;
const numLines = lines.map((lineString) =>
calcStringLines(lineString, textareaContentWidth)
);
let lineNumbers = [];
let i = 1;
while (numLines.length > 0) {
const numLinesOfSentence = numLines.shift();
lineNumbers.push(i);
if (numLinesOfSentence > 1) {
Array(numLinesOfSentence - 1)
.fill("")
.forEach((_) => lineNumbers.push(""));
}
i++;
}
return lineNumbers;
}
function initLineNumbers() {
const lines = calcLines();
const lineDoms = Array.from({
length: lines.length,
}, (_, i) => `<div>${lines[i] || "&nbsp;"}</div>`);
number.innerHTML = lineDoms.join("");
}
function initCanvas() {
let objs = [];
try {
objs = JSON.parse(`[${textarea.value}]`);
rdcanvas.innerHTML = "";
} catch (e) {
rdcanvas.innerHTML =
`<div style="color: red; font-weight: bold;">JSON解析错误:${e.message}</div>`;
return;
}
const eventStyle = { "scale": 2.0, "showDuration": false };
let maxy = 0;
const elemPromises = [];
for (let obj of objs) {
const style = { ...eventStyle, enabled: obj.active ?? true };
const elem = createElementEvent(obj, style).then((elem) => {
elem.eventStyle = style;
elem.style.position = "absolute";
elem.style.left = `${
((((obj.bar ?? 1) - 1) * 8) + (obj.beat ?? 1) - 1) * 14 *
eventStyle.scale
}px`;
elem.style.top = `${
(obj.y ?? obj.row ?? 0) * 14 * eventStyle.scale
}px`;
if (
((obj.y ?? obj.row ?? 0) * 14 * eventStyle.scale) +
elem.offsetHeight > maxy
) {
maxy = ((obj.y ?? obj.row ?? 0) * 14 * eventStyle.scale) +
elem.offsetHeight;
}
elem.addEventListener("mousedown", (event) => {
const eStyle = elem.eventStyle;
eStyle.active = true;
elem.onStateChange(eStyle);
});
elem.addEventListener("mouseover", (event) => {
const eStyle = elem.eventStyle;
eStyle.hover = true;
elem.onStateChange(eStyle);
});
elem.addEventListener("mouseout", (event) => {
const eStyle = elem.eventStyle;
eStyle.hover = false;
eStyle.active = false;
elem.onStateChange(eStyle);
});
elem.addEventListener("mouseup", (event) => {
const eStyle = elem.eventStyle;
eStyle.active = false;
elem.onStateChange(eStyle);
});
return elem;
});
elemPromises.push(elem);
}
Promise.all(elemPromises).then((elems) => {
elems.forEach((elem) => {
rdcanvas.appendChild(elem);
});
});
rdcanvas.style.position = "relative";
rdcanvas.style.height = `${maxy + 4 * 14 * eventStyle.scale}px`;
}
initCanvas();
initLineNumbers();
textarea.addEventListener("input", initLineNumbers);
textarea.addEventListener("input", initCanvas);
}
window.$docsify.plugins = [].concat(window.$docsify.plugins, function (hook) {
hook.doneEach(function () {
themePosition();
rdview();
rdview2();
document.documentElement.scrollTop = document.body.scrollTop = 0;
});
});
import("./docsify.min.js").then(() => {
});
+11 -6
View File
@@ -19,16 +19,17 @@ const themeModes = ['light', 'dark', 'auto',]
var switchSpan = document.createElement('span')
switchSpan.id = 'switchLightDarkModeDivBeforeArticle'
switchSpan.classList.add('controlSpan')
switchSpan.style.position = 'fixed'
switchSpan.style.right = switchLightDarkModeOptions.right.toString() + 'px'
switchSpan.style.top = switchLightDarkModeOptions.top.toString() + 'px'
const lightModeIconXml = '<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="' + switchLightDarkModeOptions.svgColor + '"><path d="M12 18a6 6 0 100-12 6 6 0 000 12zM22 12h1M12 2V1M12 23v-1M20 20l-1-1M20 4l-1 1M4 20l1-1M4 4l1 1M1 12h1" stroke="' + switchLightDarkModeOptions.svgColor + '" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>'
const darkModeIconXml = '<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="' + switchLightDarkModeOptions.svgColor + '"><path d="M3 11.507a9.493 9.493 0 0018 4.219c-8.507 0-12.726-4.22-12.726-12.726A9.494 9.494 0 003 11.507z" stroke="' + switchLightDarkModeOptions.svgColor + '" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>'
const autoModeIconXml = '<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="' + switchLightDarkModeOptions.svgColor + '"><path d="M3 15c2.483 0 4.345-3 4.345-3s1.862 3 4.345 3c2.482 0 4.965-3 4.965-3s2.483 3 4.345 3M3 20c2.483 0 4.345-3 4.345-3s1.862 3 4.345 3c2.482 0 4.965-3 4.965-3s2.483 3 4.345 3M19 10a7 7 0 10-14 0" stroke="' + switchLightDarkModeOptions.svgColor + '" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>'
const zoomInIconXml = '<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg" color="' + switchLightDarkModeOptions.svgColor + '"><path d="M8 11h3m3 0h-3m0 0V8m0 3v3M17 17l4 4M3 11a8 8 0 1016 0 8 8 0 00-16 0z" stroke="' + switchLightDarkModeOptions.svgColor + '" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>'
const zoomOutIconXml = '<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg" color="' + switchLightDarkModeOptions.svgColor + '"><path d="M17 17l4 4M3 11a8 8 0 1016 0 8 8 0 00-16 0zM8 11h6" stroke="' + switchLightDarkModeOptions.svgColor + '" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>'
const zoomDefaultIconXml = '<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="' + switchLightDarkModeOptions.svgColor + '"><path d="M12 19a7 7 0 100-14 7 7 0 000 14zM12 19v2M5 12H3M12 5V3M19 12h2" stroke="' + switchLightDarkModeOptions.svgColor + '" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>'
const lightModeIconXml = '<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="' + switchLightDarkModeOptions.svgColor + '"><path d="M12 18a6 6 0 100-12 6 6 0 000 12zM22 12h1M12 2V1M12 23v-1M20 20l-1-1M20 4l-1 1M4 20l1-1M4 4l1 1M1 12h1" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>'
const darkModeIconXml = '<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="' + switchLightDarkModeOptions.svgColor + '"><path d="M3 11.507a9.493 9.493 0 0018 4.219c-8.507 0-12.726-4.22-12.726-12.726A9.494 9.494 0 003 11.507z" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>'
const autoModeIconXml = '<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="' + switchLightDarkModeOptions.svgColor + '"><path d="M3 15c2.483 0 4.345-3 4.345-3s1.862 3 4.345 3c2.482 0 4.965-3 4.965-3s2.483 3 4.345 3M3 20c2.483 0 4.345-3 4.345-3s1.862 3 4.345 3c2.482 0 4.965-3 4.965-3s2.483 3 4.345 3M19 10a7 7 0 10-14 0" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>'
const zoomInIconXml = '<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg" color="' + switchLightDarkModeOptions.svgColor + '"><path d="M8 11h3m3 0h-3m0 0V8m0 3v3M17 17l4 4M3 11a8 8 0 1016 0 8 8 0 00-16 0z" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>'
const zoomOutIconXml = '<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg" color="' + switchLightDarkModeOptions.svgColor + '"><path d="M17 17l4 4M3 11a8 8 0 1016 0 8 8 0 00-16 0zM8 11h6" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>'
const zoomDefaultIconXml = '<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="' + switchLightDarkModeOptions.svgColor + '"><path d="M12 19a7 7 0 100-14 7 7 0 000 14zM12 19v2M5 12H3M12 5V3M19 12h2" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>'
const ottoIconXml = `
<?xml version="1.0" encoding="UTF-8"?>
<svg width="26px" height="30px" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 24 24" color="` + switchLightDarkModeOptions.svgColor + `" stroke="` + switchLightDarkModeOptions.svgColor + `" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
@@ -125,6 +126,7 @@ function plugin(hook, vm) {
var zoomInSpan = document.createElement('span')
zoomInSpan.id = 'zoomInSpan'
zoomInSpan.classList.add('controlSpan')
zoomInSpan.style.position = 'fixed'
zoomInSpan.style.right = switchLightDarkModeOptions.right.toString() + 'px'
zoomInSpan.style.top = (switchLightDarkModeOptions.top + 35).toString() + 'px'
@@ -132,6 +134,7 @@ function plugin(hook, vm) {
var zoomOutSpan = document.createElement('span')
zoomOutSpan.id = 'zoomOutSpan'
zoomOutSpan.classList.add('controlSpan')
zoomOutSpan.style.position = 'fixed'
zoomOutSpan.style.right = switchLightDarkModeOptions.right.toString() + 'px'
zoomOutSpan.style.top = (switchLightDarkModeOptions.top + 70).toString() + 'px'
@@ -139,6 +142,7 @@ function plugin(hook, vm) {
var zoomDefaultSpan = document.createElement('span')
zoomDefaultSpan.id = 'zoomDefaultSpan'
zoomDefaultSpan.classList.add('controlSpan')
zoomDefaultSpan.style.position = 'fixed'
zoomDefaultSpan.style.right = switchLightDarkModeOptions.right.toString() + 'px'
zoomDefaultSpan.style.top = (switchLightDarkModeOptions.top + 105).toString() + 'px'
@@ -146,6 +150,7 @@ function plugin(hook, vm) {
var ottoSpan = document.createElement('span')
ottoSpan.id = 'ottoSpan'
ottoSpan.classList.add('controlSpan')
ottoSpan.style.position = 'fixed'
ottoSpan.style.right = switchLightDarkModeOptions.right.toString() + 'px'
ottoSpan.style.top = (switchLightDarkModeOptions.top + 140).toString() + 'px'
Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 B

After

Width:  |  Height:  |  Size: 129 B

+15
View File
@@ -1291,4 +1291,19 @@ del {
margin: 0;
border-radius: 5px;
font: 300 12px 'd9c', 'd9';
}
.controlSpan {
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-family: 'd9', sans-serif;
font-size: 16px;
height: 30px;
width: 30px;
transition: background-color 0.3s, transform 0.2s;
z-index: 20;
}
+7
View File
@@ -223,4 +223,11 @@ div.medium-zoom-overlay{
&>p{
background-color: var(--background-color);
}
}
.controlSpan{
background-color: var(--span-color);
&>svg{
stroke: var(--span-fill-color);
}
}
+6 -3
View File
@@ -1,12 +1,12 @@
body.dark {
--main-color: #c8c8c8;
--main-theme-color: #008080;
--main-theme-color: #3c7e7e;
--background-color: #1f1f1f;
--background-border-color: #303030;
--section-main-color: #0f0f0f;
--section-background-color: #003333;
--section-background-color: #2c3333;
--section-table-header-border-color: #303030;
--section-blockquote-background-color: #003a3a;
--section-blockquote-background-color: #2a3131;
--section-blockquote-color: #7cdcfe;
--section-tip-background-color: #161616;
--section-tip-color: #3f3f3fcc;
@@ -20,6 +20,9 @@ body.dark {
-webkit-tap-highlight-color: rgb(0, 0, 0);
--special-theme-position-backgound-color: #177500;
--span-color: #2020203a;
--span-fill-color: #3c7e7e;
}
body.dark .sidebar li>a:has(>img) {
+3
View File
@@ -20,6 +20,9 @@ body.light {
-webkit-tap-highlight-color: rgb(255, 255, 255);
--special-theme-position-backgound-color: #05a000;
--span-color: #e0e0e03a;
--span-fill-color: #008585;
}
body.light .sidebar li>a:has(>img) {
+60
View File
@@ -1146,6 +1146,36 @@
}
}
&>.beat:not(:has(.classicbeat)) {
&>div.holdbeat {
position: absolute;
width: calc((var(--hold) * 28 - 2) * 1px);
height: inherit;
background-size: auto 100%;
background-image: url(./assets/beats/hold-area.png);
transform: translate(calc(((var(--tick) + var(--delay) + var(--loop) * var(--interval)) * 28 - 4) * 1px), 0);
z-index: -2;
&::after {
content: '';
position: absolute;
width: 2px;
height: 28px;
background-size: auto 100%;
transform: translate(calc((var(--hold) * 28 - 2) * 1px), 0);
background-image: url(./assets/beats/hold-right.png);
}
}
&:active>div.holdbeat {
background-image: url(./assets/beats/hold-hover-area.png);
&::after {
background-image: url(./assets/beats/hold-hover-right.png);
}
}
}
&>.beat:has(.row-xs) {
width: 56px;
height: 28px;
@@ -2180,6 +2210,36 @@
}
}
&>.beat:not(:has(.classicbeat)) {
&>div.holdbeat {
position: absolute;
width: calc((var(--hold) * 28 - 2) * 1px);
height: inherit;
background-size: auto 100%;
background-image: url(./assets/beats/hold-area.png);
transform: translate(calc(((var(--tick) + var(--delay) + var(--loop) * var(--interval)) * 28 - 4) * 1px), 0);
z-index: -2;
&::after {
content: '';
position: absolute;
width: 2px;
height: 28px;
background-size: auto 100%;
transform: translate(calc((var(--hold) * 28 - 2) * 1px), 0);
background-image: url(./assets/beats/hold-right.png);
}
}
&:active>div.holdbeat {
background-image: url(./assets/beats/hold-hover-area.png);
&::after {
background-image: url(./assets/beats/hold-hover-right.png);
}
}
}
&>.beat:has(.row-xs) {
width: 56px;
height: 28px;
+19 -1
View File
@@ -2,6 +2,24 @@
--line-width: 1px;
}
div.qqgroup{
height: 80px;
display: flex;
justify-self: center;
position: relative;
&>img{
}
&>p{
container: qqgroup;
position: absolute;
left: 5%;
top: 19%;
font-size: 23px;
resize: both;
color: #3b8e59;
}
}
div.theme-positions {
position: relative;
display: flex;
@@ -144,7 +162,7 @@ div.theme-positions>.infobox {
.markdown-section:has(div.rdview) {}
div.rdview {
div.rdview, div.rdview2 {
& div.canvas {
width: 100%;
}