Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d77bad610 | ||
|
|
b3579bbd07 | ||
|
|
3828811b3f | ||
|
|
a606de738a | ||
|
|
3c8733312c | ||
|
|
2b9a5a008c | ||
|
|
39c0db4373 | ||
|
|
05ae18d2ff | ||
|
|
a51b4fea03 | ||
|
|
98b5707c60 | ||
|
|
d6bbec8601 | ||
|
|
d62a6164a0 | ||
|
|
38fa5cffcc | ||
|
|
dfb2c9cf4e | ||
|
|
08b0b338b4 | ||
|
|
74a156ab43 | ||
|
|
e61c719989 | ||
|
|
a8162f59df | ||
|
|
74e4ec7ef3 | ||
|
|
58ee445c39 | ||
|
|
22ea4b8319 | ||
|
|
bfd781a545 | ||
|
|
661cf0ff74 | ||
|
|
3928730839 | ||
|
|
c446bd296c | ||
|
|
accc3e46cf | ||
|
|
54a4b7fdc1 | ||
|
|
b44f808592 | ||
|
|
3b3a6d4090 | ||
|
|
d9f1b2c3a4 | ||
|
|
6cd73fd1bd | ||
|
|
13ece539ec | ||
|
|
6f386c1cf2 | ||
|
|
867738bf7a | ||
|
|
f7dfd312d3 | ||
|
|
8b4877724e | ||
|
|
4e6cc59300 | ||
|
|
caf38e002f | ||
|
|
83da1be318 | ||
|
|
1425d1b512 | ||
|
|
cd72af4043 | ||
|
|
38010a85e9 | ||
|
|
e12b104c8b | ||
|
|
dac8579656 | ||
|
|
d125e827f3 | ||
|
|
76b48c3b95 | ||
|
|
479da74bfa | ||
|
|
05c3417439 | ||
|
|
fe639f79eb | ||
|
|
4014df39e5 | ||
|
|
8b55914845 | ||
|
|
ecb95f3e8e | ||
|
|
550045f5f8 | ||
|
|
ff60b5fe12 | ||
|
|
73ef185ba3 | ||
|
|
28fb3b4a88 | ||
|
|
757ce6b6ed | ||
|
|
d82f49dbec | ||
|
|
7f58583cff | ||
|
|
be23ad1d29 | ||
|
|
c7e9e3da13 | ||
|
|
c595870e06 | ||
|
|
3568004db6 | ||
|
|
93985cea1d | ||
|
|
c512c2ff3f | ||
|
|
9c6ef4e9e3 | ||
|
|
981b70c402 | ||
|
|
0f3bed36d9 | ||
|
|
850d7d8d0f | ||
|
|
42afb16b45 | ||
|
|
70feff6119 | ||
|
|
0ead33329e | ||
|
|
d6ed934b17 | ||
|
|
2a90886246 | ||
|
|
3e3bf39c2d | ||
|
|
d27a29e380 | ||
|
|
a974916f0e | ||
|
|
9f9717bc36 | ||
|
|
921df2e863 | ||
|
|
3e6434fe82 | ||
|
|
9477fa57e0 | ||
|
|
2cff4abbc2 | ||
|
|
072dea2b7b | ||
|
|
e49584a412 | ||
|
|
9f14397c63 | ||
|
|
fc1e839f48 | ||
|
|
b1f7dfe11d | ||
|
|
04d1af58f9 | ||
|
|
b5cbb3c588 | ||
|
|
68179a4d4d | ||
|
|
f19a7890ea | ||
|
|
345aca09ac | ||
|
|
659e01b30c | ||
|
|
3ff383764a | ||
|
|
99350e298c | ||
|
|
1a66c90022 | ||
|
|
76c272bfbe | ||
|
|
ccd55c84dd | ||
|
|
f9f067cc5f | ||
|
|
375193eec3 | ||
|
|
e67ec51cae | ||
|
|
c3068c312d | ||
|
|
0392d8f6ee | ||
|
|
81276cd83d | ||
|
|
9bc6730408 | ||
|
|
69e9535c68 | ||
|
|
484bad3ebc | ||
|
|
b53b86e9dc | ||
|
|
a21261ebca | ||
|
|
7ce70aff8f | ||
|
|
cf678ff1a2 | ||
|
|
4d28adc6a9 | ||
|
|
c28cf7605d | ||
|
|
72830302e8 | ||
|
|
7c229153a9 | ||
|
|
38a17ad35d | ||
|
|
4b842c721b | ||
|
|
70026114d8 | ||
|
|
455bb82550 | ||
|
|
1bff68aac5 | ||
|
|
6820dfc2ae | ||
|
|
7acdc7fed0 | ||
|
|
14f97502f0 | ||
|
|
6d3d02c5e2 | ||
|
|
0e26fea056 | ||
|
|
318f6bbcda | ||
|
|
a8c833c96f | ||
|
|
4a07b0eaf4 | ||
|
|
29b30c6782 | ||
|
|
b5b68b0c25 | ||
|
|
97a7697f66 | ||
|
|
6a2da287d8 | ||
|
|
922b5e1334 | ||
|
|
3a4ae62e66 | ||
|
|
594ffce2f1 | ||
|
|
a6a1420368 | ||
|
|
beb5385e25 | ||
|
|
64b612088c | ||
|
|
9336f789c1 | ||
|
|
c6ac6e5396 | ||
|
|
16207c03c5 | ||
|
|
67550f329d | ||
|
|
e115480491 | ||
|
|
1761283ca9 | ||
|
|
b6bec98286 | ||
|
|
12271b6943 | ||
|
|
a11aefd96d | ||
|
|
e92dc48e60 | ||
|
|
df07dde9c2 | ||
|
|
356893dcc3 | ||
|
|
b0d3f214d5 | ||
|
|
8bf2044e42 | ||
|
|
7eb77c3cba | ||
|
|
4d022a39de | ||
|
|
20e0f2b278 | ||
|
|
8140e2e156 | ||
|
|
ab1210ae23 | ||
|
|
dda3903f3f | ||
|
|
a1cb8f9adb | ||
|
|
1695f4ba59 | ||
|
|
64dc297141 | ||
|
|
0cf3e6a1d1 | ||
|
|
f8e616b048 | ||
|
|
daaf8c6604 | ||
|
|
e1aaae4067 | ||
|
|
4830fbf791 | ||
|
|
95e3205fcb | ||
|
|
c4f1e9190d | ||
|
|
9b2fefd482 | ||
|
|
34d10aacdc | ||
|
|
f6bb7c4656 | ||
|
|
f63a57d1b7 | ||
|
|
37843725da | ||
|
|
c3f78823a1 | ||
|
|
6088ac31a8 | ||
|
|
5fdf71d1e9 | ||
|
|
86bf9b876d | ||
|
|
36eec64a04 | ||
|
|
1d93e2140f | ||
|
|
a2f8775659 | ||
|
|
8bced361fe | ||
|
|
4c493ca9b3 | ||
|
|
e75daf1b5e | ||
|
|
a4531febd3 | ||
|
|
74c9014c5f | ||
|
|
d1d5926747 | ||
|
|
fa8dbd7d27 | ||
|
|
14975bc31c | ||
|
|
c8d61ba5b7 | ||
|
|
bd7480e686 | ||
|
|
852d8e719d | ||
|
|
e1dc15a5a7 | ||
|
|
5e426d9261 | ||
|
|
e7646d59b5 | ||
|
|
4463ba1b87 | ||
|
|
1115099a29 | ||
|
|
449d800bae | ||
|
|
ec2ab12898 | ||
|
|
f2b0c3a33e | ||
|
|
46fbe848d3 | ||
|
|
5555e612b3 | ||
|
|
e23b6000c4 | ||
|
|
c8bc990412 | ||
|
|
aedf303e89 | ||
|
|
6a433657f6 | ||
|
|
64fe405d2e | ||
|
|
f18d0974ac | ||
|
|
51207f501f | ||
|
|
4d7e2961f8 | ||
|
|
a26095bea2 | ||
|
|
a6711f859f | ||
|
|
d6e5ff39e3 | ||
|
|
f315aa9f2e | ||
|
|
92a39d05ad | ||
|
|
2792202ac5 | ||
|
|
1d8825da77 | ||
|
|
f4dee6f3c6 | ||
|
|
7300fbfa16 | ||
|
|
8486bd807e | ||
|
|
41ada2cf46 | ||
|
|
8ee381909f | ||
|
|
ae9c93deb2 | ||
|
|
d922a6fae6 | ||
|
|
006e2f2ff1 | ||
|
|
c14a85c464 | ||
|
|
5aedbbfbe0 | ||
|
|
a14b4436f5 | ||
|
|
4e1e57b08e | ||
|
|
51e8b1f449 | ||
|
|
11846eb83e | ||
|
|
2b3e6404a4 | ||
|
|
f5e8b6d6f4 | ||
|
|
758645041b | ||
|
|
fb2e0e124b | ||
|
|
006a5fe4f5 | ||
|
|
1e4e94cce7 | ||
|
|
1024b31790 | ||
|
|
22558c6813 | ||
|
|
55c53278ea | ||
|
|
089f4c551d | ||
|
|
9a060eb6ff | ||
|
|
6b0da44786 | ||
|
|
50bef7ba6d | ||
|
|
6f8e88b93d | ||
|
|
0fecdf5b19 | ||
|
|
f51785f649 | ||
|
|
c1b00aa34d | ||
|
|
a01042af6a | ||
|
|
9d14a88a98 | ||
|
|
9714689690 | ||
|
|
dca868ac71 | ||
|
|
81b54f7fbd | ||
|
|
c467825ec1 | ||
|
|
91fed78ce1 | ||
|
|
9becdf3f88 | ||
|
|
547181bff1 | ||
|
|
052463645b | ||
|
|
2d6125b082 | ||
|
|
69165da834 | ||
|
|
90a764dd7f | ||
|
|
7c888f5249 | ||
|
|
214b7856bd | ||
|
|
d83cc5a829 | ||
|
|
837336a321 | ||
|
|
62c9b8517f | ||
|
|
7921ecc981 | ||
|
|
745dbaee3e | ||
|
|
e28eea0a77 | ||
|
|
517c75bb66 | ||
|
|
10db121ad7 | ||
|
|
d51204985f | ||
|
|
bc7518ba0b | ||
|
|
a0d296a818 | ||
|
|
bb0cb7de3a | ||
|
|
ae32b0e7aa | ||
|
|
dca2f87b4b | ||
|
|
7aa95ab0ba | ||
|
|
7a2e16d714 | ||
|
|
f588b3ce92 | ||
|
|
5d7d99b24c | ||
|
|
fdad67efee | ||
|
|
d2f80e8390 | ||
|
|
1884e5097e | ||
|
|
8faac81f8f | ||
|
|
718be9e9bf | ||
|
|
139f1eef71 | ||
|
|
4d37019e1a | ||
|
|
90af884c2c | ||
|
|
9114b1664b | ||
|
|
96a90c364d | ||
|
|
56e78752b2 | ||
|
|
f902bd4ec6 | ||
|
|
7c35d418c0 | ||
|
|
91737a0f95 | ||
|
|
520f68be8f | ||
|
|
ca02d2e195 | ||
|
|
4e92254eb8 | ||
|
|
30d84f613b | ||
|
|
5e92f750a6 | ||
|
|
4f08e1e53a | ||
|
|
1d9514bd7b | ||
|
|
ac39d732b7 | ||
|
|
c323edf184 | ||
|
|
239e15c01d | ||
|
|
bfa44b33c4 | ||
|
|
a702602ef5 | ||
|
|
fac884caf2 | ||
|
|
e3d6c8c572 | ||
|
|
5e91af323b | ||
|
|
c7b6c35ddc | ||
|
|
5dab36288b |
@@ -0,0 +1,69 @@
|
||||
项目综合授权条款
|
||||
1. 源代码与原创资源
|
||||
路径:
|
||||
所有源码文件、
|
||||
/indexicon/ 下的所有文件
|
||||
所有以下未提及部分
|
||||
授权:MIT License
|
||||
2. 文档内容
|
||||
路径:
|
||||
/pages/ 下的所有 .md 文件
|
||||
授权: Creative Commons Attribution-NonCommercial 4.0 International (CC-BY-NC 4.0)
|
||||
3. 其他作者的美术
|
||||
路径:
|
||||
/resources/ 下的所有文件
|
||||
/images/intro-qqgroup.png
|
||||
/images/otto-dark.gif
|
||||
/images/otto-light.gif
|
||||
/images/otto-puzzled-original.png
|
||||
/images/otto-puzzled.png
|
||||
/images/otto-rd.png
|
||||
/images/otto-rd2-1.png
|
||||
/images/otto-rd2-xmas-compressed.png
|
||||
/images/otto-rd2-xmas.png
|
||||
/images/otto-traditional.png
|
||||
/images/otto-wyym.png
|
||||
授权: Creative Commons Attribution-NonCommercial 4.0 International (CC-BY-NC 4.0)
|
||||
4. 受限游戏美术
|
||||
路径:
|
||||
/images/ 内的截图、临摹图
|
||||
授权:仅限本教程在线演示,禁止复制、再分发
|
||||
5. 商业字体
|
||||
字体文件未包含在仓库
|
||||
说明:已购个人授权,不可再分发;本地部署请另行购买或改用免费可商用字体
|
||||
Copyright (c) 2025 节奏医生饭制部制作组
|
||||
|
||||
Comprehensive License Notice
|
||||
1. Source Code & Original Assets
|
||||
Scope:
|
||||
All source files
|
||||
All files in /indexicon/
|
||||
All other unmentioned parts
|
||||
License: MIT License
|
||||
2. Documentation
|
||||
Scope:
|
||||
All .md files in /pages/
|
||||
License: Creative Commons Attribution-NonCommercial 4.0 International (CC-BY-NC 4.0)
|
||||
3. Other Authors' Art
|
||||
Scope:
|
||||
/resources/ directory
|
||||
/images/intro-qqgroup.png
|
||||
/images/otto-dark.gif
|
||||
/images/otto-light.gif
|
||||
/images/otto-puzzled-original.png
|
||||
/images/otto-puzzled.png
|
||||
/images/otto-rd.png
|
||||
/images/otto-rd2-1.png
|
||||
/images/otto-rd2-xmas-compressed.png
|
||||
/images/otto-rd2-xmas.png
|
||||
/images/otto-traditional.png
|
||||
/images/otto-wyym.png
|
||||
License: Creative Commons Attribution-NonCommercial 4.0 International (CC-BY-NC 4.0)
|
||||
4. Restricted Game Art
|
||||
Scope:
|
||||
Screenshots or derivative art in /images/
|
||||
License: Display-only for this tutorial; no copying or redistribution
|
||||
5. Commercial Fonts
|
||||
Font files are NOT included in the repository
|
||||
Note: personal license only; for local builds obtain separate license or replace with free-for-commercial-use fonts
|
||||
Copyright (c) 2025 节奏医生饭制部制作组
|
||||
@@ -1,20 +1,52 @@
|
||||
# 节奏医生中文编辑器教程网站
|
||||
|
||||
> 此版本网页正在维护。
|
||||
## 预览
|
||||
|
||||
# 节奏医生中文编辑器教程
|
||||
### [Visual Studio Code](https://code.visualstudio.com/)
|
||||
|
||||
《节奏医生》编辑器中文教程旨在以教学的形式帮助您快速了解编辑器的界面,基础功能,设计技巧和做谱规范。未经授权不得以图文,视频等形式转载,也不得以本教程内素材进行二次创作。
|
||||
此项目基于 [docsify](https://docsify.js.org/#/) 编辑,并使用 [RDView](https://github.com/OLDRedstone/RDView) 和 [RhythmBase.View(RDTKView)](https://github.com/OLDRedstone/RhythmBase.View) 显示编辑器可交互模块。
|
||||
可以参考以下多种方案预览编辑效果。
|
||||
|
||||
编辑器视频教程点击[此链接](https://www.bilibili.com/video/BV1pr4y1k7gP)。教程内所有演示关卡下载放置于[百度网盘](https://pan.baidu.com/s/1Tb6ywVmge25ztMFnpa6q_Q),提取码:rdlv。
|
||||
- [安装 docsify](https://docsify.js.org/#/quickstart) 以实时预览页面。
|
||||
|
||||
> 如果你看到[更新信息](/pages/changelog.md)增加了,但是又感觉什么也没更新,那就试着按一下`Ctrl + F5`,再不行就清空浏览器缓存。
|
||||
```bash
|
||||
npm i docsify-cli -g
|
||||
```
|
||||
|
||||
## 联系我们
|
||||
- 运行以下命令以启动本地服务器实时预览。
|
||||
|
||||

|
||||
```bash
|
||||
docsify s
|
||||
```
|
||||
|
||||
如果你有做谱相关的问题,或是对本教程有什么意见和建议,可以点击链接加入 QQ 群 [951070053](https://jq.qq.com/?_wv=1027&k=nsPA09E4) 告知我们。你也可以在群里上传谱面给我们试玩,群友们都会热心为你提供谱面优化建议。真诚欢迎各位做谱萌新和大佬的加入。
|
||||
- 在 Visual Studio Code 插件商店[安装 Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) 以预览。
|
||||
|
||||
(悄悄透露一句:官方也入驻了这个群哦~)
|
||||
### RDView
|
||||
|
||||
戳这只看板娘可以获得随机 TIPS →
|
||||
> ### 此条目即将废弃。
|
||||
> 请优先使用 RhythmBase.View 格式。
|
||||
|
||||
- [安装 markdown-rdview-support](https://github.com/OLDRedstone/markdown-rdview-support) 以预览 RDView 内容。
|
||||
如果成功安装,那么以下内容的 markdown 预览应当是一个事件栏。
|
||||
|
||||
```rdview 7 5 1
|
||||
es.PlaySong 0 0[];
|
||||
es.SetCrotchetsPerBar_4 0 1[];
|
||||
eb.AddClassicBeat 0 2[tick=6];
|
||||
```
|
||||
|
||||
### RhythmBase.View
|
||||
|
||||
RDView 的替代。
|
||||
可以直接使用关卡文件内格式进行展示。
|
||||
暂无计划支持 Visual Studio Code 内预览。(~~感觉没必要支持~~)
|
||||
可以访问[此处](https://view.obugs.cn/)以预览效果和获得额外属性说明。
|
||||
|
||||
## 编辑
|
||||
|
||||
请尽量使用 [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.
|
||||
@@ -1 +0,0 @@
|
||||
<!-- _navbar.md -->
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
margin: 0;
|
||||
& img{
|
||||
image-rendering: pixelated;
|
||||
width: 64px;
|
||||
height: 32px;
|
||||
}
|
||||
}
|
||||
@@ -11,39 +12,36 @@
|
||||
|
||||
- [<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/moreclassicbeats.png"/><p>普通拍子的衍生节奏型</p>](/pages/moreclassicbeats.md)
|
||||
- [<img src="/indexicon/moreoneshotbeats.png"/><p>单发拍子的衍生节奏型</p>](/pages/moreoneshotbeats.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)
|
||||
- [<img src="/indexicon/chartdesign.png"/><p>关卡设计</p>](/pages/chartdesign.md)
|
||||
- [<img src="/indexicon/audiodesign.png"/><p>音效设计</p>](/pages/audiodesign.md)
|
||||
- [<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=""/><p>视觉干扰</p>](/pages/vfxpro.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)
|
||||
@@ -51,7 +49,12 @@
|
||||
- [<img src="/indexicon/tag.png"/><p>标签</p>](/pages/tag.md)
|
||||
- [<img src="/indexicon/custommethod.png"/><p>自定义方法</p>](/pages/custommethod.md)
|
||||
- [<img src="/indexicon/condition.png"/><p>条件</p>](/pages/condition.md)
|
||||
- [<img src="/indexicon/variable.png"/><p>变量</p>](/pages/variable.md)
|
||||
- [<img src="/indexicon/variable.png"/><p>表达式</p>](/pages/expression.md)
|
||||
- [<img src="/indexicon/setplaystyleandgotolevel.png"/><p>关卡播放与跳转<p>](/pages/setplaystyleandgotolevel.md)
|
||||
- 高级:第三方工具
|
||||
- [<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="" 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)
|
||||
@@ -61,6 +64,5 @@
|
||||
- [<img src="/indexicon/custommethods.png"/><p>自定义方法表</p>](/pages/appendix_custommethods.md)
|
||||
- [<img src="/indexicon/specifications.png"/><p>制谱规范</p>](/pages/appendix_levelrules.md)
|
||||
- [<img src="/indexicon/comparison.png"/><p>英汉对照</p>](/pages/appendix_translations.md)
|
||||
- [<img src="/indexicon/coding.png"/><p>其他编写关卡的手段</p>](/pages/appendix_coding.md)
|
||||
- [<img src="/indexicon/tools.png" width="64px"/><p>工具</p>](/pages/appendix_tools.md)
|
||||
- [<img src="/indexicon/credits.png"/><p>制作人员</p>](/pages/credits.md)
|
||||
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 103 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 164 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 701 KiB |
|
After Width: | Height: | Size: 639 KiB |
|
After Width: | Height: | Size: 609 KiB |
|
After Width: | Height: | Size: 555 KiB |
|
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 135 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 244 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 216 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 2.3 MiB After Width: | Height: | Size: 4.9 MiB |
|
After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 105 KiB |
|
After Width: | Height: | Size: 92 KiB |
@@ -1,91 +1,118 @@
|
||||
<!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: true,
|
||||
coverpage: false,
|
||||
maxLevel: 5,
|
||||
subMaxLevel: 4,
|
||||
mergeNavbar: true,
|
||||
};
|
||||
</script>
|
||||
<script type="module">
|
||||
import '/script/rdview.js';
|
||||
function escapeHtml(unsafe) {
|
||||
return unsafe
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
}
|
||||
loadRDView()
|
||||
$docsify = {
|
||||
...$docsify,
|
||||
...{
|
||||
markdown: {
|
||||
renderer: {
|
||||
code: function (code, lang) {
|
||||
if (lang.trim().startsWith('rdview')) {
|
||||
return RDViewRender(lang, code);
|
||||
}
|
||||
return `<pre><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 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 type="module" src="/script/special.js"></script>
|
||||
</body>
|
||||
</script>
|
||||
<script type="module">
|
||||
import "./script/rdview.js";
|
||||
import {render} from "./script/rdtkview_render.js";
|
||||
|
||||
</html>
|
||||
function escapeHtml(unsafe) {
|
||||
return unsafe
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
}
|
||||
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>
|
||||
|
||||
|
After Width: | Height: | Size: 581 B |
|
After Width: | Height: | Size: 626 B |
|
After Width: | Height: | Size: 612 B |
|
Before Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 705 B |
|
After Width: | Height: | Size: 691 B |
|
After Width: | Height: | Size: 666 B |
|
After Width: | Height: | Size: 753 B |
@@ -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 文件。
|
||||
@@ -1,3 +1,4 @@
|
||||
[项目地址](https://github.com/RDCN-Community-Developers/CodeRD)
|
||||
# 代码编写关卡
|
||||
|
||||
点击[此处](../resources/compiler.exe)下载。项目作者:硫酸铜。项目来源:[PyRD - 为视障谱师写节奏医生谱子的一种全新的尝试](https://github.com/qwedc001/pyrd)。
|
||||
@@ -100,7 +101,7 @@ metadata:
|
||||
|
||||
- 对于 落雨/JPEG失真/马赛克/海底波浪/电影噪点/暴风雪/素描/色像差/模糊/径向模糊/色调偏移:强度,缓速时长,缓速
|
||||
|
||||
- 对于 自定义屏幕块/自定义滚屏:x/y
|
||||
- 对于 自定义屏幕分隔/屏幕滚动:x/y
|
||||
|
||||
- 对于 高光:阈值,强度,颜色,缓速时长,缓速
|
||||
|
||||
@@ -0,0 +1,769 @@
|
||||
[项目地址](https://github.com/RDCN-Community-Developers/RhythmToolkit)
|
||||
[English](/pages/3rdparty_rdtk_EN.md) | 中文
|
||||
|
||||
# RhythmBase 使用教程
|
||||
|
||||
本项目为节奏医生关卡开发者服务,旨在为开发人员提供更加系统、直观的关卡编辑媒介。
|
||||
感谢节奏医生饭制部玩家对这个项目的支持。
|
||||
欢迎来到 RhythmBase 教程。本指南将帮助您开始在项目中设置和使用 RhythmBase。
|
||||
|
||||
## 安装 Nuget 包
|
||||
|
||||
要安装 RhythmBase NuGet 包,请按照以下步骤操作:
|
||||
|
||||
1. 打开 Visual Studio 或使用命令行工具。
|
||||
2. 在 Visual Studio 中,依次点击 **工具** > **NuGet 包管理器** > **程序包管理器控制台**。
|
||||
3. 在控制台中输入以下命令:
|
||||
|
||||
```bash
|
||||
Install-Package RhythmBase -Version 1.2.0-rc2
|
||||
```
|
||||
|
||||
4. 等待安装完成,并确保项目已引用所需的 NuGet 包。
|
||||
5. 如果使用 .NET CLI,请输入:
|
||||
|
||||
```bash
|
||||
dotnet add package RhythmBase -version 1.2.0-rc2
|
||||
```
|
||||
|
||||
## 编写
|
||||
### 创建关卡
|
||||
|
||||
关卡是一个事件集合, 如果使用 C# 12 或更高版本, 可以使用[集合表达式](https://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/operators/collection-expressions)以创建空关卡。
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
using RDLevel emptyLevel = [];
|
||||
Console.WriteLine(emptyLevel); // "" Count = 0
|
||||
```
|
||||
|
||||
也可以使用自带的模板以创建具有基础事件的关卡。
|
||||
此模板即为节奏医生编辑器默认创建的关卡模板。
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
using RDLevel defaultLevel = RDLevel.Default;
|
||||
Console.WriteLine(defaultLevel); // "" Count = 3
|
||||
```
|
||||
|
||||
### 读取和写入
|
||||
|
||||
可以直接以文件路径读取和导出文件。将以默认读写设置读写文件。
|
||||
导出时不会打包为关卡包。
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
// 直接读取关卡文件
|
||||
using RDLevel rdlevel1 = RDLevel.Read(@"your\level.rdlevel");
|
||||
|
||||
// 读取关卡包文件
|
||||
using RDLevel rdlevel2 = RDLevel.Read(@"your\level.rdzip");
|
||||
|
||||
// 读取关卡压缩包
|
||||
using RDLevel rdlevel3 = RDLevel.Read(@"your\level.zip");
|
||||
|
||||
// 写入关卡文件
|
||||
rdlevel1.Write(@"your\outLevel.rdlevel");
|
||||
```
|
||||
|
||||
可以添加自定义读写设置 `LevelReadOrWriteSettings` 以读写关卡。
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
using RhythmBase.RhythmDoctor.Settings;
|
||||
|
||||
// 编写自定义读写设置
|
||||
LevelReadOrWriteSettings settings = new()
|
||||
{
|
||||
// 对未激活事件的处理方式
|
||||
InactiveEventsHandling = InactiveEventsHandling.Store,
|
||||
// 对读取出现异常的事件的处理方式
|
||||
// 常见于精灵事件未与精灵轨道绑定等
|
||||
UnreadableEventsHandling = UnreadableEventHandling.Store,
|
||||
// 是否启用缩进
|
||||
Indented = true,
|
||||
};
|
||||
|
||||
using RDLevel rdlevel1 = RDLevel.Read(@"your\level.rdlevel", settings);
|
||||
```
|
||||
|
||||
也可以生成 json 对象或 json 字符串以进行进一步操作。
|
||||
|
||||
```cs
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
JObject jobject = rdlevel.ToJObject();
|
||||
string json = rdlevel.ToRDLevelJson(settings);
|
||||
```
|
||||
|
||||
`LevelReadOrWriteSettings` 添加了 `BeforeReading`, `AfterReading`, `BeforeWriting`, `AfterWriting` 事件,分别会在关卡读取之前、之后,写入之前、之后触发。
|
||||
可在这些事件上添加监听以达到特定效果。
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Settings;
|
||||
|
||||
settings.AfterWriting += Settings_AfterReading;
|
||||
|
||||
// 将在写入结束时触发
|
||||
void Settings_AfterReading(object? sender, EventArgs e)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
rdlevel.Write(@"your\outLevel.rdlevel", settings);
|
||||
```
|
||||
|
||||
> 在读取关卡压缩包文件时请使用 `using` 语句或主动调用 `RDLevel.Dispose()` 方法以保证被解压的临时文件被及时销毁。
|
||||
|
||||
### 查找和获取事件
|
||||
|
||||
`OrderedEventCollection` 类型用于存储事件集合, `RDLevel` 继承此类型。
|
||||
|
||||
可以使用针对节奏医生关卡事件的查询操作的扩展方法, 用以简化查询操作。
|
||||
例如通过事件类型及其父类型、事件实现的接口、节拍范围、自定义谓词等。
|
||||
提供 `AddRange()`, `RemoveRange()`, `Where()`, `RemoveAll()`, `First()`, `FirstOrDefault()`, `Last()`, `LastOrDefault()`, `TakeWhile()` 等扩展方法。
|
||||
|
||||
推荐使用这些经过效率优化的方法。
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Extensions;
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
// 查找在第 3 到第 5 小节、在事件栏的第 0 到第 2 行的移动轨道事件
|
||||
var list = rdlevel.Where<MoveRow>(
|
||||
i => 0 <= i.Y && i.Y < 3, // 在事件栏的第 0 到第 2 行
|
||||
3..5 // 第 3 到第 5 小节
|
||||
);
|
||||
```
|
||||
|
||||
`Row` 和 `Decoration` 也继承 `OrderedEventCollection`, 所以轨道和精灵也支持这些扩展方法。
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Extensions;
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
// 查找在第 11 小节第 1 拍到第 13 小节第 1 拍的普通拍子事件
|
||||
var list = rdlevel.Decorations[0].Where<Tint>(
|
||||
new Beat(11, 1), // 查找起点为第 11 小节第 1 拍
|
||||
new Beat(13, 1) // 查找终点为第 13 小节第 1 拍
|
||||
);
|
||||
```
|
||||
|
||||
### 创建节拍
|
||||
|
||||
`RDBeat` 是一个结构体, 它缓存三个信息 `BeatOnly`, `BarBeat`和`TimeSpan`。
|
||||
|
||||
可以创建一个不与关卡相关的 `RDBeat` 实例, 但因为缺失和关卡的联系, 其功能可能不完善。
|
||||
可以查看它的 `IsEmpty` 属性以了解此实例是否可用。
|
||||
在没有关卡联系的情况下, 调用它的 `ToString()` 方法会显示此实例拥有的信息和缺失的信息。
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
// 创建与关卡无关联的节拍
|
||||
RDBeat beat1 = new(11);
|
||||
RDBeat beat2 = new(2, 3);
|
||||
RDBeat beat3 = new(TimeSpan.FromSeconds(11.45));
|
||||
|
||||
Console.WriteLine(beat1); // [10,?,?]
|
||||
Console.WriteLine(beat2); // [?,(2, 3),?]
|
||||
Console.WriteLine(beat3); // [?,?,00:00:11.4500000]
|
||||
```
|
||||
|
||||
可以依靠 `BeatCalculator` 实例或 `RDLevel` 实例创建一个和关卡关联的 `RDBeat` 实例。
|
||||
|
||||
其中 `BeatCalculator` 伴随 `RDLevel` 的创建而创建, 可通过 `RDLevel.Calculator` 访问。
|
||||
在有关卡联系的情况下, 调用它的 `ToString()` 方法会显示 `BarBeat` 属性。
|
||||
只有与关卡关联, 三个属性才能建立联系, 节拍才能参与所有运算。否则只有相应属性存在数据才能运算。
|
||||
关卡内事件和书签的节拍属性都是与关卡相关联的, 而移出的事件会断开与关卡的关联。
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
// 创建与关卡有关联的节拍
|
||||
RDBeat beat1 = rdlevel.BeatOf(11);
|
||||
RDBeat beat2 = rdlevel.Calculator.BeatOf(2, 3);
|
||||
RDBeat beat3 = beat1 - 10 + TimeSpan.FromSeconds(11.45);
|
||||
|
||||
Console.WriteLine(beat1); // [2,3]
|
||||
Console.WriteLine(beat2); // [2,3]
|
||||
Console.WriteLine(beat3); // [3,4.083334]
|
||||
```
|
||||
|
||||
在节拍之间参与运算时, 若都有所链接的关卡, 需确保其指向的关卡相同。
|
||||
可调用 `FromSameLevel()` 或 `FromSameLevelOrNull()` 方法检查其是否指向相同关卡。
|
||||
可调用 `WithoutLink()` 返回一个脱离关卡的新节拍实例。
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
RDBeat beat1 = rdlevel.BeatOf(1);
|
||||
RDBeat beat2 = beat1.WithoutLink();
|
||||
|
||||
Console.WriteLine(beat1.FromSameLevel(beat2)); // False
|
||||
Console.WriteLine(beat1.FromSameLevelOrNull(beat2)); // True
|
||||
```
|
||||
|
||||
`BeatCalculator` 也带有时间转换的方法, 可以对不同的时间单位进行转换。
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
using RhythmBase.RhythmDoctor.Utils;
|
||||
|
||||
(float, float) barbeat = rdlevel.Calculator.TimeSpanToBarBeat(TimeSpan.FromSeconds(19.19)); // (4, 8.983334)
|
||||
```
|
||||
|
||||
`RDLevel` 带有一个和此实例关联的节拍数为 1 的默认节拍。
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
RDBeat @default = RDLevel.DefaultBeat;
|
||||
```
|
||||
|
||||
`RDRange` 是一个与 `Range` 相似的数据类型, 用以表示一个节拍范围。
|
||||
常用于查询事件。
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
using RhythmBase.RhythmDoctor.Extension;
|
||||
|
||||
var result = rdlevel.Where(new RDRange(rdlevel.DefaultBeat + 10, null));
|
||||
```
|
||||
|
||||
### 扩展数据类型
|
||||
|
||||
以 `RD` 开头, 带有 `Point`, `Size`, `Rect`, `RotatedRect` 的名称的类型都是 `RhythmBase` 里与平面几何相关的数据类型。
|
||||
|
||||
后缀带有 `I` 的为整数类型, 其所有数据属性都为 `int`, 如 `RDPointI.X`。
|
||||
后缀带有 `N` 的为非空类型, 其所有数据属性都为不可空类型, 如 `RDSizeN.Height`。
|
||||
后缀带有 `E` 的为表达式类型, 其所有数据属性都为 `RDExpression`, 如 `RDRectE.Size`。
|
||||
`RotatedRect` 的 `Angle` 不受命名规则 `I` 约束, 其始终为浮点数类型。
|
||||
|
||||
`RDExpression` 用以存储节奏医生表达式并尝试解析和求值(没做完), 以字符串创建, 并支持简单的运算。
|
||||
底层为字符串拼接, 所以当然版本运算会导致表达式嵌套多层括号是正常现象。
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
RDExpression exp1 = new("i2+1");
|
||||
RDExpression exp2 = new(30);
|
||||
RDExpression exp3 = new("25.5");
|
||||
|
||||
RDExpression result = exp1 - exp2 * exp3;
|
||||
|
||||
Console.WriteLine(result); // i2+1-765
|
||||
```
|
||||
|
||||
### 创建事件和增删事件
|
||||
|
||||
所有事件都直接或间接实现 `IBaseEvent` 接口并继承 `BaseEvent` 抽象类型。
|
||||
可以将这些接口与抽象类型作为查询扩展方法的泛型参数以筛选事件。
|
||||
例如,
|
||||
`BaseRowAction`, `BaseDecorationAction` 分别是轨道事件和精灵事件,
|
||||
`IRoomEvent` 是拥有多房间属性的事件。
|
||||
创建事件所使用的节拍参数可以与关卡无关联, 当事件被添加进关卡时会创建与关卡的关联, 而移除关卡时也会切断关联。
|
||||
若不提供节拍参数则默认为关卡的第 1 拍。
|
||||
当调用事件的 `ToString()` 方法时, 将会以事件的节拍, 事件的类型, 事件的可显示数据的形式返回一个字符串。
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
using RhythmBase.RhythmDoctor.Events;
|
||||
|
||||
Comment comment = new() { Beat = new(12), Text = "My_comment." };
|
||||
Console.WriteLine(comment); // [11,?,?] Comment My_comment.
|
||||
|
||||
rdlevel.Add(comment);
|
||||
Console.WriteLine(comment); // [2,4] Comment My_comment.
|
||||
|
||||
rdlevel.Remove(comment);
|
||||
Console.WriteLine(comment); // [11,?,?] Comment My_comment.
|
||||
```
|
||||
|
||||
特别地,添加、更改、移除 `SetCrotchetsPerBar` 事件时会更新此事件之后的时间线,所以无需担心修改其数值时会影响事件的顺序、排布等;它们会按其自身的绝对节拍固定在相应的位置。关卡也会尝试增加新的 `SetCrotchetsPerBar` 事件或移除相同 `CrotchetsPerBar` 属性的相邻事件以维持其他片段的稳定。
|
||||
|
||||
轨道和精灵事件需要在相应的轨道或精灵上调用 `Add()` 进行添加, 而移除可以在轨道, 精灵或关卡的任意一处调用 `Remove()` 方法移除。
|
||||
重复添加不会有任何效果。
|
||||
事件类型 `Comment` 和 `TintRows` 不受此限制。
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
using RhythmBase.RhythmDoctor.Events;
|
||||
|
||||
using RDLevel rdlevel = RDLevel.Default;
|
||||
|
||||
MoveRow tr = new();
|
||||
Console.WriteLine(rdlevel); // "" Count = 3
|
||||
|
||||
rdlevel.Add(tint); // "" Count = 3
|
||||
|
||||
rdlevel.Rows[0].Add(tr);
|
||||
Console.WriteLine(rdlevel); // "" Count = 4
|
||||
|
||||
rdlevel.Remove(tr);
|
||||
Console.WriteLine(rdlevel); // "" Count = 3
|
||||
```
|
||||
|
||||
### 自定义事件
|
||||
|
||||
如果此程序集没有需要的事件类型,可以继承 `CustomEvent`, `CustomRowEvent` 或 `CustomDecorationEvent` 以实现类型。
|
||||
|
||||
```cs
|
||||
using Newtonsoft.RhythmDoctor.Json.Linq;
|
||||
using RhythmBase.RhythmDoctor.Events;
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
// 创建 MyEvent 类型
|
||||
// 继承自 CustomEvent 类型
|
||||
public class MyEvent : CustomEvent
|
||||
{
|
||||
// 重写属性
|
||||
public override Tabs Tab => Tabs.Actions;
|
||||
|
||||
// 实现的属性都需要和 CustomEvent.Data 字段内的数据绑定和判空。
|
||||
|
||||
// 实现一个 RDPointE 类型属性
|
||||
public RDPointE? MyProperty
|
||||
{
|
||||
get
|
||||
{
|
||||
// 在 Data 字段内获取所需要的内容并判空
|
||||
var value = Data["myProperty"];
|
||||
return value?.ToObject<RDPointE?>() ?? new RDPointE(0, 0);
|
||||
}
|
||||
set
|
||||
{
|
||||
// 将内容保存在 Data 字段内
|
||||
Data["myProperty"] =
|
||||
value.HasValue ?
|
||||
new JArray(
|
||||
value?.X ?? null,
|
||||
value?.Y ?? null) :
|
||||
null;
|
||||
}
|
||||
}
|
||||
|
||||
// 在构造函数内初始化类型
|
||||
public MyEvent()
|
||||
{
|
||||
// 初始化 RealType 属性。
|
||||
ActureType = nameof(MyEvent);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
编写好类型后可以像正常事件一样被读写。
|
||||
值得注意的是,`Type` 仍然是 `EventType.CustomEvent`, 而 `ActureType` 是自定义类型名。
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Events;
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
MyEvent myEvent = new();
|
||||
|
||||
rdlevel.Add(myEvent);
|
||||
|
||||
myEvent.Beat = new(8);
|
||||
|
||||
Console.WriteLine(myEvent.Type); // CustomEvent
|
||||
Console.WriteLine(myEvent.ActureType); // MyEvent
|
||||
```
|
||||
|
||||
另外,如果读取关卡时意外出现未知事件类型,其也会被读取为相应的 `CustomEvent`, `CustomRowEvent` 或 `CustomDecorationEvent` 类型事件。
|
||||
|
||||
### 事件类型与枚举
|
||||
|
||||
事件都拥有属性 `EaseType`, 可以通过 `EventTypeUtils` 内的方法转换得到对应的类型。
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
using RhythmBase.RhythmDoctor.Events;
|
||||
using RhythmBase.RhythmDoctor.Utils;
|
||||
|
||||
Console.WriteLine(EventType.Tint.ToType()); // RhythmBase.Events.Tint
|
||||
Console.WriteLine(EventTypeUtils.ToType("Tint")); // RhythmBase.Events.Tint
|
||||
Console.WriteLine(EventTypeUtils.ToEnum(typeof(Tint))); // Tint
|
||||
Console.WriteLine(EventTypeUtils.ToEnum<Tint>()); // Tint
|
||||
Console.WriteLine(string.Join(", ", EventTypeUtils.ToEnums(typeof(IBarBeginningEvent)))); // PlaySong,SetCrotchetsPerBar, SetHeartExplodeVolume
|
||||
Console.WriteLine(string.Join(", ", EventTypeUtils.ToEnums<IBarBeginningEvent>())); // PlaySong,SetCrotchetsPerBar, SetHeartExplodeVolume
|
||||
```
|
||||
|
||||
`EventTypeUtils` 也包含一些事件类型的归类,如:
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Utils;
|
||||
|
||||
Console.WriteLine(string.Join(",\n", EventTypeUtils.DecorationTypes));
|
||||
// Comment,
|
||||
// CustomDecorationEvent,
|
||||
// Move,
|
||||
// PlayAnimation,
|
||||
// SetVisible,
|
||||
// Tile,
|
||||
// Tint
|
||||
|
||||
Console.WriteLine(string.Join(",\n", EventTypeUtils.EventTypeEnumsForCameraFX));
|
||||
// MoveCamera,
|
||||
// ShakeScreen,
|
||||
// FlipScreen,
|
||||
// PulseCamera
|
||||
|
||||
Console.WriteLine(string.Join(",\n", EventTypeUtils.EventTypeEnumsForUtility));
|
||||
// Comment,
|
||||
// TagAction,
|
||||
// CallCustomMethod
|
||||
```
|
||||
|
||||
### 富文本和对话组件
|
||||
|
||||
富文本组件位于 `RhythmBase.Components.RichText` 命名空间下,可以通过 `+` 运算组合自定义颜色的富文本。同时支持富文本的序列化和反序列化。
|
||||
|
||||
`RDLine<>` 是一个完整的富文本。
|
||||
`RDPhrase<>` 是富文本的一个样式片段,其遵循单个样式。
|
||||
使用实现了 `IRDRichStringStyle<>` 的结构体以指明此富文本遵循的样式规则。下例的 `RDRichStringStyle` 即为仅带有颜色样式的富文本。
|
||||
|
||||
都可以从 string 隐式转换。注意,转换的文字为不带样式的富文本。
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
using RhythmBase.Global.Components.RichText;
|
||||
|
||||
RDLine<RDRichStringStyle> line = RDLine<RDRichStringStyle>.Deserialize("Hel<color=#00FF00>lo");
|
||||
|
||||
Console.WriteLine(line.ToString()); // Hello
|
||||
Console.WriteLine(line.Serialize()); // Hel<color=lime>lo</color>
|
||||
|
||||
line +=
|
||||
new RDPhrase<RDRichStringStyle>(" Rhythm")
|
||||
{
|
||||
Style = new()
|
||||
{
|
||||
Color = RDColor.Lime
|
||||
}
|
||||
};
|
||||
|
||||
line += " Doctor!";
|
||||
|
||||
Console.WriteLine(line.ToString()); // Hello Rhythm Doctor!
|
||||
Console.WriteLine(line.Serialize()); // Hel<color=lime>lo Rhythm</color> Doctor!
|
||||
```
|
||||
|
||||
`RDLine<>` 和 `RDPhrase<>` 都可以使用索引访问和修改其片段。
|
||||
|
||||
```cs
|
||||
using RhythmBase.Global.Components.RichText;
|
||||
|
||||
RDLine<RDRichStringStyle> line = RDLine<RDRichStringStyle>.Deserialize("Hel<color=#00FF00>lo Rhythm</color> Doctor!");
|
||||
|
||||
Console.WriteLine(line[6..].ToString()); // Rhythm Doctor!
|
||||
Console.WriteLine(line[6..].Serialize()); // <color=lime>Rhythm</color> Doctor!
|
||||
|
||||
line[5] = " and Welcome to ";
|
||||
|
||||
Console.WriteLine(line.ToString()); // Hello and Welcome to Rhythm Doctor!
|
||||
Console.WriteLine(line.Serialize()); // Hel<color=lime>lo</color> and Welcome to <color=lime>Rhythm</color> Doctor!
|
||||
|
||||
return;
|
||||
```
|
||||
|
||||
此包内也提供一整套适配节奏医生对话格式的对话组件,用以模块化构造对话事件的文本内容,减少错误率。
|
||||
|
||||
```cs
|
||||
using RhythmBase.Global.Components.RichText;
|
||||
|
||||
RDDialogueExchange exchange =
|
||||
[
|
||||
new RDDialogueBlock()
|
||||
{
|
||||
Character = "Paige",
|
||||
Expression = "neutral",
|
||||
Content = RDLine<RDDialoguePhraseStyle>.Deserialize("Hel<color=#00FF00>lo [2]<shake>Rhythm</color> Doctor</shake>!"),
|
||||
},
|
||||
new RDDialogueBlock()
|
||||
{
|
||||
Character = "Ian",
|
||||
Content = "Hello Paige!",
|
||||
},
|
||||
new RDDialogueBlock()
|
||||
{
|
||||
Character = "Paige",
|
||||
Expression = "happy",
|
||||
Content = new RDPhrase<RDDialoguePhraseStyle>("What a good day!")
|
||||
{
|
||||
Events =
|
||||
[
|
||||
new RDDialogueTone(RDDialogueToneType.VerySlow,6),
|
||||
new RDDialogueTone(RDDialogueToneType.Static,11),
|
||||
],
|
||||
Style = new RDDialoguePhraseStyle()
|
||||
{
|
||||
Volume = 0.5f,
|
||||
Bold = true,
|
||||
},
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
Console.WriteLine(exchange.Serialize());
|
||||
// Paige_neutral:Hel<color=lime>lo [2]<shake>Rhythm</color> Doctor</shake>!
|
||||
// Ian:Hello Paige!
|
||||
// Paige_happy:<volume=0.5><bold>What a[vslow] good[static] day!</volume></bold>
|
||||
```
|
||||
|
||||
### 缓动
|
||||
|
||||
引入 `RhythmBase.Global.Components.Easing` 之后,可以很方便地使用 `EaseType` 枚举常量。
|
||||
同时也可以使用扩展方法 `Calculate()` 快速计算过渡值。
|
||||
|
||||
```cs
|
||||
using RhythmBase.Global.Components.Easing;
|
||||
|
||||
double var1 = EaseType.InSine.Calculate(0.25);
|
||||
double var2 = EaseType.Linear.Calculate(0.5,4,9);
|
||||
|
||||
Console.WriteLine(var1); // 0.07612046748871326
|
||||
Console.WriteLine(var2); // 6.5
|
||||
```
|
||||
|
||||
`EaseValue` 是一个简单但强大的结构体。得益于 mfgujhgh 的算法,通过使用静态方法 `Fit()` 处理任意数据,`EaseValue` 可以使用给定的 `EaseType` 选择列表拟合出可被节奏医生事件使用的曲线。
|
||||
|
||||
```cs
|
||||
using RhythmBase.Global.Components.Easing;
|
||||
|
||||
// 使用点集和阈值拟合
|
||||
EaseValue data1 = EaseValue.Fit([
|
||||
(0, 0),
|
||||
(1, 1)
|
||||
], 3f);
|
||||
// 使用初始值、点集、可选缓动类型列表和阈值拟合
|
||||
EaseValue data2 = EaseValue.Fit(0, [
|
||||
(0, 0),
|
||||
(1, 1)
|
||||
], [EaseType.Linear, EaseType.InSine], 3f);
|
||||
// 从缓动数据中获取指定时刻的值
|
||||
float value = data1.GetValue(2.5f);
|
||||
```
|
||||
|
||||
`RhythmBase.Extensions.EasePropertyExtensions` 为实现了 `IEaseEvent` 的类型添加了一个 `GetEaseProperties` 方法,用于获取这一系列事件的各个属性的缓动曲线。
|
||||
|
||||
```cs
|
||||
using RhythmBase.Global.Components;
|
||||
using RhythmBase.Global.Components.Easing;
|
||||
using RhythmBase.Global.Events;
|
||||
using RhythmBase.RhythmDoctor.Extensions;
|
||||
|
||||
var deco = level.Decorations[0];
|
||||
|
||||
Move[] moves =
|
||||
[
|
||||
new(){ Beat = level.BeatOf(1), Position = new(0, (RDExpression?)null), Duration = 1,Ease = EaseType.Linear, Angle = "2" },
|
||||
new(){ Beat = level.BeatOf(2.1f), Position = new(10, 90), Duration = 1,Ease = EaseType.Linear },
|
||||
new(){ Beat = level.BeatOf(2.2f), Position = new(90, 10), Duration = 1,Ease = EaseType.Linear },
|
||||
new(){ Beat = level.BeatOf(3), Position = new(10, 70), Duration = 1,Ease = EaseType.Linear },
|
||||
new(){ Beat = level.BeatOf(3.5f), Position = new(10, 10), Duration = 1,Ease = EaseType.Linear },
|
||||
new(){ Beat = level.BeatOf(3.8f), Position = new(30, 50), Duration = 1,Ease = EaseType.Linear },
|
||||
new(){ Beat = level.BeatOf(3.9f), Position = new(20, (RDExpression?)null), Duration = 1,Ease = EaseType.Linear },
|
||||
new(){ Beat = level.BeatOf(4.1f), Position = new(70, 20), Duration = 1,Ease = EaseType.Linear },
|
||||
new(){ Beat = level.BeatOf(4.4f), Position = new((RDExpression?)null, 0), Duration = 1,Ease = EaseType.Linear },
|
||||
];
|
||||
|
||||
deco.AddRange(moves);
|
||||
|
||||
var eases = EasePropertyExtensions.GetEaseProperties(moves);
|
||||
|
||||
foreach(var e in eases)
|
||||
Console.WriteLine(e);
|
||||
// [Position, RhythmBase.Components.Easing.EasePropertyPoint]
|
||||
// [Scale, RhythmBase.Components.Easing.EasePropertySize]
|
||||
// [Angle, RhythmBase.Components.Easing.EasePropertyFloat]
|
||||
// [Pivot, RhythmBase.Components.Easing.EasePropertyPoint]
|
||||
```
|
||||
|
||||
实现 `IEaseProperty<>` 接口的类型,例如 `EasePropertyColor`,`EasePropertyFloat`,`EasePropertyPoint`,`EasePropertySize`,用于存储来自缓动事件列表的内容。
|
||||
同样也可以获取相应时刻的值。
|
||||
|
||||
> 在调用之前请检查属性的值类型,并应用相应的类型转换。
|
||||
|
||||
```cs
|
||||
using RhythmBase.Global.Components.Easing;
|
||||
|
||||
var result = ((EasePropertyPoint)eases["Position"]).GetValue(rdlevel.BeatOf(3.2f));
|
||||
|
||||
Console.WriteLine(result); // [59.759995, 21.840006]
|
||||
```
|
||||
|
||||
### 表达式(重写中)
|
||||
|
||||
`RhythmBase.Components.RDLang.RDLang` 提供一个 `TryRun()` 方法,用于运行节奏医生表达式。
|
||||
|
||||
> 注意,若表达式不正确则会返回 `false`,同时结果为 `0`。
|
||||
|
||||
`RDLang` 同时有一个静态字段 `Variables`,用于存储所有常用变量与方法。在执行 `TryRun` 之前修改字段会影响执行时的值。
|
||||
`RDLang` 也支持三个常用方法 `Rand()`,`atLeastRank()`,`atLeastNPerfects()`,这些方法都可以在 `RDVariables` 上正常访问。
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components.RDLang;
|
||||
|
||||
RDLang.Variables.i[1] = 9;
|
||||
|
||||
RDLang.TryRun("numMistakesP2 = 3", out float result); // 3
|
||||
RDLang.TryRun("numMistakesP2+i1", out result); // 12
|
||||
RDLang.TryRun("atLeastRank(A)", out result); // 1
|
||||
```
|
||||
由于此库不支持动态播放关卡,可使用以下字段对后两个函数的效果进行模拟:
|
||||
- `atLeastRank()`
|
||||
使用 `RDVariables.SimulateCurrentRank` 属性更改模拟关卡评级状态。
|
||||
当表达式访问 `atLeastRank()` 方法时使用此值进行模拟。
|
||||
- `atLeastNPerfects()`
|
||||
使用 `RDVariables.SimulateAtLeastNPerfectsSuccessRate` 属性更改模拟成功击拍百分比。
|
||||
当表达式访问 `atLeastNPerfects()` 方法时使用此值进行模拟。
|
||||
|
||||
### 事件组
|
||||
|
||||
像一个新事件一样声明并使用它,它会按照您指定的方式生成关卡事件!
|
||||
|
||||
像下面这样继承 `Group` 类,实现新的逻辑后,您可以像其他事件一样自由地操纵它。
|
||||
这与 `CustomEvent` 不同,它会用指定的事件序列写入关卡,而不是它本身。
|
||||
|
||||
```cs
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.RhythmDoctor.Events;
|
||||
|
||||
public class GroupData1
|
||||
{
|
||||
public RDSize Size;
|
||||
public int RowIndex;
|
||||
}
|
||||
|
||||
public class MoveCameraRectangle : Group<GroupData1>
|
||||
{
|
||||
public RDSize Size
|
||||
{
|
||||
get => Data.Size;
|
||||
set => Data.Size = value;
|
||||
}
|
||||
public Row Row
|
||||
{
|
||||
get => Rows?[Data.RowIndex] ?? [];
|
||||
set => Data.RowIndex = value.Index;
|
||||
}
|
||||
public MoveCameraRectangle() { }
|
||||
public override IEnumerable<BaseEvent> GenerateEvents()
|
||||
{
|
||||
yield return new MoveCamera() { Beat = new(1), Rooms = new(true, 0), CameraPosition = new(50 - Size.Width / 2, 50 - Size.Height / 2), Duration = 1 };
|
||||
yield return new MoveCamera() { Beat = new(2), Rooms = new(true, 0), CameraPosition = new(50 + Size.Width / 2, 50 - Size.Height / 2), Duration = 1 };
|
||||
yield return new MoveCamera() { Beat = new(3), Rooms = new(true, 0), CameraPosition = new(50 + Size.Width / 2, 50 + Size.Height / 2), Duration = 1 };
|
||||
yield return new MoveCamera() { Beat = new(4), Rooms = new(true, 0), CameraPosition = new(50 - Size.Width / 2, 50 + Size.Height / 2), Duration = 1 };
|
||||
yield return SetParent(new MoveRow() { Beat = new(1), RowPosition = new(50, 50), CustomPosition = true, Duration = 0 }, Row);
|
||||
yield return SetParent(new MoveRow() { Beat = new(1.001f), RowPosition = new(50 - Size.Width / 2, 50 - Size.Height / 2), CustomPosition = true, Duration = 1 }, Row);
|
||||
yield return SetParent(new MoveRow() { Beat = new(2), RowPosition = new(50 + Size.Width / 2, 50 - Size.Height / 2), CustomPosition = true, Duration = 1 }, Row);
|
||||
yield return SetParent(new MoveRow() { Beat = new(3), RowPosition = new(50 + Size.Width / 2, 50 + Size.Height / 2), CustomPosition = true, Duration = 1 }, Row);
|
||||
yield return SetParent(new MoveRow() { Beat = new(4), RowPosition = new(50 - Size.Width / 2, 50 + Size.Height / 2), CustomPosition = true, Duration = 1 }, Row);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
值得注意的是,这样的操作会比较消耗资源。所以 `LevelReadOrWriteSettings` 会默认禁用这个选项。
|
||||
其底层逻辑大致为,它会为事件序列中的每个事件附加一个特殊的标签以标记它是“被生成”的,以供下次读取事件时清理这些被生成的事件。对于其中已有标签的事件,它会有一层额外逻辑以封装这些事件。
|
||||
|
||||
```cs
|
||||
using RhythmBase.Global.Settings;
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
Console.WriteLine(level);
|
||||
|
||||
LevelReadOrWriteSettings settings = new()
|
||||
{
|
||||
EnableGroupEvent = true,
|
||||
InactiveEventsHandling = InactiveEventsHandling.Retain,
|
||||
Indented = true
|
||||
};
|
||||
|
||||
using RDLevel level = RDLevel.Default;
|
||||
level.Decorations.Add(new Decoration() { Room = RDRoomIndex.Room1 });
|
||||
var re1 = new MoveCameraRectangle() { Beat = new(4), Size = new RDSize(80, 80) };
|
||||
var re2 = new MoveCameraRectangle() { Beat = new(9), Y = 2, Size = new RDSize(20, 20) };
|
||||
level.Add(re1);
|
||||
level.Add(re2);
|
||||
level.Write(dstPath, settings);
|
||||
|
||||
// 会生成这些事件:
|
||||
// {"bar":1,"beat":1,"type":"MoveCamera","rooms":[0],"cameraPosition":[10,10],"duration":1,"ease":"Linear","y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000000"},
|
||||
// {"bar":1,"beat":1,"type":"MoveRow","customPosition":true,"target":"WholeRow","rowPosition":[50,50],"duration":0,"ease":"Linear","row":0,"y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000000"},
|
||||
// {"bar":1,"beat":1.001,"type":"MoveRow","customPosition":true,"target":"WholeRow","rowPosition":[10,10],"duration":1,"ease":"Linear","row":0,"y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000000"},
|
||||
// {"bar":1,"beat":2,"type":"MoveCamera","rooms":[0],"cameraPosition":[90,10],"duration":1,"ease":"Linear","y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000000"},
|
||||
// {"bar":1,"beat":2,"type":"MoveRow","customPosition":true,"target":"WholeRow","rowPosition":[90,10],"duration":1,"ease":"Linear","row":0,"y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000000"},
|
||||
// {"bar":1,"beat":3,"type":"MoveCamera","rooms":[0],"cameraPosition":[90,90],"duration":1,"ease":"Linear","y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000000"},
|
||||
// {"bar":1,"beat":3,"type":"MoveRow","customPosition":true,"target":"WholeRow","rowPosition":[90,90],"duration":1,"ease":"Linear","row":0,"y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000000"},
|
||||
// {"bar":1,"beat":4,"type":"MoveCamera","rooms":[0],"cameraPosition":[10,90],"duration":1,"ease":"Linear","y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000000"},
|
||||
// {"bar":1,"beat":4,"type":"MoveRow","customPosition":true,"target":"WholeRow","rowPosition":[10,90],"duration":1,"ease":"Linear","row":0,"y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000000"},
|
||||
// {"bar":1,"beat":1,"type":"MoveCamera","rooms":[0],"cameraPosition":[40,40],"duration":1,"ease":"Linear","y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000001"},
|
||||
// {"bar":1,"beat":1,"type":"MoveRow","customPosition":true,"target":"WholeRow","rowPosition":[50,50],"duration":0,"ease":"Linear","row":0,"y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000001"},
|
||||
// {"bar":1,"beat":1.001,"type":"MoveRow","customPosition":true,"target":"WholeRow","rowPosition":[40,40],"duration":1,"ease":"Linear","row":0,"y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000001"},
|
||||
// {"bar":1,"beat":2,"type":"MoveCamera","rooms":[0],"cameraPosition":[60,40],"duration":1,"ease":"Linear","y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000001"},
|
||||
// {"bar":1,"beat":2,"type":"MoveRow","customPosition":true,"target":"WholeRow","rowPosition":[60,40],"duration":1,"ease":"Linear","row":0,"y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000001"},
|
||||
// {"bar":1,"beat":3,"type":"MoveCamera","rooms":[0],"cameraPosition":[60,60],"duration":1,"ease":"Linear","y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000001"},
|
||||
// {"bar":1,"beat":3,"type":"MoveRow","customPosition":true,"target":"WholeRow","rowPosition":[60,60],"duration":1,"ease":"Linear","row":0,"y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000001"},
|
||||
// {"bar":1,"beat":4,"type":"MoveCamera","rooms":[0],"cameraPosition":[40,60],"duration":1,"ease":"Linear","y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000001"},
|
||||
// {"bar":1,"beat":4,"type":"MoveRow","customPosition":true,"target":"WholeRow","rowPosition":[40,60],"duration":1,"ease":"Linear","row":0,"y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000001"},
|
||||
// {"bar":1,"beat":1,"type":"Comment","tab":"Song","show":false,"text":"$RhythmBase_GroupData$\r\n/* Generated by RhythmBase */\r\n@MoveCameraRectangle\r\n@MoveCameraRectangle2\r\n@RhythmBase.RhythmDoctor.Events.Group\r\n@RhythmBase.RhythmDoctor.Events.Group`1\r\n{\"size\":[80.0,80.0],\"rowIndex\":0}\r\n{\"size\":[20.0,20.0],\"rowIndex\":0}\r\n","color":"F2E644","y":-1},
|
||||
// {"bar":1,"beat":4,"type":"TagAction","Tag":"$RhythmBase_GroupEvent$0000000000000000","y":0,"tag":"","Action":"Run"},
|
||||
// {"bar":2,"beat":1,"type":"TagAction","Tag":"$RhythmBase_GroupEvent$0000000000000001","y":2,"tag":"","Action":"Run"},
|
||||
```
|
||||
|
||||
|
||||
## 案例
|
||||
### 合并采音关卡与视效关卡
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
using RhythmBase.RhythmDoctor.Events;
|
||||
using RhythmBase.RhythmDoctor.Extensions;
|
||||
|
||||
// 读取视效关卡文件
|
||||
using RDLevel vfxLevel = RDLevel.Read(@"vfx.rdlevel");
|
||||
// 读取采音关卡文件
|
||||
using RDLevel audioLevel = RDLevel.Read(@"beat.rdlevel");
|
||||
|
||||
// 移除视效关卡内所有轨道
|
||||
RowEventCollection[] vfxrows = [.. vfxLevel.Rows];
|
||||
foreach (var row in vfxrows)
|
||||
vfxLevel.Rows.Remove(row);
|
||||
|
||||
// 复制采音关卡所有轨道的内容到新的关卡内
|
||||
foreach (var row in audioLevel.Rows)
|
||||
{
|
||||
// 复制轨道信息
|
||||
Row row2 = new()
|
||||
{
|
||||
Rooms = row.Rooms,
|
||||
Character = row.Character,
|
||||
Sound = row.Sound,
|
||||
RowType = row.RowType
|
||||
};
|
||||
vfxLevel.Rows.Add(row2);
|
||||
|
||||
// 复制轨道内的事件
|
||||
BaseBeat[] evts = [.. row.Where<BaseBeat>()];
|
||||
foreach (var evt in evts)
|
||||
row2.Add(evt);
|
||||
i++;
|
||||
}
|
||||
|
||||
// 复制需要的音效事件
|
||||
foreach (var sound in audioLevel.Where(e =>
|
||||
e.Tab == Tabs.Sounds && // 事件位于音效栏中
|
||||
e is not BaseRowAction && // 音效事件内包含轨道事件,如果在这里添加轨道事件会导致引用出错
|
||||
e is not PlaySong && // 播放音乐事件相同的情况下不需要复制
|
||||
e is not SetCrotchetsPerBar)) // 复制事件的时间计算是无关四分音符数的,所以可以不用添加
|
||||
{
|
||||
vfxLevel.Add(sound);
|
||||
}
|
||||
|
||||
// 写入到新的关卡文件中
|
||||
vfxLevel.Write(@"result.rdlevel");
|
||||
```
|
||||
@@ -0,0 +1,763 @@
|
||||
[Repository](https://github.com/RDCN-Community-Developers/RhythmToolkit)
|
||||
English | [中文](/pages/3rdparty_rdtk.md)
|
||||
|
||||
# RhythmBase Tutorial
|
||||
|
||||
This project serves Rhythm Doctor level developers, aiming to provide a more systematic and intuitive level editing medium for developers.
|
||||
Thanks to the Rhythm Doctor fan community for their support of this project.
|
||||
Welcome to the RhythmBase tutorial. This guide will help you get started with setting up and using RhythmBase in your project.
|
||||
|
||||
## Install NuGet Package
|
||||
|
||||
To install the RhythmBase NuGet package, follow these steps:
|
||||
|
||||
1. Open Visual Studio or use the command line tools.
|
||||
2. In Visual Studio, go to **Tools** > **NuGet Package Manager** > **Package Manager Console**.
|
||||
3. In the console, enter the following command:
|
||||
|
||||
```
|
||||
Install-Package RhythmBase -Version 1.2.0-rc2
|
||||
```
|
||||
|
||||
4. Wait for the installation to complete and ensure your project references the required NuGet package.
|
||||
5. To install using the .NET CLI, use:
|
||||
|
||||
```
|
||||
dotnet add package RhythmBase -version 1.2.0-rc2
|
||||
```
|
||||
|
||||
## Coding
|
||||
### Creating a Level
|
||||
|
||||
A level is a collection of events.
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
using RDLevel emptyLevel = [];
|
||||
Console.WriteLine(emptyLevel); // "" Count = 0
|
||||
```
|
||||
|
||||
You can also use the built-in template to create a level with basic events.
|
||||
This template is the same as the default level template created by the Rhythm Doctor Level Editor.
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
using RDLevel defaultLevel = RDLevel.Default;
|
||||
Console.WriteLine(defaultLevel); // "" Count = 3
|
||||
```
|
||||
|
||||
### Reading and Writing
|
||||
|
||||
You can directly import and export files using file paths. The default read/write settings will be used.
|
||||
Exporting does not package the level as a `.rdzip` file.
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
// Directly read a level file
|
||||
using RDLevel rdlevel1 = RDLevel.Read(@"your\level.rdlevel");
|
||||
|
||||
// Read a level pack file
|
||||
using RDLevel rdlevel2 = RDLevel.Read(@"your\level.rdzip");
|
||||
|
||||
// Read a compressed level pack
|
||||
using RDLevel rdlevel3 = RDLevel.Read(@"your\level.zip");
|
||||
|
||||
// Write a level file
|
||||
rdlevel1.Write(@"your\outLevel.rdlevel");
|
||||
```
|
||||
|
||||
You can add custom read/write settings with `LevelReadOrWriteSettings` when reading or writing levels.
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
using RhythmBase.RhythmDoctor.Settings;
|
||||
|
||||
// Create custom read/write settings
|
||||
LevelReadOrWriteSettings settings = new()
|
||||
{
|
||||
// Handling of inactive events
|
||||
InactiveEventsHandling = InactiveEventsHandling.Store,
|
||||
// Handling of unreadable events
|
||||
// Common when sprite events are not bound to sprite tracks, etc.
|
||||
UnreadableEventsHandling = UnreadableEventHandling.Store,
|
||||
// Enable indentation
|
||||
Indented = true,
|
||||
};
|
||||
|
||||
using RDLevel rdlevel1 = RDLevel.Read(@"your\level.rdlevel", settings);
|
||||
```
|
||||
|
||||
You can also generate a JSON object or JSON string for further operations.
|
||||
|
||||
```cs
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
JObject jobject = rdlevel.ToJObject();
|
||||
string json = rdlevel.ToRDLevelJson(settings);
|
||||
```
|
||||
|
||||
`LevelReadOrWriteSettings` provides `BeforeReading`, `AfterReading`, `BeforeWriting`, and `AfterWriting` events, which are triggered before/after reading or writing a level.
|
||||
You can add listeners to these events for custom behaviors.
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Settings;
|
||||
|
||||
settings.AfterWriting += Settings_AfterReading;
|
||||
|
||||
// This will be triggered after writing is finished
|
||||
void Settings_AfterReading(object? sender, EventArgs e)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
rdlevel.Write(@"your\outLevel.rdlevel", settings);
|
||||
```
|
||||
|
||||
> When reading compressed level pack files, please use the `using` statement or actively call the `RDLevel.Dispose()` method to ensure that temporary files extracted during decompression are properly cleaned up.
|
||||
|
||||
### Finding and Retrieving Events
|
||||
|
||||
The `OrderedEventCollection` type is used to store collections of events, and `RDLevel` inherits from this type.
|
||||
|
||||
You can use extension methods designed for querying Rhythm Doctor level events to simplify your queries.
|
||||
For example, you can filter by event type and its base types, interfaces implemented by events, beat ranges, custom predicates, and more.
|
||||
Methods such as `AddRange()`, `RemoveRange()`, `Where()`, `RemoveAll()`, `First()`, `FirstOrDefault()`, `Last()`, `LastOrDefault()`, and `TakeWhile()` are provided.
|
||||
|
||||
It is recommended to use these optimized methods for better performance.
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Extensions;
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
// Find MoveRow events between measures 3 and 5, and in event rows 0 to 2
|
||||
var list = rdlevel.Where<MoveRow>(
|
||||
i => 0 <= i.Y && i.Y < 3, // In event rows 0 to 2
|
||||
3..5 // From bar 3 to 5
|
||||
);
|
||||
```
|
||||
|
||||
`Row` and `Decoration` also inherit from `OrderedEventCollection`, so rows and decorations also support these extension methods.
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Extensions;
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
// Find the AddClassicBeat event in the decoration between beat (11,1) and (13,1)
|
||||
var list = rdlevel.Decorations[0].Where<Tint>(
|
||||
new Beat(11, 1), // Start searching from bar 11, beat 1
|
||||
new Beat(13, 1) // End searching at bar 13, beat 1
|
||||
);
|
||||
```
|
||||
### Creating a Beat
|
||||
|
||||
`RDBeat` is a struct that stores three pieces of information: `BeatOnly`, `BarBeat`, and `TimeSpan`.
|
||||
|
||||
You can create a `RDBeat` instance that is not associated with a level, but due to the lack of a level context, its functionality may be limited.
|
||||
You can check its `IsEmpty` property to determine whether the instance is valid.
|
||||
When not associated with a level, calling its `ToString()` method will display the information it contains and indicate any missing information.
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
// Create a beat not associated with a level
|
||||
RDBeat beat1 = new(11);
|
||||
RDBeat beat2 = new(2, 3);
|
||||
RDBeat beat3 = new(TimeSpan.FromSeconds(11.45));
|
||||
|
||||
Console.WriteLine(beat1); // [10,?,?]
|
||||
Console.WriteLine(beat2); // [?,(2, 3),?]
|
||||
Console.WriteLine(beat3); // [?,?,00:00:11.4500000]
|
||||
```
|
||||
|
||||
You can create a beat associated with a level using a `BeatCalculator` instance or an `RDLevel` instance.
|
||||
|
||||
A `BeatCalculator` is created along with an `RDLevel` and can be accessed via `RDLevel.Calculator`.
|
||||
When associated with a level, calling its `ToString()` method will display the `BarBeat` property.
|
||||
Only when associated with a level can all three properties be linked, and the beat can participate in all operations. Otherwise, only the properties with data can be used in calculations.
|
||||
The beat properties of events and bookmarks within a level are all associated with the level, while events removed from the level will lose this association.
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
// Create a beat associated with a level
|
||||
RDBeat beat1 = rdlevel.BeatOf(11);
|
||||
RDBeat beat2 = rdlevel.Calculator.BeatOf(2, 3);
|
||||
RDBeat beat3 = beat1 - 10 + TimeSpan.FromSeconds(11.45);
|
||||
|
||||
Console.WriteLine(beat1); // [2,3]
|
||||
Console.WriteLine(beat2); // [2,3]
|
||||
Console.WriteLine(beat3); // [3,4.083334]
|
||||
```
|
||||
|
||||
When performing operations between beats, if both are linked to a level, you must ensure they refer to the same level.
|
||||
You can call the `FromSameLevel()` or `FromSameLevelOrNull()` methods to check if they refer to the same level.
|
||||
You can call `WithoutLink()` to return a new beat instance detached from any level.
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
RDBeat beat1 = rdlevel.BeatOf(1);
|
||||
RDBeat beat2 = beat1.WithoutLink();
|
||||
|
||||
Console.WriteLine(beat1.FromSameLevel(beat2)); // False
|
||||
Console.WriteLine(beat1.FromSameLevelOrNull(beat2)); // True
|
||||
```
|
||||
|
||||
`BeatCalculator` also provides methods for time conversion, allowing you to convert between different time units.
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
using RhythmBase.RhythmDoctor.Utils;
|
||||
|
||||
(float, float) barbeat = rdlevel.Calculator.TimeSpanToBarBeat(TimeSpan.FromSeconds(19.19)); // (4, 8.983334)
|
||||
```
|
||||
|
||||
`RDLevel` provides a default beat associated with the instance, with a beat count of 1.
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
RDBeat @default = RDLevel.DefaultBeat;
|
||||
```
|
||||
|
||||
`RDRange` is a data type similar to `Range`, used to represent a range of beats.
|
||||
It is commonly used for querying events.
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
using RhythmBase.RhythmDoctor.Extension;
|
||||
|
||||
var result = rdlevel.Where(new RDRange(rdlevel.DefaultBeat + 10, null));
|
||||
```
|
||||
### Extended Data Types
|
||||
|
||||
Types in RhythmBase that start with `RD` and contain names like `Point`, `Size`, `Rect`, or `RotatedRect` are data types related to planar geometry.
|
||||
|
||||
Types ending with `I` are integer types, where all data properties are of type `int`, such as `RDPointI.X`.
|
||||
Types ending with `N` are non-nullable types, where all data properties are non-nullable, such as `RDSizeN.Height`.
|
||||
Types ending with `E` are expression types, where all data properties are of type `RDExpression`, such as `RDRectE.Size`.
|
||||
The `Angle` property of `RotatedRect` is always a floating-point type and is not affected by the `I` naming convention.
|
||||
|
||||
`RDExpression` is used to store Rhythm Doctor expressions and attempts to parse and evaluate them (not fully implemented yet).
|
||||
It is created from a string and supports simple operations.
|
||||
The underlying implementation is string concatenation, so it is normal for nested parentheses to appear when performing multiple operations.
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
RDExpression exp1 = new("i2+1");
|
||||
RDExpression exp2 = new(30);
|
||||
RDExpression exp3 = new("25.5");
|
||||
|
||||
RDExpression result = exp1 - exp2 * exp3;
|
||||
|
||||
Console.WriteLine(result.ExpressionValue); // i2+1-765
|
||||
```
|
||||
### Creating and Modifying Events
|
||||
|
||||
All events directly or indirectly implement the `IBaseEvent` interface and inherit from the `BaseEvent` abstract type.
|
||||
You can use these interfaces and abstract types as generic parameters for query extension methods to filter events.
|
||||
For example,
|
||||
`BaseRowAction` and `BaseDecorationAction` are track events and sprite events, respectively,
|
||||
while `IRoomEvent` represents events with multi-room properties.
|
||||
The beat parameter used when creating an event can be unbound from any level; when the event is added to a level, it will be associated with that level, and when removed, the association will be broken.
|
||||
If no beat parameter is provided, it defaults to the first beat of the level.
|
||||
When calling the event's `ToString()` method, it will return a string in the format of the event's beat, event type, and displayable data.
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
using RhythmBase.RhythmDoctor.Events;
|
||||
|
||||
Comment comment = new() { Beat = new(12), Text = "My_comment." };
|
||||
Console.WriteLine(comment); // [11,?,?] Comment My_comment.
|
||||
|
||||
rdlevel.Add(comment);
|
||||
Console.WriteLine(comment); // [2,4] Comment My_comment.
|
||||
|
||||
rdlevel.Remove(comment);
|
||||
Console.WriteLine(comment); // [11,?,?] Comment My_comment.
|
||||
```
|
||||
|
||||
In particular, adding, modifying, or removing a `SetCrotchetsPerBar` event will update the timeline after this event, so you don't need to worry about changes affecting the order or arrangement of events; they will remain fixed at their absolute beat positions. The level will also attempt to add new `SetCrotchetsPerBar` events or remove adjacent events with the same `CrotchetsPerBar` property to maintain the stability of other segments.
|
||||
|
||||
Row and decoration events need to be added using `Add()` on the corresponding row or decoration, while removal can be done from the row, decoration, or level using the `Remove()` method.
|
||||
Repeated additions have no effect.
|
||||
The event types `Comment` and `TintRows` are not subject to this restriction.
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
using RhythmBase.RhythmDoctor.Events;
|
||||
|
||||
using RDLevel rdlevel = RDLevel.Default;
|
||||
|
||||
MoveRow tr = new();
|
||||
Console.WriteLine(rdlevel); // "" Count = 3
|
||||
|
||||
rdlevel.Add(tint); // "" Count = 3
|
||||
|
||||
rdlevel.Rows[0].Add(tr);
|
||||
Console.WriteLine(rdlevel); // "" Count = 4
|
||||
|
||||
rdlevel.Remove(tr);
|
||||
Console.WriteLine(rdlevel); // "" Count = 3
|
||||
```
|
||||
|
||||
### Custom Events
|
||||
|
||||
If the required event type is not available in this assembly, you can implement your own by inheriting from `CustomEvent`, `CustomRowEvent`, or `CustomDecorationEvent`.
|
||||
|
||||
```cs
|
||||
using Newtonsoft.RhythmDoctor.Json.Linq;
|
||||
using RhythmBase.RhythmDoctor.Events;
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
// Create a MyEvent type
|
||||
// Inherit from CustomEvent
|
||||
public class MyEvent : CustomEvent
|
||||
{
|
||||
// Override property
|
||||
public override Tabs Tab => Tabs.Actions;
|
||||
|
||||
// All implemented properties need to be bound to and checked for null in the CustomEvent.Data field.
|
||||
|
||||
// Implement an RDPointE type property
|
||||
public RDPointE? MyProperty
|
||||
{
|
||||
get
|
||||
{
|
||||
// Get the required content from the Data field and check for null
|
||||
var value = Data["myProperty"];
|
||||
return value?.ToObject<RDPointE?>() ?? new RDPointE(0, 0);
|
||||
}
|
||||
set
|
||||
{
|
||||
// Save the content in the Data field
|
||||
Data["myProperty"] =
|
||||
value.HasValue ?
|
||||
new JArray(
|
||||
value?.X ?? null,
|
||||
value?.Y ?? null) :
|
||||
null;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the type in the constructor
|
||||
public MyEvent()
|
||||
{
|
||||
// Initialize the ActureType property.
|
||||
ActureType = nameof(MyEvent);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
After writing your type, it can be read and written like a normal event.
|
||||
Note that `Type` is still `EventType.CustomEvent`, while `ActureType` is the custom type name.
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Events;
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
MyEvent myEvent = new();
|
||||
|
||||
rdlevel.Add(myEvent);
|
||||
|
||||
myEvent.Beat = new(8);
|
||||
|
||||
Console.WriteLine(myEvent.Type); // CustomEvent
|
||||
Console.WriteLine(myEvent.ActureType); // MyEvent
|
||||
```
|
||||
|
||||
Additionally, if an unknown event type is encountered when reading a level, it will also be read as the corresponding `CustomEvent`, `CustomRowEvent`, or `CustomDecorationEvent` type event.
|
||||
|
||||
### Event Types and Enums
|
||||
|
||||
All events have the `EaseType` property, and you can use methods in `EventTypeUtils` to convert and obtain the corresponding type.
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
using RhythmBase.RhythmDoctor.Events;
|
||||
using RhythmBase.RhythmDoctor.Utils;
|
||||
|
||||
Console.WriteLine(EventType.Tint.ToType()); // RhythmBase.Events.Tint
|
||||
Console.WriteLine(EventTypeUtils.ToType("Tint")); // RhythmBase.Events.Tint
|
||||
Console.WriteLine(EventTypeUtils.ToEnum(typeof(Tint))); // Tint
|
||||
Console.WriteLine(EventTypeUtils.ToEnum<Tint>()); // Tint
|
||||
Console.WriteLine(string.Join(", ", EventTypeUtils.ToEnums(typeof(IBarBeginningEvent)))); // PlaySong,SetCrotchetsPerBar, SetHeartExplodeVolume
|
||||
Console.WriteLine(string.Join(", ", EventTypeUtils.ToEnums<IBarBeginningEvent>())); // PlaySong,SetCrotchetsPerBar, SetHeartExplodeVolume
|
||||
```
|
||||
|
||||
`EventTypeUtils` also includes some event type classifications, such as:
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Utils;
|
||||
|
||||
Console.WriteLine(string.Join(",\n", EventTypeUtils.DecorationTypes));
|
||||
// Comment,
|
||||
// CustomDecorationEvent,
|
||||
// Move,
|
||||
// PlayAnimation,
|
||||
// SetVisible,
|
||||
// Tile,
|
||||
// Tint
|
||||
|
||||
Console.WriteLine(string.Join(",\n", EventTypeUtils.EventTypeEnumsForCameraFX));
|
||||
// MoveCamera,
|
||||
// ShakeScreen,
|
||||
// FlipScreen,
|
||||
// PulseCamera
|
||||
|
||||
Console.WriteLine(string.Join(",\n", EventTypeUtils.EventTypeEnumsForUtility));
|
||||
// Comment,
|
||||
// TagAction,
|
||||
// CallCustomMethod
|
||||
```
|
||||
|
||||
### Rich Text and Dialogue Components
|
||||
|
||||
The rich text components are located in the `RhythmBase.Components.RichText` namespace. You can use the `+` operator to combine rich text with custom colors. Serialization and deserialization of rich text are also supported.
|
||||
|
||||
`RDLine<>` represents a complete rich text line.
|
||||
`RDPhrase<>` is a style fragment of rich text, which follows a single style.
|
||||
You can use a struct that implements `IRDRichStringStyle<>` to specify the style rules for the rich text. In the example below, `RDRichStringStyle` is a rich text style that only includes color.
|
||||
|
||||
All can be implicitly converted from a string. Note that the converted text will be plain rich text without any style.
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
using RhythmBase.Global.Components.RichText;
|
||||
|
||||
RDLine<RDRichStringStyle> line = RDLine<RDRichStringStyle>.Deserialize("Hel<color=#00FF00>lo");
|
||||
|
||||
Console.WriteLine(line.ToString()); // Hello
|
||||
Console.WriteLine(line.Serialize()); // Hel<color=lime>lo</color>
|
||||
|
||||
line +=
|
||||
new RDPhrase<RDRichStringStyle>(" Rhythm")
|
||||
{
|
||||
Style = new()
|
||||
{
|
||||
Color = RDColor.Lime
|
||||
}
|
||||
};
|
||||
|
||||
line += " Doctor!";
|
||||
|
||||
Console.WriteLine(line.ToString()); // Hello Rhythm Doctor!
|
||||
Console.WriteLine(line.Serialize()); // Hel<color=lime>lo Rhythm</color> Doctor!
|
||||
```
|
||||
|
||||
Both `RDLine<>` and `RDPhrase<>` support index access and modification of their fragments.
|
||||
|
||||
```cs
|
||||
using RhythmBase.Global.Components.RichText;
|
||||
|
||||
RDLine<RDRichStringStyle> line = RDLine<RDRichStringStyle>.Deserialize("Hel<color=#00FF00>lo Rhythm</color> Doctor!");
|
||||
|
||||
Console.WriteLine(line[6..].ToString()); // Rhythm Doctor!
|
||||
Console.WriteLine(line[6..].Serialize()); // <color=lime>Rhythm</color> Doctor!
|
||||
|
||||
line[5] = " and Welcome to ";
|
||||
|
||||
Console.WriteLine(line.ToString()); // Hello and Welcome to Rhythm Doctor!
|
||||
Console.WriteLine(line.Serialize()); // Hel<color=lime>lo</color> and Welcome to <color=lime>Rhythm</color> Doctor!
|
||||
|
||||
return;
|
||||
```
|
||||
|
||||
This package also provides a complete set of dialogue components adapted to the Rhythm Doctor dialogue format, allowing you to modularly construct the text content of dialogue events and reduce error rates.
|
||||
|
||||
```cs
|
||||
using RhythmBase.Global.Components.RichText;
|
||||
|
||||
RDDialogueExchange exchange =
|
||||
[
|
||||
new RDDialogueBlock()
|
||||
{
|
||||
Character = "Paige",
|
||||
Expression = "neutral",
|
||||
Content = RDLine<RDDialoguePhraseStyle>.Deserialize("Hel<color=#00FF00>lo [2]<shake>Rhythm</color> Doctor</shake>!"),
|
||||
},
|
||||
new RDDialogueBlock()
|
||||
{
|
||||
Character = "Ian",
|
||||
Content = "Hello Paige!",
|
||||
},
|
||||
new RDDialogueBlock()
|
||||
{
|
||||
Character = "Paige",
|
||||
Expression = "happy",
|
||||
Content = new RDPhrase<RDDialoguePhraseStyle>("What a good day!")
|
||||
{
|
||||
Events =
|
||||
[
|
||||
new RDDialogueTone(RDDialogueToneType.VerySlow,6),
|
||||
new RDDialogueTone(RDDialogueToneType.Static,11),
|
||||
],
|
||||
Style = new RDDialoguePhraseStyle()
|
||||
{
|
||||
Volume = 0.5f,
|
||||
Bold = true,
|
||||
},
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
Console.WriteLine(exchange.Serialize());
|
||||
// Paige_neutral:Hel<color=lime>lo [2]<shake>Rhythm</color> Doctor</shake>!
|
||||
// Ian:Hello Paige!
|
||||
// Paige_happy:<volume=0.5><bold>What a[vslow] good[static] day!</volume></bold>
|
||||
```
|
||||
|
||||
### Easing
|
||||
|
||||
After importing `RhythmBase.Global.Components.Easing`, you can easily use the `EaseType` enum constants.
|
||||
You can also use the extension method `Calculate()` to quickly compute eased values.
|
||||
|
||||
```cs
|
||||
using RhythmBase.Global.Components.Easing;
|
||||
|
||||
double var1 = EaseType.InSine.Calculate(0.25);
|
||||
double var2 = EaseType.Linear.Calculate(0.5, 4, 9);
|
||||
|
||||
Console.WriteLine(var1); // 0.07612046748871326
|
||||
Console.WriteLine(var2); // 6.5
|
||||
```
|
||||
|
||||
`EaseValue` is a simple yet powerful struct. Thanks to mfgujhgh's algorithm, by using the static method `Fit()` to process arbitrary data, `EaseValue` can fit a curve usable by Rhythm Doctor events with a given selection of `EaseType`.
|
||||
|
||||
```cs
|
||||
using RhythmBase.Global.Components.Easing;
|
||||
|
||||
// Fit using a set of points and a threshold
|
||||
EaseValue data1 = EaseValue.Fit([
|
||||
(0, 0),
|
||||
(1, 1)
|
||||
], 3f);
|
||||
// Fit using an initial value, a set of points, an optional list of ease types, and a threshold
|
||||
EaseValue data2 = EaseValue.Fit(0, [
|
||||
(0, 0),
|
||||
(1, 1)
|
||||
], [EaseType.Linear, EaseType.InSine], 3f);
|
||||
// Get the value at a specific time from the easing data
|
||||
float value = data1.GetValue(2.5f);
|
||||
```
|
||||
|
||||
`RhythmBase.Extensions.EasePropertyExtensions` adds a `GetEaseProperties` method to types that implement `IEaseEvent`, which is used to obtain the easing curves for each property in a series of events.
|
||||
|
||||
```cs
|
||||
using RhythmBase.Global.Components;
|
||||
using RhythmBase.Global.Components.Easing;
|
||||
using RhythmBase.Global.Events;
|
||||
using RhythmBase.RhythmDoctor.Extensions;
|
||||
|
||||
var deco = level.Decorations[0];
|
||||
|
||||
Move[] moves =
|
||||
[
|
||||
new(){ Beat = level.BeatOf(1), Position = new(0, (RDExpression?)null), Duration = 1, Ease = EaseType.Linear, Angle = "2" },
|
||||
new(){ Beat = level.BeatOf(2.1f), Position = new(10, 90), Duration = 1, Ease = EaseType.Linear },
|
||||
new(){ Beat = level.BeatOf(2.2f), Position = new(90, 10), Duration = 1, Ease = EaseType.Linear },
|
||||
new(){ Beat = level.BeatOf(3), Position = new(10, 70), Duration = 1, Ease = EaseType.Linear },
|
||||
new(){ Beat = level.BeatOf(3.5f), Position = new(10, 10), Duration = 1, Ease = EaseType.Linear },
|
||||
new(){ Beat = level.BeatOf(3.8f), Position = new(30, 50), Duration = 1, Ease = EaseType.Linear },
|
||||
new(){ Beat = level.BeatOf(3.9f), Position = new(20, (RDExpression?)null), Duration = 1, Ease = EaseType.Linear },
|
||||
new(){ Beat = level.BeatOf(4.1f), Position = new(70, 20), Duration = 1, Ease = EaseType.Linear },
|
||||
new(){ Beat = level.BeatOf(4.4f), Position = new((RDExpression?)null, 0), Duration = 1, Ease = EaseType.Linear },
|
||||
];
|
||||
|
||||
deco.AddRange(moves);
|
||||
|
||||
var eases = EasePropertyExtensions.GetEaseProperties(moves);
|
||||
|
||||
foreach(var e in eases)
|
||||
Console.WriteLine(e);
|
||||
// [Position, RhythmBase.Components.Easing.EasePropertyPoint]
|
||||
// [Scale, RhythmBase.Components.Easing.EasePropertySize]
|
||||
// [Angle, RhythmBase.Components.Easing.EasePropertyFloat]
|
||||
// [Pivot, RhythmBase.Components.Easing.EasePropertyPoint]
|
||||
```
|
||||
|
||||
Types that implement the `IEaseProperty<>` interface, such as `EasePropertyColor`, `EasePropertyFloat`, `EasePropertyPoint`, and `EasePropertySize`, are used to store the content from a list of easing events.
|
||||
You can also get the value at a specific time.
|
||||
|
||||
> Before calling, please check the value type of the property and apply the appropriate type conversion.
|
||||
|
||||
```cs
|
||||
using RhythmBase.Global.Components.Easing;
|
||||
|
||||
var result = ((EasePropertyPoint)eases["Position"]).GetValue(rdlevel.BeatOf(3.2f));
|
||||
|
||||
Console.WriteLine(result); // [59.759995, 21.840006]
|
||||
```
|
||||
|
||||
### RDCode (Under Revision)
|
||||
|
||||
`RhythmBase.Components.RDLang.RDLang` provides a `TryRun()` method for evaluating Rhythm Doctor expressions.
|
||||
|
||||
> Note: If the expression is incorrect, it will return `false` and the result will be `0`.
|
||||
|
||||
`RDLang` also has a static field `Variables` for storing all commonly used variables and methods. Modifying this field before executing `TryRun` will affect the values during execution.
|
||||
`RDLang` also supports three common methods: `Rand()`, `atLeastRank()`, and `atLeastNPerfects()`. These methods can also be accessed via `RDVariables`.
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components.RDLang;
|
||||
|
||||
RDLang.Variables.i[1] = 9;
|
||||
|
||||
RDLang.TryRun("numMistakesP2 = 3", out float result); // 3
|
||||
RDLang.TryRun("numMistakesP2+i1", out result); // 12
|
||||
RDLang.TryRun("atLeastRank(A)", out result); // 1
|
||||
```
|
||||
Since this library does not support dynamic level playback, you can use the following fields to simulate the effects of the last two functions:
|
||||
- `atLeastRank()`
|
||||
Use the `RDVariables.SimulateCurrentRank` property to change the simulated level rank state.
|
||||
When the expression accesses the `atLeastRank()` method, this value will be used for simulation.
|
||||
- `atLeastNPerfects()`
|
||||
Use the `RDVariables.SimulateAtLeastNPerfectsSuccessRate` property to change the simulated percentage of perfect hits.
|
||||
When the expression accesses the `atLeastNPerfects()` method, this value will be used for simulation.
|
||||
|
||||
### Event Groups
|
||||
|
||||
Declare and use it like a new event, and it will generate level events according to your specifications!
|
||||
|
||||
By inheriting from the `Group` class and implementing new logic as shown below, you can freely manipulate it just like other events.
|
||||
Unlike `CustomEvent`, it writes the specified sequence of events into the level instead of itself.
|
||||
|
||||
```cs
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.RhythmDoctor.Events;
|
||||
|
||||
public class GroupData1
|
||||
{
|
||||
public RDSize Size;
|
||||
public int RowIndex;
|
||||
}
|
||||
|
||||
public class MoveCameraRectangle : Group<GroupData1>
|
||||
{
|
||||
public RDSize Size
|
||||
{
|
||||
get => Data.Size;
|
||||
set => Data.Size = value;
|
||||
}
|
||||
public Row Row
|
||||
{
|
||||
get => Rows?[Data.RowIndex] ?? [];
|
||||
set => Data.RowIndex = value.Index;
|
||||
}
|
||||
public MoveCameraRectangle() { }
|
||||
public override IEnumerable<BaseEvent> GenerateEvents()
|
||||
{
|
||||
yield return new MoveCamera() { Beat = new(1), Rooms = new(true, 0), CameraPosition = new(50 - Size.Width / 2, 50 - Size.Height / 2), Duration = 1 };
|
||||
yield return new MoveCamera() { Beat = new(2), Rooms = new(true, 0), CameraPosition = new(50 + Size.Width / 2, 50 - Size.Height / 2), Duration = 1 };
|
||||
yield return new MoveCamera() { Beat = new(3), Rooms = new(true, 0), CameraPosition = new(50 + Size.Width / 2, 50 + Size.Height / 2), Duration = 1 };
|
||||
yield return new MoveCamera() { Beat = new(4), Rooms = new(true, 0), CameraPosition = new(50 - Size.Width / 2, 50 + Size.Height / 2), Duration = 1 };
|
||||
yield return SetParent(new MoveRow() { Beat = new(1), RowPosition = new(50, 50), CustomPosition = true, Duration = 0 }, Row);
|
||||
yield return SetParent(new MoveRow() { Beat = new(1.001f), RowPosition = new(50 - Size.Width / 2, 50 - Size.Height / 2), CustomPosition = true, Duration = 1 }, Row);
|
||||
yield return SetParent(new MoveRow() { Beat = new(2), RowPosition = new(50 + Size.Width / 2, 50 - Size.Height / 2), CustomPosition = true, Duration = 1 }, Row);
|
||||
yield return SetParent(new MoveRow() { Beat = new(3), RowPosition = new(50 + Size.Width / 2, 50 + Size.Height / 2), CustomPosition = true, Duration = 1 }, Row);
|
||||
yield return SetParent(new MoveRow() { Beat = new(4), RowPosition = new(50 - Size.Width / 2, 50 + Size.Height / 2), CustomPosition = true, Duration = 1 }, Row);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note that this operation can be resource-intensive, so `LevelReadOrWriteSettings` disables this option by default.
|
||||
The underlying logic is that it attaches a special tag to each event in the sequence to mark it as "generated", so that these generated events can be cleaned up the next time events are read. For events that already have tags, there is an extra layer of logic to encapsulate them.
|
||||
|
||||
```cs
|
||||
using RhythmBase.Global.Settings;
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
|
||||
LevelReadOrWriteSettings settings = new()
|
||||
{
|
||||
EnableGroupEvent = true,
|
||||
InactiveEventsHandling = InactiveEventsHandling.Retain,
|
||||
Indented = true
|
||||
};
|
||||
|
||||
using RDLevel level = RDLevel.Default;
|
||||
level.Decorations.Add(new Decoration() { Room = RDRoomIndex.Room1 });
|
||||
var re1 = new MoveCameraRectangle() { Beat = new(4), Size = new RDSize(80, 80) };
|
||||
var re2 = new MoveCameraRectangle() { Beat = new(9), Y = 2, Size = new RDSize(20, 20) };
|
||||
level.Add(re1);
|
||||
level.Add(re2);
|
||||
level.Write(dstPath, settings);
|
||||
|
||||
// The following events will be generated:
|
||||
// {"bar":1,"beat":1,"type":"MoveCamera","rooms":[0],"cameraPosition":[10,10],"duration":1,"ease":"Linear","y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000000"},
|
||||
// {"bar":1,"beat":1,"type":"MoveRow","customPosition":true,"target":"WholeRow","rowPosition":[50,50],"duration":0,"ease":"Linear","row":0,"y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000000"},
|
||||
// {"bar":1,"beat":1.001,"type":"MoveRow","customPosition":true,"target":"WholeRow","rowPosition":[10,10],"duration":1,"ease":"Linear","row":0,"y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000000"},
|
||||
// {"bar":1,"beat":2,"type":"MoveCamera","rooms":[0],"cameraPosition":[90,10],"duration":1,"ease":"Linear","y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000000"},
|
||||
// {"bar":1,"beat":2,"type":"MoveRow","customPosition":true,"target":"WholeRow","rowPosition":[90,10],"duration":1,"ease":"Linear","row":0,"y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000000"},
|
||||
// {"bar":1,"beat":3,"type":"MoveCamera","rooms":[0],"cameraPosition":[90,90],"duration":1,"ease":"Linear","y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000000"},
|
||||
// {"bar":1,"beat":3,"type":"MoveRow","customPosition":true,"target":"WholeRow","rowPosition":[90,90],"duration":1,"ease":"Linear","row":0,"y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000000"},
|
||||
// {"bar":1,"beat":4,"type":"MoveCamera","rooms":[0],"cameraPosition":[10,90],"duration":1,"ease":"Linear","y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000000"},
|
||||
// {"bar":1,"beat":4,"type":"MoveRow","customPosition":true,"target":"WholeRow","rowPosition":[10,90],"duration":1,"ease":"Linear","row":0,"y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000000"},
|
||||
// {"bar":1,"beat":1,"type":"MoveCamera","rooms":[0],"cameraPosition":[40,40],"duration":1,"ease":"Linear","y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000001"},
|
||||
// {"bar":1,"beat":1,"type":"MoveRow","customPosition":true,"target":"WholeRow","rowPosition":[50,50],"duration":0,"ease":"Linear","row":0,"y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000001"},
|
||||
// {"bar":1,"beat":1.001,"type":"MoveRow","customPosition":true,"target":"WholeRow","rowPosition":[40,40],"duration":1,"ease":"Linear","row":0,"y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000001"},
|
||||
// {"bar":1,"beat":2,"type":"MoveCamera","rooms":[0],"cameraPosition":[60,40],"duration":1,"ease":"Linear","y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000001"},
|
||||
// {"bar":1,"beat":2,"type":"MoveRow","customPosition":true,"target":"WholeRow","rowPosition":[60,40],"duration":1,"ease":"Linear","row":0,"y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000001"},
|
||||
// {"bar":1,"beat":3,"type":"MoveCamera","rooms":[0],"cameraPosition":[60,60],"duration":1,"ease":"Linear","y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000001"},
|
||||
// {"bar":1,"beat":3,"type":"MoveRow","customPosition":true,"target":"WholeRow","rowPosition":[60,60],"duration":1,"ease":"Linear","row":0,"y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000001"},
|
||||
// {"bar":1,"beat":4,"type":"MoveCamera","rooms":[0],"cameraPosition":[40,60],"duration":1,"ease":"Linear","y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000001"},
|
||||
// {"bar":1,"beat":4,"type":"MoveRow","customPosition":true,"target":"WholeRow","rowPosition":[40,60],"duration":1,"ease":"Linear","row":0,"y":-1,"tag":"$RhythmBase_GroupEvent$0000000000000001"},
|
||||
// {"bar":1,"beat":1,"type":"Comment","tab":"Song","show":false,"text":"$RhythmBase_GroupData$\r\n/* Generated by RhythmBase */\r\n@MoveCameraRectangle\r\n@MoveCameraRectangle2\r\n@RhythmBase.RhythmDoctor.Events.Group\r\n@RhythmBase.RhythmDoctor.Events.Group`1\r\n{\"size\":[80.0,80.0],\"rowIndex\":0}\r\n{\"size\":[20.0,20.0],\"rowIndex\":0}\r\n","color":"F2E644","y":-1},
|
||||
// {"bar":1,"beat":4,"type":"TagAction","Tag":"$RhythmBase_GroupEvent$0000000000000000","y":0,"tag":"","Action":"Run"},
|
||||
// {"bar":2,"beat":1,"type":"TagAction","Tag":"$RhythmBase_GroupEvent$0000000000000001","y":2,"tag":"","Action":"Run"},
|
||||
```
|
||||
|
||||
## Examples
|
||||
### Merging Audio and Visual Levels
|
||||
|
||||
```cs
|
||||
using RhythmBase.RhythmDoctor.Components;
|
||||
using RhythmBase.RhythmDoctor.Events;
|
||||
using RhythmBase.RhythmDoctor.Extensions;
|
||||
|
||||
// Read the visual effects level file
|
||||
using RDLevel vfxLevel = RDLevel.Read(@"vfx.rdlevel");
|
||||
// Read the audio level file
|
||||
using RDLevel audioLevel = RDLevel.Read(@"beat.rdlevel");
|
||||
|
||||
// Remove all rows from the visual effects level
|
||||
RowEventCollection[] vfxrows = [.. vfxLevel.Rows];
|
||||
foreach (var row in vfxrows)
|
||||
vfxLevel.Rows.Remove(row);
|
||||
|
||||
// Copy all rows from the audio level into the new level
|
||||
foreach (var row in audioLevel.Rows)
|
||||
{
|
||||
// Copy row information
|
||||
Row row2 = new()
|
||||
{
|
||||
Rooms = row.Rooms,
|
||||
Character = row.Character,
|
||||
Sound = row.Sound,
|
||||
RowType = row.RowType
|
||||
};
|
||||
vfxLevel.Rows.Add(row2);
|
||||
|
||||
// Copy events within the row
|
||||
BaseBeat[] evts = [.. row.Where<BaseBeat>()];
|
||||
foreach (var evt in evts)
|
||||
row2.Add(evt);
|
||||
}
|
||||
|
||||
// Copy necessary sound events
|
||||
foreach (var sound in audioLevel.Where(e =>
|
||||
e.Tab == Tabs.Sounds && // Event is in the Sounds tab
|
||||
e is not BaseRowAction && // Sound events contain row events; adding row events here would cause reference errors
|
||||
e is not PlaySong && // No need to copy PlaySong if the music is the same
|
||||
e is not SetCrotchetsPerBar)) // The timing of these events is independent of the number of crotchets per bar, so they don't need to be added
|
||||
{
|
||||
vfxLevel.Add(sound);
|
||||
}
|
||||
|
||||
// Write to a new level file
|
||||
vfxLevel.Write(@"result.rdlevel");
|
||||
```
|
||||
@@ -0,0 +1,241 @@
|
||||
# 窗口相关的动画
|
||||
|
||||
在1.0正式版更新后,窗口被单独提取成了一个独立的板块:**窗口板块**。为了避免剧透,这个板块默认是隐藏的,要让这个板块显示出来,我们需要在动作板块先放一个窗口动效事件,或者在编辑器设置中的显示窗口标签栏设置为**总是报告**,这个板块才会显示出来。
|
||||
|
||||

|
||||
|
||||
我们可以看到,窗口事件比以前多了很多。而且4个窗口都像房间板块一样每个窗口都占了一行。所有事件都只会对其所在行对应的窗口生效。接下来将会介绍这些事件的作用和使用方法。
|
||||
|
||||
## 隐藏窗口
|
||||
|
||||
窗口的显示和隐藏都在这个事件中,窗口默认只有窗口1是显示,其他窗口默认都是隐藏的,所以如果你需要操作其他窗口,需要把窗口显示出来再进行操作。
|
||||
|
||||
如果需要使用透明窗口,记得把背景颜色设置为透明(顶部的背景也要)
|
||||
|
||||
窗口板块中隐藏状态的窗口会显示灰色,可以通过这个判断你的窗口有没有忘记显示出来。
|
||||
|
||||

|
||||
|
||||
## 窗口动效
|
||||
|
||||
### 移动
|
||||
|
||||
移动跟**移动房间**事件一样,坐标填多少就移动到哪。
|
||||
|
||||

|
||||
|
||||
需要注意的是参照,影响的是窗口移动的范围,这两个选项的具体情况如下:
|
||||
|
||||
`居中`的范围是整个屏幕,如果将位置设置为(0,0),那么窗口只会露出一个角;
|
||||
|
||||
`边缘`的范围是整个屏幕减去窗口大小,如果将位置设置为(0,0),那么窗口的左下角将对齐屏幕左下角。
|
||||
|
||||

|
||||
|
||||
### 摇摆
|
||||
|
||||
使窗口按特定速度和方向来回移动。
|
||||
|
||||
**位置:** 初始位置;
|
||||
|
||||
**增幅:** 移动的幅度;
|
||||
|
||||
**角度:** 来回移动的方向,0度为向右;
|
||||
|
||||
**频率:** 每拍移动多少次;
|
||||
|
||||
**运动缓速:** 每次移动时用的缓速;
|
||||
|
||||
**缓速类型:** 偶数次移动可以设置成相同的缓速或者镜像(如从快到慢镜像后就是从慢到快)。
|
||||
|
||||

|
||||
|
||||
### 缠绕
|
||||
|
||||
像缠胶带一样将窗口绕着屏幕旋转。
|
||||
|
||||
**位置:** 初始位置;
|
||||
|
||||
**速度:** 每拍移动多少距离(一圈的百分之n);
|
||||
|
||||
**增幅:** 往另一个方向`摇摆`的距离(与移动方向垂直);
|
||||
|
||||
**角度:** 移动的方向,0度为向右;
|
||||
|
||||
**频率:** `摇摆`的频率(每拍移动多少次)。
|
||||
|
||||

|
||||
|
||||
### 椭圆
|
||||
|
||||
将窗口绕着一点旋转。
|
||||
|
||||
**位置:** 旋转中心;
|
||||
|
||||
**速度:** 每拍转多少度`(360° * n%)`;
|
||||
|
||||
**使用循环:** 文本
|
||||
|
||||
**增幅:** X轴和Y轴方向分别远离这个点多远;
|
||||
|
||||
**角度:** 从哪个角度开始旋转。
|
||||
|
||||

|
||||
|
||||
### 震动
|
||||
|
||||
震动窗口,跟震动摄像机一样。
|
||||
|
||||
**位置:** 初始位置;
|
||||
|
||||
**增幅:** 震动时X轴和Y轴方向最远能到哪;
|
||||
|
||||
**频率:** 每拍震动多少次;
|
||||
|
||||
**周期:** 每多少拍震动的移动会重复;
|
||||
|
||||
**运动缓速:** 每次震动时移动的缓速。
|
||||
|
||||

|
||||
|
||||
|
||||
时长和缓速前面都说过了,就不再提了。
|
||||
|
||||
> 如果你想直观地看看各种移动方式的速度区别,可以[看看这里](https://easings.net/zh-cn)。
|
||||
|
||||
|
||||
## 窗口大小重置
|
||||
|
||||
想要让窗口大小发生变化,或调整窗口的轴点,都需要借助**窗口大小重置**事件。这个事件的设置项目是这样的:
|
||||
|
||||

|
||||
|
||||
**大小:** 窗口的目标大小,最大可以设置为`200%, 200%`,如果`x`和`y`同时被设置为了0,则窗口会立刻被重置为初始的大小(即`100%, 100%`)。
|
||||
|
||||
**缩放模式:** 窗口大小发生变化时内容的缩放模式,具体如下:
|
||||
<ul>
|
||||
<li><strong>填充:</strong>将画面中的内容尽可能的填满窗口</li>
|
||||
<li><strong>适应:</strong>将画面中的内容尽可能放进窗口</li>
|
||||
<li><strong>无:</strong>保持窗口中原来内容的大小不变</li>
|
||||
</ul>
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
> 如果你的窗口在大小发生变化前后长宽比不变,那么**填充**和**适应**在效果上没有区别。
|
||||
|
||||
**轴点模式:** 有**默认**和**锚点边缘**两种模式,选择**默认**即和房间移动的轴点没有区别,选择**锚点边缘**则表示选择一条边缘固定不动的情况下进行大小的缩放。
|
||||
|
||||
> 实际上选择锚点边缘的情况下就是由系统计算轴点的位置,因此在锚点边缘选择左或右时不要把`x`设置为`0%`,在锚点边缘选择上或下时不要把`y`设置为`0%`,否则会出现bug,表现为对应窗口会消失且**无法被任何方式**移动回来,即使通过事件恢复了窗口的大小和轴点。
|
||||
|
||||
**轴点:** 设置位置和缩放的基准点,类似于精灵图和房间的轴点,此处不再赘述。
|
||||
|
||||
**动画时长和缓速:** 见过多次了,不再赘述。
|
||||
|
||||
> 如果你想直观地看看各种移动方式的速度区别,可以[看看这里](https://easings.net/zh-cn)。
|
||||
|
||||
### 轴点的使用技巧
|
||||
|
||||
我们知道,在窗口大小发生变化时,调整轴点可以改变其缩放的中心。但是实际上,即使窗口不需要缩放,我们也可以通过调整轴点来改变窗口的位置,那么这种操作从效果上看和直接使用窗口移动看似没有什么区别,实际上在一些特殊的需求中,这个方法可以被很巧妙地使用。
|
||||
|
||||
窗口在移动时,使用的坐标是相对整个屏幕的,而由于不同设备的屏幕分辨率不同,导致有些效果如果用窗口移动来做会在不同分辨率下有不同效果,尤其是当多个窗口之间的位置有配合的时候(如两个窗口紧贴的效果)。
|
||||
|
||||
如在16:9的分辨率下制作的两个窗口紧挨着的效果:
|
||||
|
||||

|
||||
|
||||
在其他分辨率下,即使不改变窗口的位置,也可能会有不同的效果(如在22:9分辨率下):
|
||||
|
||||

|
||||
|
||||
如果想要做出在类似`2-XN`中两个窗口相撞的效果,窗口中间有距离会导致表演效果大打折扣。这时我们可能会想,能不能不以屏幕为基准定位,而是以窗口的大小为基准定位,是不是就可以做到了呢?
|
||||
|
||||
事实上,**轴点**就解决了这样的问题。
|
||||
|
||||
试想,如果两个窗口在同一个位置,而一个窗口的轴点在左边缘,另一个窗口在右边缘,就可以保证无论在什么样的分辨率下,这两个窗口都一定是紧挨着的。
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
所以当你的动画需要多个窗口之间的位置配合时,不妨试试用轴点的移动来代替直接移动窗口。
|
||||
|
||||
## 设置窗口内容
|
||||
|
||||
~~这个事件以前翻译错误,译成了**设置窗口数量**,害人不浅。~~
|
||||
|
||||
这个事件的设置项目是这样的:
|
||||
|
||||

|
||||
|
||||
**内容模式:** 可以选择**一个房间**或**全部房间**,在选择**一个房间**时,下面会出现**房间目录**选项,可以从4个房间里面选择一个,随后这个窗口中只会显示这个房间的内容。在选择全部房间时,这个窗口将会像平常一样显示全部4个房间的内容。
|
||||
|
||||
> 注意,在选择**一个房间**时,这个房间中的所有房间事件都不会在这个窗口中生效,包括房间移动,淡入淡出房间,房间遮罩等。
|
||||
|
||||

|
||||
|
||||
**位置,缩放和角度:** 类似于摄像头移动的对应参数。
|
||||
|
||||
在内容模式为**一个房间**时,等同于调用房间的摄像头,`位置`是对应房间区域的对应坐标(左下角是`(0%, 0%)`,右上角是`(100%, 100%)`);
|
||||
|
||||
在选择**全部房间**时,等同于调用顶部摄像头,而所有房间可显示的范围为`(200%, 200%)`大小,所以当`位置`设置为`(100%, 100%)`时,实际会在(相对于一个房间默认大小的)`(200%, 200%)`的位置,默认位置的房间的`(100%, 100%)`则在`(75%, 75%)`的位置。
|
||||
|
||||
根据这个结论,可以将4个房间分别放在显示区域的四个角上,并显示`全部房间`,这样就能用`全部房间`分别显示4个房间了
|
||||
|
||||

|
||||
|
||||
无论选择哪种内容模式,超出区域范围的内容都会被裁剪。
|
||||
|
||||
**时长和缓速:** 略
|
||||
|
||||
## 重新排列窗口
|
||||
|
||||
类似于房间板块的**重新排列房间**,可以设置窗口的上下关系。
|
||||
|
||||
## 设置主窗口
|
||||
|
||||
将对应的窗口设置为主窗口,对话,顶部护士灯光,状态牌等内容将在主窗口显示。
|
||||
|
||||
## 设置窗口名称
|
||||
|
||||
修改窗口的标题。在动作选择**设置**的时候,会直接设置窗口的标题;在动作选择**增补**的时候,会在原来标题的后面增加内容;在动作选择**重置**的时候,会将标题重置为`Rhythm Doctor`。
|
||||
|
||||
## 设置桌面颜色
|
||||
|
||||
修改模拟移动时桌面的颜色,如果不打开起始颜色,则表示从当前颜色渐变为结束颜色,如果打开起始颜色,效果将类似于**自定义闪烁**。
|
||||
|
||||
## 进阶内容(可能需要手术)
|
||||
|
||||
> 如果你不知道手术是什么,可以[看看这里](https://docs.qq.com/sheet/DQUJxb0puSFFOVWpz?tab=000004)。
|
||||
|
||||
### 全屏窗口
|
||||
|
||||
因为窗口的最大大小写死了只能为200%,所以需要用到`OutElastic`缓速。
|
||||
|
||||
> 如果你忘了这个缓速长什么样,可以[看看这里](https://easings.net/zh-cn)。
|
||||
|
||||
注意到这个缓速的一部分会超出所设置的值,所以可以先将窗口缩小到`(1%,1%)`大小,然后使用`OutElastic`缓速将窗口缩放到`(200%,200%)`大小,当窗口变大的过程中会有几帧是占满整个屏幕的,此时放一个大小为`(200%,200%)`、时长为999、缓速为`Linear`的**窗口大小重置事件**,窗口大小就会固定成全屏的了。
|
||||
|
||||
> 使用注释指令`()=>windowSize(float SizeX%, float SizeY%, float duration)`可以直接将窗口缩放到200%以上,但这个方法只能控制窗口1的大小,还没有缓速。
|
||||
|
||||
### 更多窗口(暂时不确定官方会不会修这个)
|
||||
|
||||
在谱面中放置一个窗口相关的事件(这个例子用`隐藏窗口`事件),记住这个事件的小节、节拍和在第几行,然后打开这个谱面的文件(xxx.rdlevel),找到{ "bar": <小节>, "beat": <节拍>, "y": <行数减一>, "type": "HideWindow", "show": true },这一行,<>里面应该是你记住的数据,将"y": 后面的数替换成一个大于3的数,保存并返回编辑器,重新打开这个谱面,就会发现这个事件到第4行下面了,接着当正常窗口使用就行。
|
||||
|
||||
如果想要`重新排列窗口`,同上,找到"ReorderWindows", "order": [0, 1, 2, 3],在[]中加上 窗口的编号减一 的数,还有逗号。
|
||||
|
||||
窗口事件名称表:
|
||||
|
||||
| 事件 | 名称 |
|
||||
| :--- | :--- |
|
||||
| 窗口动效 | NewWindowDance |
|
||||
| 重置窗口大小 | WindowResize |
|
||||
| 设置窗口内容 | SetWindowContent |
|
||||
| 重新排列窗口 | ReorderWindows |
|
||||
| 隐藏窗口 | HideWindow |
|
||||
| 设置主窗口 | SetMainWindow |
|
||||
| 设置窗口名称 | RenameWindow |
|
||||
| 设置桌面颜色 | DesktopColor |
|
||||
|
||||
当然,如果你不想手术,可以安装[这个模组](https://github.com/9thCore/RDEditorPlus/releases)(b站有安装教程)
|
||||
@@ -44,3 +44,56 @@
|
||||
举个例子,假如你的设备输入延迟比较大,又或者你用的是蓝牙耳机,更甚至是Steam远程畅玩或是和好友远程玩双人关卡,此时你会发现,你按下空格键,会等大概一秒钟才会听到空拍音效,节奏点也会因为网络延迟延后判断,通常这时候我们会通过调整输入偏移来解决,但即使是调整了输入偏移,你在按空拍的时候还是会因为网络延迟等原因延后一秒钟才会播放空拍音效。
|
||||
|
||||
这也就是为什么说空拍音效的响起会对后续节奏判断产生影响了,偏移量小的玩家还没什么,无非就是多响一声而已,但偏移量大的玩家呢?所以制作过程中尽量不要让玩家在没有节拍的位置误认为有节拍并按了一个空拍,毕竟如果延迟比较大的话,这种误导性影响还是挺大的。
|
||||
|
||||
### *7、 使用屏幕朗读事件
|
||||
|
||||
官方在v0.19.0无障碍更新中加入了屏幕朗读事件,以为视障玩家群体提供更多支持。
|
||||
|
||||
> 为你的关卡添加屏幕朗读事件是可选的,但是请确保你正确使用了事件。同时,你**不应该**:
|
||||
>
|
||||
> - 添加会干扰正常游玩的屏幕朗读事件(如场景描述与画面不符、对轨道的错误提示等);
|
||||
> - 将屏幕朗读事件作为谱面玩法的一部分(除非在关卡描述中特别说明)。
|
||||
|
||||
在继续之前,请确保在`设置>易用性设置>朗读设置`中启用了`朗读`。
|
||||
|
||||
阅读[关卡屏幕阅读器的适配测试指南](https://docs.qq.com/doc/DUVJVc1pjam1uT1R6)以了解如何配置屏幕朗读。
|
||||
|
||||
另外,推荐在启用朗读的情况下先游玩官谱以作参考。
|
||||
|
||||
#### 朗读轨道信息
|
||||
|
||||

|
||||
|
||||
**轨道**:选择要朗读哪条轨道的信息。
|
||||
|
||||
**类型**:“**患者上线**”表示新的轨道被引入;“**患者更新**”表示某条轨道的行为模式改变;“**患者离线**”表示某条轨道在当前谱面不再被使用。
|
||||
“**医生上线**”“**医生离线**”与“**患者上线**”“**患者离线**”类似,只不过由电脑操控。
|
||||
|
||||
**仅声音提示**:启用该选项时,游戏将不会朗读该提示的类型。
|
||||
|
||||
**朗读X字拍子**:选择**开启**时,游戏将会朗读该轨道当前的X字拍子。选择**自定义**时,将会朗读玩家自定义的X字拍子,而不是轨道当前的X字拍子。例如,对于`----xx ---♥`,游戏会朗读“X拍56”;而当轨道没有X字拍子时,游戏会朗读“无X拍”。
|
||||
|
||||
**紊乱**:用于提示X字拍子连续变化的节拍(例如`X-WOT`)。
|
||||
|
||||
**玩家**:选择在双人模式下,该轨道由哪位玩家接管。
|
||||
|
||||
**自定义长度**:启用后将朗读所填的轨道长度。
|
||||
|
||||
一般情况下,游戏会按以下的顺序来朗读:
|
||||
|
||||
`[玩家][类型][轨道角色][X字拍子]`
|
||||
|
||||
#### 朗读口述
|
||||
|
||||
**口述内容**:游戏朗读的内容。
|
||||
|
||||
**朗读分类**:该朗读事件的类别。下面是官方对朗读分类的说明:
|
||||
|
||||
- 提示:适用于常规屏幕文字提示,“状态标识”信息默认归入此类。
|
||||
|
||||
- 描述:“朗读口述”事件的默认分类,专用于呈现纯视觉信息(如角色动画、背景环境等)。玩家可按`F6`键切换此类播报。
|
||||
|
||||
- 字幕:"浮动文字"事件的默认分类,适用于语音内容字幕(如歌词字幕),支持多语言翻译。玩家可按`F7`键切换此类播报。
|
||||
|
||||
- 说明:专用于游戏控制说明。播报后,玩家可随时按`F1`键重复听取当前指引(直至下一条指引信息覆盖)。
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
| sndPoliticianHurryUp3 | 政客说:Make a move already, would you? |
|
||||
| sndPoliticianHurryUp4 | 政客说:Oh, bloody hell. Hurry up already! |
|
||||
|
||||
### 在EA版本中出现的音效
|
||||
### 在正式版本中使用的音效
|
||||
|
||||
| 音效名 | 内容 |
|
||||
| :--- | :--- |
|
||||
@@ -160,10 +160,20 @@
|
||||
| sndWhistle5 | 口哨声第5拍 |
|
||||
| sndWhistle7 | 口哨声第7拍 |
|
||||
| sndApplause | 鼓掌声 |
|
||||
| sndRowShrink | 轨道缩短声 |
|
||||
| sndSkate1 | <code>MD-3</code>内布若拍子用到的提示音(准备) |
|
||||
| sndSkate2 | <code>MD-3</code>内布若拍子用到的提示音(释放) |
|
||||
| sndSquareshot | 哐啷声 |
|
||||
| sndTriangleshot1 | 三角拍子声(后面的数字可改为1~10) |
|
||||
| sndSleighHi | 圣诞树节拍器 - 高 |
|
||||
| sndSleighLo | 圣诞树节拍器 - 低 |
|
||||
| sndCalibrationBeep | 校准界面哔声 |
|
||||
| sndMelonMorse | Melon 摩尔斯电码 |
|
||||
| sndVividStasisResultsRiser | <code>X-FTS</code>恋恋群星S+评价前摇 |
|
||||
| sndVividStasisScratch | <code>X-FTS</code>恋恋群星V评价出现 |
|
||||
| sndWingFlap | 鸟儿扇动翅膀 |
|
||||
|
||||
### 未使用的音效
|
||||
### 未在正式版本中使用的音效
|
||||
|
||||
| 音效名 | 内容 |
|
||||
| :--- | :--- |
|
||||
@@ -245,7 +255,7 @@
|
||||
| sndLowHealthCSharpA | 低血量警告音 CA# |
|
||||
| sndLowHealthE | 低血量警告音 E |
|
||||
|
||||
### 在EA版本中出现的音乐
|
||||
### 在正式版本中出现的音乐
|
||||
|
||||
| 音效名 | 内容 | 曲速 |
|
||||
| :--- | :--- | :--- |
|
||||
@@ -262,27 +272,114 @@
|
||||
| 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 |
|
||||
| sndTutorialMilonga | <code>5-3N</code>的教程音乐 | 88 |
|
||||
| sndTutorialMilongaPrelude | <code>5-3N</code>的教程音乐前奏 | 88 |
|
||||
| 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 |
|
||||
| sndIntimate | <code>1-2</code>亲密 | 90 |
|
||||
| sndIntimate2P | 在双人模式下的<code>1-2N</code>亲密 | 90 |
|
||||
| sndOrientalInsomniac | <code>1-X</code>东方不眠夜 | 180 |
|
||||
| sndOrientalInsomniac1 | <code>1-X</code> 东方不眠夜 第一部分 | |
|
||||
| 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->196-->231->255-->196 |
|
||||
| sndBitternessCutscene | <code>2-XN</code>Bitter Times 爱情是苦和甜的交错后半段 | |
|
||||
| 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 |
|
||||
| sndLesMisBar1 | <code>3-X</code>轮班之歌 | 100 |
|
||||
| sndLesMisBar39 | <code>3-X</code>轮班之歌 从第39小节开始 | |
|
||||
| sndLesmisDog | 节奏狗生 | 100 |
|
||||
| sndMinersong | <code>4-1</code>实习医生培训演练表现评估 | 128 |
|
||||
| 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-1N</code>One Slip Too Late 创伤之歌 | 175->150->175 |
|
||||
| sndOSTLCN | <code>5-1N</code>One Slip Too Late 创伤之歌中文版 | 175->150->175 |
|
||||
| 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>偕老 | 248 |
|
||||
| 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-->200->210-->181->198? |
|
||||
| sndHaileyDuetCN | <code>6-1</code>想把心事和你说中文版 | 94.5-->190-->200->210-->181->198? |
|
||||
| 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 |
|
||||
| sndVividStasisResults | <code>X-FTS</code>恋恋群星V评价结算音乐 | 150 |
|
||||
| sndOsmBluesRadio | 夜间的病房内过剧情 | 98? |
|
||||
| sndOsmBluesNormal | 袖管涂鸦背景音乐 | 98? |
|
||||
| sndInsomniacCutscene | 1-X后过剧情 | 140 |
|
||||
| SoftPianoIntimate | 第一章末尾的过剧情 | 88 |
|
||||
| sndDistantDuetCutsceneLoop | 3-3后过剧情 | 165 |
|
||||
| sndDDSPianoCutsceneLoop | 5-X后过剧情第一部分 | 130 |
|
||||
| sndDDSEdegaCutscene | 5-X后过剧情第一部分(埃德加来) | 140 |
|
||||
| sndDDSVirusTalkCutsceneLoop | 5-X后过剧情(伊恩来) | 105 |
|
||||
| sndMarksTheme | 病历间音乐 | 110 |
|
||||
| sndBlurredCutscene | 7-1后过剧情 | 63? |
|
||||
| sndPaigeReturnsCutscene | 佩奇回来 | 157? |
|
||||
| sndEdegaBedsidePaigeCutscene | 7-X2后埃德加住院 | 58? |
|
||||
|
||||
### 未使用的音乐
|
||||
### 未在正式版本中出现的音乐
|
||||
|
||||
| 音效名 | 内容 | 曲速 |
|
||||
| :--- | :--- | :--- |
|
||||
@@ -294,4 +391,5 @@
|
||||
| sndChopin | Op.10 No.4 | |
|
||||
| sndOrientalInsomniacHardRepOld | 超东方不眠夜(旧版) | |
|
||||
| sndGreenlightInsomniac | 超东方不眠夜(预告片版) | |
|
||||
| sndOpeningCredits | |
|
||||
| sndLanterns | | 150 |
|
||||
| sndOpeningCredits | | 187.9 |
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
[去往原页面](https://docs.qq.com/sheet/DQUJxb0puSFFOVWpz)
|
||||
|
||||
<iframe single src="https://docs.qq.com/sheet/DQUJxb0puSFFOVWpz"></iframe>
|
||||
@@ -4,90 +4,116 @@
|
||||
|
||||
| 功能 | 快捷键 | 章节 | 内容 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| 播放音乐 | `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+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#播放表情) | 改变轨道中角色的表情 |
|
||||
| 改变角色 | `Shift+J` | [轨道视效](../pages/rowfx.md#轨道涂色) | 改变轨道的角色 |
|
||||
| 轨道涂色 | `R` | [轨道视效](../pages/rowfx.md#轨道涂色) | 设置轨道的边框、涂色、透明度 |
|
||||
| 切换轨道 | `Y` | [采音和节奏设计](../pages/beatpatterndesign.md) | 切换轨道的游玩者:1P,2P或是CPU |
|
||||
| **镜头类** | | | |
|
||||
| 旋转轨道 | `Shift+S` | | (仅高级模式下可用)将另一个轨道连接到角色上,实现`7-1`中的一人多轨 |
|
||||
| **摄像头特效类** | | | |
|
||||
| 移动摄像头 | `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#适合配合轨道或节拍一起使用的特效) | 自定义屏幕闪烁的图层位置,颜色,透明度 |
|
||||
| 重低音震动 | `K` | [轨道视效](../pages/rowfx.md#适合配合轨道或节拍一起使用的特效) | 添加一次大幅度的色像差加大幅度屏幕缩放 |
|
||||
| 反转颜色 | `I` | [镜厅](../pages/hallofmirror.md) | 给画面添加反色效果 |
|
||||
| 卡带效果 | `0` | [视觉干扰](../pages/vfx.md#卡带效果) | 反复重现某个画面造成卡顿错觉 |
|
||||
| 窗口动效 | `W` | [窗口移动](../pages/windowmove.md) | 把关卡变成窗口模式,并设置窗口的移动 |
|
||||
| 自定义闪烁 | `F` | [轨道视效](../pages/rowfx.md#适合配合轨道或节拍一起使用的特效) | 自定义屏幕闪烁的图层位置,颜色,透明度 |
|
||||
| 闪烁 | `Shift+F` | [轨道视效](../pages/rowfx.md#适合配合轨道或节拍一起使用的特效) | 简单地屏幕闪烁 |
|
||||
| 重低音震动 | `K` | [轨道视效](../pages/rowfx.md#适合配合轨道或节拍一起使用的特效) | 添加一次大幅度的色像差+大幅度屏幕缩放 |
|
||||
| 颜色反转 | `I` | [镜厅](../pages/hallofmirror.md) | 给画面添加反色效果 |
|
||||
| 卡带效果 | `E` | [视觉干扰](../pages/vfx.md#卡带效果) | 反复重现某个画面造成卡顿错觉 |
|
||||
| 手涂色 | `Shift+U` | [手](../pages/hand.md#手涂色) | 改变手的颜色 |
|
||||
| 窗口动效 | `W` | [窗口移动](../pages/WindowDance.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#让事件摆放更有条理) | 添加注释内容或插入注释型自定义方法 |
|
||||
|
||||
## 黄色版块(房间)
|
||||
|
||||
| 功能 | 快捷键 | 章节 | 内容 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| 排列显示房间 | `S` | [房间](../pages/room.md#排列显示房间) | 改变四个房间的前后顺序 |
|
||||
| 排列显示房间 | `S` | [房间](../pages/room.md#排列显示房间) | 从上到下显示房间 |
|
||||
| 移动房间 | `M` | [镜头移动](../pages/camera.md) | 让房间在画面中移动,缩放,旋转等 |
|
||||
| 重新排序房间 | `O` | [房间](../pages/room.md#房间的前后关系) | 改变四个房间的前后顺序 |
|
||||
| 重新排序房间 | `O` | [房间](../pages/room.md#房间的前后关系) | 改变四个房间叠放时的上下关系 |
|
||||
| 设置房间内容模式 | `C` | [镜头移动](../pages/camera.md) | 设置房间在缩小时是缩放房间还是剪裁房间 |
|
||||
| 房间遮罩 | `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#让事件摆放更有条理) | 添加注释内容或插入注释型自定义方法 |
|
||||
|
||||
## 淡蓝色版块(窗口)
|
||||
|
||||
| 功能 | 快捷键 | 章节 | 内容 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| 窗口动效 | `W` | [窗口相关的动画](../pages/WindowDance.md#窗口动效) | 设置窗口的移动模式,移动窗口 |
|
||||
| 窗口大小重置 | `R` | [窗口相关的动画](../pages/WindowDance.md#窗口大小重置) | 改变窗口的大小、缩放模式、轴点 |
|
||||
| 设置窗口内容 | `C` | [窗口相关的动画](../pages/WindowDance.md#设置窗口内容) | 设置窗口显示的内容是哪个房间或全部房间 |
|
||||
| 重新排列窗口 | `O` | [窗口相关的动画](../pages/WindowDance.md#重新排列窗口) | 改变四个窗口叠放时的上下关系 |
|
||||
| 隐藏窗口 | `H` | [窗口相关的动画](../pages/WindowDance.md#隐藏窗口) | 隐藏或显示窗口 |
|
||||
| 设置主窗口 | `U` | [窗口相关的动画](../pages/WindowDance.md#设置主窗口) | 设置对话,顶部护士灯光,状态牌等内容在哪个窗口显示 |
|
||||
| 设置窗口名称 | `N` | [窗口相关的动画](../pages/WindowDance.md#设置窗口名称) | 修改窗口的标题 |
|
||||
| 设置桌面颜色 | `D` | [窗口相关的动画](../pages/WindowDance.md#设置桌面颜色) | 修改模拟移动时桌面的颜色 |
|
||||
| 注释 | `M` | [标签](../pages/tag.md#让事件摆放更有条理) | 添加注释内容或插入注释型自定义方法 |
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
### 带X拍子
|
||||
|
||||
在编辑器中翻译为X字拍子。心跳有时候会**跳过一些拍子**,但我们仍然需要在拍子抵达时抓住时机按键。当电图线路上出现**红色的X字**时,就意味着这些拍子会被跳过。这个时候你需要在头脑里继续数数,然后照常在第二拍处按键。
|
||||
在编辑器中翻译为X字拍子。心跳有时候会**跳过一些拍子**,但我们仍然需要在拍子抵达时抓住时机按键。当电图线路上出现**红色的X字**时,就意味着这些拍子会被跳过。这个时候你需要在头脑里继续数数,然后照常在七处按键。
|
||||
|
||||
在`1-2 亲密`中被首次引入,且在大量关卡中出现。
|
||||
|
||||
@@ -22,13 +22,13 @@
|
||||
|
||||
### 摇摆普通拍子
|
||||
|
||||
也称心脏梗阻。他们的心跳会出现不规则的拍子,因为心跳信号的工作不正常,节拍也会呈现不规则的感觉。无论如何,也请在第二拍按下空格。
|
||||
也称心脏梗阻。他们的心跳会出现不规则的拍子,因为心跳信号的工作不正常,节拍也会呈现不规则的感觉。无论如何,也请在第七拍按下空格。
|
||||
|
||||
在`3-3 分离二重唱`中被首次引入。
|
||||
|
||||
### 网好卡菌
|
||||
|
||||
在编辑器中应设置为电击拍子。无论发生什么都要在音乐的第二拍按下空格。
|
||||
在编辑器中应设置为电击拍子。无论发生什么都要在音乐的第七拍按下空格。
|
||||
|
||||
在`1-X 东方不眠夜`中被首次引入。
|
||||
|
||||
@@ -98,6 +98,12 @@
|
||||
|
||||
在`5-2N 无以为继的伤心欲绝`中被首次引入。
|
||||
|
||||
### 长按单发拍子
|
||||
|
||||
当听到咻噗的声音时,说明下一次击拍需要长按到下一个出拍点。
|
||||
|
||||
在`7-1 模糊`中被首次引入。
|
||||
|
||||
### 冲击拍子
|
||||
|
||||
单发拍子根据哨声提示在脉冲和按拍时全都按拍。
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
[去往原页面](https://docs.qq.com/sheet/DUGpSTXFZQkNGWWdn)
|
||||
|
||||
<iframe single src="https://docs.qq.com/sheet/DUGpSTXFZQkNGWWdn"></iframe>
|
||||
@@ -1 +1,3 @@
|
||||
[去往原页面](https://docs.qq.com/sheet/DZU1LTmJGVkhhQ2Vp)
|
||||
|
||||
<iframe single src="https://docs.qq.com/sheet/DZU1LTmJGVkhhQ2Vp"></iframe>
|
||||
@@ -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 +1,3 @@
|
||||
[去往原页面](https://docs.qq.com/sheet/DZGlHSExJSllSZ0tI)
|
||||
|
||||
<iframe single src="https://docs.qq.com/sheet/DZGlHSExJSllSZ0tI"></iframe>
|
||||
@@ -5,32 +5,39 @@
|
||||
| 特效名称 | 具体效果 |
|
||||
| :--- | :--- |
|
||||
| **摄像头类** | |
|
||||
| <font color='red'>屏幕块2x2</font> | 把屏幕块变成2x2个相同的部分 |
|
||||
| <font color='red'>屏幕块3x3</font> | 把屏幕块变成3x3个相同的部分 |
|
||||
| <font color='red'>屏幕块4x4</font> | 把屏幕块变成4x4个相同的部分 |
|
||||
| 自定义屏幕块 | 把屏幕块变成任意个相同的部分,注意这里是可以填写小数的 |
|
||||
| <font color='red'>屏幕分隔2x2</font> | 把屏幕分隔变成2x2个相同的部分 |
|
||||
| <font color='red'>屏幕分隔3x3</font> | 把屏幕分隔变成3x3个相同的部分 |
|
||||
| <font color='red'>屏幕分隔4x4</font> | 把屏幕分隔变成4x4个相同的部分 |
|
||||
| 屏幕分割 | 把屏幕分隔变成任意个相同的部分,注意这里是可以填写小数的 |
|
||||
| <font color='red'>水平滚屏</font> | 画面向左移动,并且从右方重复出现 |
|
||||
| <font color='red'>垂直滚屏</font> | 画面向上移动,并且从下方重复出现;需要注意:水平垂直滚屏只能存在一个 |
|
||||
| VHS | 画面带有横条和轻微抖动,有老式录像机的感觉 |
|
||||
| <font color='red'>水平滚屏+VHS</font> | 上面两个的叠加,实际上分开放两个物块效果也是一样的 |
|
||||
| <font color='red'>垂直滚屏+VHS</font> | 上面两个的叠加,实际上分开放两个物块效果也是一样的 |
|
||||
| 自定义滚屏 | 允许同时设置水平和垂直的滚屏,并且自由设置滚屏速度 |
|
||||
| 屏幕滚动 | 允许同时设置水平和垂直的滚屏,并且自由设置滚屏速度 |
|
||||
| 过场模式 | 屏幕上下方出现黑条,类似于很多游戏出过场动画时的效果 |
|
||||
| 按键低重音 | 每次按拍后画面产生震动和色像差 |
|
||||
| 鱼眼 | 用鱼眼镜头拍出来的效果,中间比其他部分更大(显得更靠近屏幕),强度可以是负数 |
|
||||
| | |
|
||||
| **画风突变类** | |
|
||||
| <font color='red'>黑屏</font> | <font color='red'>别多想,真的就是屏幕全黑了</font> |
|
||||
| 倒带 | 屏幕内容左右抽搐 |
|
||||
| 扫描线 | 屏幕被分割为许多极小横条,透明大横条从上往下循环移动 |
|
||||
| 噪点 | 就是那种老电视收不到信号的马赛克 |
|
||||
| 电影噪点 | 在保持画面的基础上加一些噪点 |
|
||||
| 色调偏移 | 改变画面的色调,每隔100%是一个色调循环 |
|
||||
| 亮度 | 改变画面的亮度,小于等于0的情况下等效于黑屏 |
|
||||
| 对比度 | 改变画面的色彩对比度,负数的情况下等效于反色 |
|
||||
| 饱和度 | 改变画面的色彩饱和度,负数的情况下等效于反色 |
|
||||
| <font color='red'>灰度</font> | <font color='red'>画面变成黑白灰的</font> |
|
||||
| 灰度 | 画面变成黑白灰的 |
|
||||
| 怀旧 | 画面发黄 |
|
||||
| JPEG失真 | 出现类似信号不稳定时的画面割裂效果 |
|
||||
| 像素化 | 画面变成一个个像素格,“数量”其实是格子的大小 |
|
||||
| 马赛克 | 与普通的打码不太一样,能感觉到画面依然清晰但是割裂成了一个个小格子 |
|
||||
| 点阵 | 画面变成一个个小点,类似于`5-1N`中的背景 |
|
||||
| 海底波浪 | 屏幕左右扭曲 |
|
||||
| 热变 | 受高温影响屏幕逐渐扭曲和失真 |
|
||||
| 玻璃碎裂 | 和`6-1`中一样的碎裂效果,一次性 |
|
||||
| 放克 | 精神污染,屏幕上滚动着高饱和度的纯色 |
|
||||
| 素描 | 添加一张揉皱的白纸背景,将原始画面自动抽取关键部分变成黑色画在纸上 |
|
||||
| 色像差 | 有点像红蓝眼镜3D视频不戴眼镜时看到的效果 |
|
||||
@@ -50,10 +57,15 @@
|
||||
| 矩阵 | 添加一个绿色音符上升的效果,和`1-XN`这关是一样的,可以和前景背景叠加起来显示 |
|
||||
| 落花 | 屏幕上方开始落下花瓣,可以和前景背景叠加起来显示 |
|
||||
| 落花即刻 | 屏幕上方落下花瓣,同时屏幕上已生成一些花瓣,可以和前景背景叠加起来显示 |
|
||||
| 落叶 | 屏幕上方开始落下落叶,可以和前景背景叠加起来显示 |
|
||||
| 飘雪 | 屏幕上方开始落下雪花,可以和前景背景叠加起来显示 |
|
||||
| 雪花 | 屏幕上方开始落下快速的雪花,短时间内充满屏幕,可以和前景背景叠加起来显示 |
|
||||
| 暴风雪 | 屏幕上方开始落下暴风雪,可以和前景背景叠加起来显示 |
|
||||
| 钻石 | 屏幕上出现很多方块 |
|
||||
| 气球 | 屏幕下方飘出很多气球 |
|
||||
| 余烬 | 屏幕上出现飘动的火星 |
|
||||
| 纸屑 | 屏幕上方落下各种颜色的纸屑 |
|
||||
| 彩纸爆破 | 屏幕左下角和右下角爆出彩纸,和`5-3N`中一样 |
|
||||
| 教程音符 | 屏幕铺满剧情模式教程中的音符背景,可以自定义颜色等 |
|
||||
| | |
|
||||
| **轨道类** | |
|
||||
@@ -64,7 +76,7 @@
|
||||
| <font color='red'>轨道全白</font> | 把轨道变成纯白色,需要事先布置一个轨道涂色物件 |
|
||||
| <font color='red'>轨道轮廓光</font> | 把轨道变成纯黑色白边,需要事先布置一个轨道涂色物件 |
|
||||
| <font color='red'>轨道普通</font> | 把轨道变成普通样子,需要事先布置一个轨道涂色物件 |
|
||||
| 波状轨道 | 轨道自己上下来回移动,类似于`2-3N`这关 |
|
||||
| 轨道浮动 | 轨道自己上下来回移动,类似于`2-2`这关 |
|
||||
| 脉冲计数 | 对普通拍子轨道有效,轨道上方随节奏出现1~7的数字,每个房间只能有一条轨道显示 |
|
||||
| 心跳震屏 | 每个心跳拍子都会让轨道抖动一下 |
|
||||
| 按键震屏 | 每个按键拍子都会让轨道抖动一下 |
|
||||
|
||||
@@ -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%)`,设置四个背景图片,使用平铺的方式,设置不同的水平移动速度,就得到了在公路上慢慢前进的效果。
|
||||
|
||||

|
||||
|
||||
另外,使用小图片像地砖一样平铺才是更为原本的用法。
|
||||
|
||||
## 还原PV效果
|
||||
|
||||
有些音乐是自带PV/MV/BGA的,直接将原视频的风格或内容搬运到节奏医生中也不失为一种选择。但编辑器也有其自己的像素风格,有节奏医生自己的游戏特色,还原时也要讲究融合。
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
|
||||
## 设置游戏音效
|
||||
|
||||
除了节奏音效和按拍音效之外,游戏里还有一些地方会出现音效,主要是失误的时候(分为微小失误和严重失误),没有节拍却按了空格的时候(默认是“啵”一声,所以在编辑器里面叫“手掌-啵音”),第二拍按下之后第八拍“咚”地一声回音(叫做心爆,这时候心脏图标也会小抖一下),以及跳过拍(嘎↘的声音),长按拍,冻结拍,灼热拍的音效。
|
||||
除了节奏音效和按拍音效之外,游戏里还有一些地方会出现音效,主要是失误的时候(分为微小失误和严重失误),没有节拍却按了空格的时候(默认是“啵”一声,所以在编辑器里面叫“手掌-啵音”),第七拍按下之后第八拍“咚”地一声回音(叫做心爆,这时候心脏图标也会小抖一下),以及跳过拍(嘎↘的声音),长按拍,冻结拍,灼热拍的音效。
|
||||
|
||||
这些音效在设置的时候是无法下拉列表选择更改的,只能通过键入游戏内置的音效文件名,或者导入自定义的音效来改变。目前已公开的内置音效文件名因为数量太多,集中收录在了[附录3](../appendix/3.html)中。
|
||||
这些音效在设置的时候是无法下拉列表选择更改的,只能通过键入游戏内置的音效文件名,或者导入自定义的音效来改变。目前已公开的内置音效文件名因为数量太多,集中收录在了[附录3](../pages/appendix_audios.md)中。
|
||||
|
||||
## 心爆
|
||||
|
||||
@@ -132,4 +132,4 @@ g 4 7 2 {
|
||||
## 播放音效
|
||||
**播放音效**是所有音效设置里面自由度最高的一个,可以在任意的时间开始播放一个音效文件,和游戏的轨道与按键没有任何关联。如果处理得当,你甚至可以用这个功能写一个打击乐段在游戏里面。
|
||||
|
||||
另外,剧情模式里面的内置音效也可以在这里通过写文件名的形式添加进自己的谱面。但是官方目前并没有公开所有的音效文件,我们收集了其中的一部分放在了[附录3](../appendix/3.html)中整理成了表格,需要的话可以自取。
|
||||
另外,剧情模式里面的内置音效也可以在这里通过写文件名的形式添加进自己的谱面。但是官方目前并没有公开所有的音效文件,我们收集了其中的一部分放在了[附录3](../pages/appendix_audios.md)中整理成了表格,需要的话可以自取。
|
||||
|
||||
@@ -1,4 +1,88 @@
|
||||
# 镜头移动
|
||||
# 房间与镜头
|
||||
|
||||
完全掌握了节奏医生的节奏设计之后,我们要把目光放在谱面的视觉呈现上了,这一节我们就从理解“房间”的概念开始。
|
||||
|
||||
编辑器总共支持四个房间,你可以想象成一栋房子有四层楼,每层楼最多住四个人,同时,每层楼的装修可以随意摆设互不干扰。这四层楼不一定刚刚好叠在一起,可以随时移动,互不交叠,只是高度不同。我们飞在空中从上往下看,就能看到目视所及范围内的大楼景象。同时,如果空中飘扬着其他物件,也会被我们的眼睛捕捉到,如果大楼的天花板和地板是透明的,那么地基里有什么东西也会被看到。
|
||||
|
||||
当我们使用**排列显示房间**事件时,房间就只能从上到下地排列在屏幕上,而如果使用**移动房间**事件,则可以随便移动。
|
||||
|
||||
## 排列显示房间
|
||||
|
||||

|
||||
|
||||
将左边的可见房间点亮为黄色,屏幕上就会显示这个房间,高度可以自定义,填写数据后房间高度将自动分配。详细的分配规则点击下方箭头展开。如果你懒得理解分配规则,只需永远保证 **不点亮多余的房间,并且将存在的房间高度总和设置到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)。
|
||||
|
||||
## 房间的前后关系
|
||||
|
||||
但实际上很多时候我们并不想就让房间这样死板地上下排布,甚至想让这些房间交叠在一起。要做到这一点,我们得先明确各个房间叠在一起的时候,它们的前后关系是怎样的。
|
||||
|
||||

|
||||
|
||||
首先看一个房间内,各种事件的由前往后关系是:
|
||||
|
||||
> [浮动文字]
|
||||
[弹幕效果]
|
||||
[前景图片]
|
||||
[轨道4]
|
||||
[轨道3]
|
||||
[轨道2]
|
||||
[轨道1]
|
||||
[背景图片(图片)]
|
||||
[背景图片(颜色)]
|
||||
|
||||
它们的前后顺序是不可改变的。
|
||||
|
||||
各个房间整体之间又有前后顺序,默认由前往后关系是:
|
||||
|
||||
> [显示状态牌]
|
||||
[应用到:顶部]
|
||||
[房间1]
|
||||
[房间2]
|
||||
[房间3]
|
||||
[房间4]
|
||||
|
||||
四个房间的顺序是可以改变的,只需要在黄色版块内添加一个**重新排序房间**事件,把前后顺序拖动到想要的即可。
|
||||
|
||||

|
||||
|
||||
## 激活其他房间
|
||||
|
||||
在刚打开编辑器的状态下,实际上只能看到房间1。并不是另外三个房间不存在,而是房间大小被设置成了`0%`。在黄色版块中找到**移动房间**事件,事件放置在工作区的哪一行,就是对应的哪个房间被移动。创建三个移动房间事件置于234行,将“大小”设置为`(100%,100%)`,这样所有的房间都以屏幕大小叠在一起了。
|
||||
|
||||
还记得[这里](../pages/settheme.md)提到了**设置主题**事件吗,我们再添加一个“花房·昼”。由于黄色版块不再是空白的,设置主题的事件的右上角出现了新的按钮,这是将事件设置到具体房间的功能。
|
||||
|
||||

|
||||
|
||||
将带有花房·昼主题的事件选择房间4,预览效果会发现我们看到的依然是武士电子,因为现在不透明的房间1完全遮住了房间4。删掉武士电子主题,会发现背景全黑,依然看不到花房。这是因为默认状态下房间并不是透明背景,而是纯黑背景。
|
||||
|
||||
在紫色的版块找到**设置背景**事件,将背景颜色选择为纯透明,应用到123房间。再次预览,终于能看到房间4了。“应用到”选项是可以多选的。
|
||||
|
||||

|
||||
|
||||
有时还会有第五个按钮“顶部”,如果你理解了本节最开头的比喻的话,应用到顶部的事件是直接在大楼与你之间的空中生效的。房间怎么移动都不会影响到顶部。
|
||||
|
||||

|
||||
|
||||
经此示例,相信你已经能理解房间的基本运作原理了。
|
||||
|
||||
## 概述
|
||||
移动房间应该是整个编辑器内灵活性最高的功能之一了。它的灵活性本身并不是基于对编辑器功能的理解的,而是更类似于对摄影或是视频制作手法的理解。我们观看电影也总是会说“镜头语言”,这话同样适用于作谱。合理的镜头运用可以极大程度提升谱面的视觉观感。
|
||||
@@ -17,6 +101,8 @@
|
||||
|
||||
**1、**所谓的移动摄像头,画一个三维空间出来也许可以让你更好地理解。它就像是我们举着一台摄像机拍摄自己的家一样,你的手或者身子移动,那么摄像头跟着移动,拍摄下来的整体画面位置就会不同。
|
||||
|
||||
如果“真实运动”选择的是开启,那么摄像头就是记录房间内的画面,怎么移动都在房间内;选择关闭则是像看录像一样,移动时会露出边缘。
|
||||
|
||||

|
||||
|
||||
**2、**移动摄像头最基本的用法就是把摄像头跟着节奏晃来晃去,与全程静止不动的背景相比,这样会给谱面增加一些动感。这个轨道移动的弹跳设计原理是一样的,仅仅是呈现的画面效果稍显不同。
|
||||
@@ -54,11 +140,6 @@
|
||||
|
||||

|
||||
|
||||
**3、房间透明度**
|
||||
**淡入淡出房间**事件倒是没有太多可说的,调节的是房间整体的透明度。同样也可以选择时长和缓速模式。
|
||||
|
||||
最基本的用法就是把一个房间的透明度从`0`调到`100`,另一个从`100`调到`0`,完成淡入淡出的转场。
|
||||
|
||||
**4、排列显示房间**
|
||||
|
||||
在[这一节](../pages/room.md)我们介绍过这个功能,但是使用这个软件自带的排列显示房间有一个略显僵硬的限制:房间的上下关系是不可变更的。如果想要自己定义谁在上谁在下,那就不能再使用这个默认功能了,需要我们添加移动房间功能来实现。
|
||||
|
||||
@@ -31,9 +31,9 @@
|
||||

|
||||

|
||||
|
||||
## 配合自定义滚屏
|
||||
## 配合屏幕滚动
|
||||
|
||||
自定义滚屏这个**预设特效**和普通的移动房间不一样,他的屏幕是上下左右接续的。但是只要是移动的屏幕,自然就可以配合浮动文字。为了方便操控文字的出现,一般也可以考虑剪裁房间的大小,并且配合遮罩。接下来就只需要安排好文字出现和消失的时机,文字就会像弹幕一样播放起来了。
|
||||
屏幕滚动这个**预设特效**和普通的移动房间不一样,他的屏幕是上下左右接续的。但是只要是移动的屏幕,自然就可以配合浮动文字。为了方便操控文字的出现,一般也可以考虑剪裁房间的大小,并且配合遮罩。接下来就只需要安排好文字出现和消失的时机,文字就会像弹幕一样播放起来了。
|
||||
|
||||

|
||||
|
||||
@@ -43,8 +43,8 @@
|
||||
|
||||
| 预设特效 | 配合效果 |
|
||||
| :--- | :--- |
|
||||
| 自定义屏幕块 | 当然是把字也分成多块,没什么特别的 |
|
||||
| 自定义滚屏 | 见上面那段 |
|
||||
| 自定义屏幕分隔 | 当然是把字也分成多块,没什么特别的 |
|
||||
| 屏幕滚动 | 见上面那段 |
|
||||
| 黑屏 | 不出意外地全黑了 |
|
||||
| 噪点、干扰 | 对浮动文字无效 |
|
||||
| 电影噪点、高光、JPEG失真、马赛克、海底波浪 | 正常地产生效果 |
|
||||
|
||||
@@ -1,4 +1,165 @@
|
||||
# 其他文字事件
|
||||
# 文字事件
|
||||
|
||||
## 浮动文字基本设置
|
||||
|
||||
如果我们要制作一首歌曲的谱面,一般而言都会考虑将歌词显示在画面中,这是一种简单粗暴,但能快速提升整体观感的做法。要在画面中加上字幕,我们需要在紫色的版块中找到**浮动文字**事件。
|
||||
|
||||
选择这个事件后,我们可以发现最开始的两行很有Word的感觉。
|
||||
|
||||

|
||||
|
||||
**aA**:可以调整字号大小,字号基本上没有上限,如果设置太大的话,文字就会**超出屏幕**。
|
||||
|
||||
**旋转**:可以旋转浮动文字框,注意是**整个文本框的旋转**,而不是每个字单独旋转。
|
||||
|
||||
**AB**:两个颜色分别是字的颜色和字符描边的颜色,刚才所说的字号里面,**只会包含字符本体的大小**,描边是没有算在里面的。
|
||||
|
||||
**↔**:指定浮动文字横向的基准位置。
|
||||
|
||||
**↕**:指定浮动文字纵向的基准位置。
|
||||
|
||||

|
||||
|
||||
**字体**:可以强制文本是哪种字体,有像素字体(不支持中文)、矢量字体(中文默认显示的字体)和粗体字体(`2-X`判定文字同款)。点击旁边的文件夹图标可以自行导入ttf或otf格式字体文件。
|
||||
|
||||

|
||||
|
||||
**位置**:指的是基准的位置。可以按一下准星符号再在预览画面窗口中点选位置。有条件精准找到位置的话还是建议在`X`和`Y`栏中输入具体数值。**点击右边的`%`按键可以切换屏幕像素点和屏幕百分比两种输入方式**。
|
||||
|
||||

|
||||
|
||||
**文字**:就是输入文本的地方了。纯英文文本是使用的像素字体,带有中文字符的情况下会全部变成矢量字体,如果你想要纯英文文本也显示矢量字体的话,可以回车键再在第二行输入一些中文,如下图所示。当文字框里没有中文时就无法输入中文,需在游戏外部打好要插入的文本,并通过复制粘贴的方式输入。
|
||||
|
||||

|
||||
|
||||
另外,目前已知中文繁体以及日语假名都可以在画面中正常显示。
|
||||
|
||||

|
||||
|
||||
**创建文本递进**:如果想要把一整句歌词按歌词节奏一个一个地显示出来,就需要在文本中使用“`/`”将它们隔开。如果想要一个一个地覆盖掉之前显示的内容,就需要在文本中使用`回车键`将他们隔开。之后点击下面的“创建文本递进”,在工作区里面可以拖动右箭头事件来调整时机。如果你做好了又不想要了,那么再把下面的开启改成关闭即可,无需手动删除。如果你又反悔了,还是想要,再改成开启,又会恢复记录。
|
||||
|
||||
```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、**在文本的最后放一个竖线“\|”或者下划线“\_”就可以做出打字的效果了。
|
||||
|
||||

|
||||
|
||||
```
|
||||
ぼ|
|
||||
ぼく|
|
||||
僕|
|
||||
僕の|
|
||||
僕のゆ|
|
||||
僕のゆめ|
|
||||
僕の夢|
|
||||
僕の夢
|
||||
|
||||
そ|
|
||||
そう、|
|
||||
そう、わ|
|
||||
そう、わた|
|
||||
そう、わたし|
|
||||
そう、私|
|
||||
そう、私の|
|
||||
そう、私のゆ|
|
||||
そう、私のゆめ|
|
||||
そう、私の夢|
|
||||
```
|
||||
|
||||
**7、**创建了一组文本递进之后,只需要双击浮动文字事件本身,整组字幕都会被选中。不需要一个个手动去点选了。
|
||||
|
||||
**8、**基准的左中右会影响文本递进效果。靠左时从左向右出现文本递进;靠中时从中间挤向两侧出现文本递进;靠右时从右向左出现文本递进。
|
||||
|
||||
**9、**在文本框的最后加一个空行,就可以通过文本递进的方式设置文本的结束时间,避免了一点点数格子的烦恼。
|
||||
|
||||
**10、**在文字中的个别字符前面加上`<color=#RRGGBBAA>`,后面加上`</color>`可以改变这几个字的颜色和透明度。关于颜色的介绍由于篇幅关系将放在下一小节。
|
||||
|
||||

|
||||
|
||||
对应文本框内容为:
|
||||
|
||||
```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=56&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>
|
||||
> 【另一个我】有两份文字略微偏移重叠在一起
|
||||
|
||||
有没有发现不管是颜色效果还是显示效果,在设计上都和歌词本身有着些许联系,也就让平淡无奇的歌词字幕一下子变得生动起来。
|
||||
|
||||
## 文本装饰
|
||||
|
||||
你可能已经注意到,**浮动文字**事件并没有移动文字的功能。如果想要移动文字,请移步绿色板块,点击加号创建装饰,选择“文本”。
|
||||
|
||||

|
||||
|
||||
创建一个**设置文本**事件,你会发现这个事件和浮动文字基本一样,相信你已经知道怎么用了。
|
||||
|
||||
这里的文本比起用浮动文字事件创建的文本功能更加齐全,不仅可以**移动装饰**,还可以**显示/隐藏**、**重排序:装饰**,等等。总之和精灵图差不多(如果想了解精灵图请看[这里](../pages/decoration.md#制作一个精灵)),这里就不过多赘述了。
|
||||
|
||||
## 显示对话
|
||||
|
||||
@@ -13,28 +174,28 @@
|
||||
|
||||
**需要注意的是:**
|
||||
|
||||
**1、**你可以一次性输入多行文本,这样在实际显示时就会在同一对话框内逐步刷新每一行台词;如果使用多个显示对话事件,每个事件只输入一行文本,那么对话框有可能在一个事件之后消失再生成,影响连贯性。
|
||||
1. 你可以一次性输入多行文本,这样在实际显示时就会在同一对话框内逐步刷新每一行台词;如果使用多个显示对话事件,每个事件只输入一行文本,那么对话框有可能在一个事件之后消失再生成,影响连贯性。
|
||||
|
||||
**2、**显示对话事件一次只能显示一个对话框,如果前一个事件的台词没有走完下一个事件就开始了,那么前一个会直接被顶替掉。即使设置为屏幕上方和屏幕下方各一个也会被顶替。
|
||||
2. 显示对话事件一次只能显示一个对话框,如果前一个事件的台词没有走完下一个事件就开始了,那么前一个会直接被顶替掉。即使设置为屏幕上方和屏幕下方各一个也会被顶替。
|
||||
|
||||
**3、**一个对话框只能显示两行文字,多出来的会无法显示,请注意分段。分段后需要再输入一次立绘人物,否则立绘就不再显示了。
|
||||
3. 一个对话框只能显示两行文字,多出来的会无法显示,请注意分段。分段后需要再输入一次立绘人物,否则立绘就不再显示了。
|
||||
|
||||
**4、** 如果需要实现像官方教程一样的可以手动跳过的对话框效果,可以添加自定义方法`activeDialogues = true`或`activeDialoguesImmediately = true`。
|
||||
- 如果启用`activeDialogues = true`,
|
||||
在对话事件所在小节已经播放完毕而对话仍未结束时,游戏会等待至游戏音乐的下一个小节开始时继续播放;
|
||||
- 如果启用`activeDialoguesImmediately = true`,
|
||||
- 如果对话事件结束时所在小节仍然未播放完毕,
|
||||
游戏会等待至游戏音乐的下一个节拍开始时立即从时间轴的下一个小节继续播放。
|
||||
- 如果对话事件所在小节已经播放完毕而对话仍未结束,
|
||||
游戏会等待至游戏音乐的下一个节拍开始时继续播放。
|
||||
4. 如果需要实现像官方教程一样的可以手动跳过的对话框效果,可以添加自定义方法`activeDialogues = true`或`activeDialoguesImmediately = true`。
|
||||
- 如果启用`activeDialogues = true`,
|
||||
在对话事件所在小节已经播放完毕而对话仍未结束时,游戏会等待至游戏音乐的下一个小节开始时继续播放;
|
||||
- 如果启用`activeDialoguesImmediately = true`,
|
||||
- 如果对话事件结束时所在小节仍然未播放完毕,
|
||||
游戏会等待至游戏音乐的下一个节拍开始时立即从时间轴的下一个小节继续播放。
|
||||
- 如果对话事件所在小节已经播放完毕而对话仍未结束,
|
||||
游戏会等待至游戏音乐的下一个节拍开始时继续播放。
|
||||
|
||||
**5、**编辑器会自动识别标点符号,并在标点符号的位置自动添加不同程度的语句停顿,非常智能。但要注意,数学上的小数点“.”是会被判定为英文的句号的,从而产生停顿,非常不智能。
|
||||
5. 编辑器会自动识别标点符号,并在标点符号的位置自动添加不同程度的语句停顿,非常智能。但要注意,数学上的小数点“.”是会被判定为英文的句号的,从而产生停顿,非常不智能。
|
||||
|
||||
**6、**从外界复制粘贴进入的文本中,换行符是有问题的,要退格两次才能被删掉,否则台词会叠在一起;最好的做法当然是不要复制进多余的换行符号。
|
||||
6. 从外界复制粘贴进入的文本中,换行符是有问题的,要退格两次才能被删掉,否则台词会叠在一起;最好的做法当然是不要复制进多余的换行符号。
|
||||
|
||||

|
||||
|
||||
**7、**可以使用对话标签控制对话的显示效果,这些标签总是被包裹在中括号里的。支持的标签如下:
|
||||
7. 可以使用对话标签控制对话的显示效果,这些标签总是被包裹在中括号里的。支持的标签如下:
|
||||
|
||||
- `[vslow]` - 非常慢
|
||||
- `[slow]` - 慢
|
||||
@@ -54,7 +215,7 @@
|
||||
- `[swirlSpeed=X]`
|
||||
- `[static]` - 让此前设置移动方式的标签失效,位于该标签后的文本将不受前面的标签影响。
|
||||
|
||||
**8、**可以使用颜色标签更改文字的颜色,只需按以下格式输入:`<color=文字颜色>要更改颜色的文字</color>`。代码中的颜色可以使用十六进制颜色值(不透明的 #RRGGBB 或包含透明度信息的 #RRGGBBAA) ,也可以使用[Unity富文本的颜色名](https://docs.unity3d.com/Packages/com.unity.ugui@1.0/manual/StyledText.html):
|
||||
**8、** 可以使用颜色标签更改文字的颜色,只需按以下格式输入:`<color=文字颜色>要更改颜色的文字</color>`。代码中的颜色可以使用十六进制颜色值(不透明的 #RRGGBB 或包含透明度信息的 #RRGGBBAA) ,也可以使用[Unity富文本的颜色名](https://docs.unity3d.com/Packages/com.unity.ugui@1.0/manual/StyledText.html):
|
||||
|
||||
| 颜色(中文) | 颜色(英文) | RGB | 示例 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# 修改游戏版本
|
||||
# 修改游戏配置
|
||||
|
||||
## 说明
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
最后说明的是,不论你使用的是哪个版本,由于近期官方对编辑器的更新极为频繁,请务必将游戏更新设置为**始终保持此游戏为最新**,否则真的是……脑壳痛。
|
||||
|
||||
## 进入方式
|
||||
## 修改游戏版本
|
||||
|
||||
接下来介绍进入Beta版本的方法:
|
||||
|
||||
@@ -31,4 +31,20 @@
|
||||
|
||||
第四步,直接打开游戏即可。
|
||||
|
||||
> 一切准备就绪,那么开始我们的节奏医生编辑器中文教程吧!
|
||||
> 一切准备就绪,那么开始我们的节奏医生编辑器中文教程吧!
|
||||
|
||||
## 启用高级编辑器功能
|
||||
|
||||
从 v1.0.4 版本开始,高级编辑器功能被加入。其中包含一些在剧情关卡中使用,但之前不能在编辑器直接使用的功能。
|
||||
|
||||
要启用高级编辑器功能,首先按住 `tab`,然后你就会看到这个界面:
|
||||
|
||||

|
||||
|
||||
然后狂点右下角的凹兔,直到弹出这个窗口:
|
||||
|
||||

|
||||
|
||||
点击接受,此时高级编辑器功能就启用了。
|
||||
|
||||
如果你想关闭高级编辑器功能,只需要点一下 `tab` 界面右下角的凹兔即可。
|
||||
@@ -1,5 +1,102 @@
|
||||
# 更新信息
|
||||
|
||||
#### 2026-06-06
|
||||
- 更新 [VFX](../pages/vfx.md) 章节
|
||||
- 更新[镜厅](../pages/hallofmirror.md) 章节
|
||||
|
||||
#### 2026-03-25
|
||||
- 更新事件列表
|
||||
- 更新预设特效列表
|
||||
- 修正格式错误
|
||||
- 更改“设置窗口数量”译名为“设置窗口内容”
|
||||
- 补充 WindowDance 页内容
|
||||
- 更新轨道涂色属性页图片
|
||||
- 更新轨道重排序事件
|
||||
- 更新旋转轨道事件的详细内容
|
||||
- 更新默认轨道的各部分位置分布数值
|
||||
- 为改变轨道事件描述添加图片
|
||||
- 更新制作人员表
|
||||
|
||||
#### 2026-03-01
|
||||
- **变量**一节被替换为[表达式](../pages/expression.md)。
|
||||
- 为各种标题添加了容易辨识和定位的背景渐变条。
|
||||
- ~~我也要加入文档编撰列表吗(~~
|
||||
|
||||
#### 2026-02-26
|
||||
- 临时修复了若干资源查找问题
|
||||
- 同步音频列表
|
||||
|
||||
#### 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
|
||||
|
||||
#### 2025-10-26
|
||||
- 文档补充
|
||||
- 修复代码块渲染异常
|
||||
- 首页添加互动模块引导
|
||||
|
||||
#### 2025-10-18
|
||||
- [自制角色与精灵资源](../pages/spritesheet.md)页添加了音效和表情命名规则相关内容。
|
||||
|
||||
#### 2025-10-16
|
||||
- 更新了字体版本
|
||||
|
||||
#### 2025-09-27
|
||||
- 添加了 7th beat games 授权
|
||||
|
||||
#### 2025-07-21
|
||||
- 添加了本地状态存储
|
||||
|
||||
#### 2025-07-19
|
||||
- 补充了目录图标
|
||||
- 整理并添加了新的板块
|
||||
- 为嵌入页面添加了跳转外链功能
|
||||
- 更换了插图
|
||||
- 添加了使用协议
|
||||
|
||||
#### 2025-06-28
|
||||
- 添加了~~吐槽~~样式
|
||||
- 修复了批量替换遗留问题
|
||||
- 修复了样式混淆
|
||||
- 添加了[双人模式设计页面](../pages/twoplayers.md)
|
||||
|
||||
#### 2025-06-08
|
||||
- 修复了一些死链
|
||||
- 添加了新的 otto 插图(没错作者又更了)并修改了更换逻辑
|
||||
|
||||
@@ -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拍的节奏,无法读谱。
|
||||
@@ -28,6 +28,8 @@ eb.AddClassicBeat 1 7[swing=1.75,tick=6];
|
||||
|
||||
如何加入类似于`1-2亲密`的`X`记号呢?在生成一个节奏之后,点击“**切换为X字拍子设置**”就可以调节。需要注意的是:你需要在一串普通拍子开始的**同时**或是**之前**就放置好修饰拍子设置。如果在普通拍子已经响起之后再添加`X`,虽然画面上能即时生效,但是节拍音效是没法立刻改变的。
|
||||
|
||||
如果你在单发类型的轨道上放置`切换为X字拍子设置`,那么时间轴会卡住无法播放。
|
||||
|
||||
> 在没有节奏的地方放置一连串的“切换为X字拍子设置”来改变`X`的排布也可以视为一种画面演出。
|
||||
|
||||
当然,这个功能也不仅仅是为轨道加`X`,按下鼠标左键是加入`X`记号,按下鼠标右键一次是`↑`箭头记号,两次是`↓`箭头记号。按下鼠标中键一次是摇摆心跳记号,两次是抖动心跳记号。
|
||||
@@ -36,6 +38,8 @@ eb.AddClassicBeat 1 7[swing=1.75,tick=6];
|
||||
|
||||
> 尽量不要在第一拍设置`X`记号,这对纯音押玩家是不可预知的,在轨道数量多的情况下也会显得比较难理清节奏。如果你觉得你的音乐中这段节奏第一拍不放`X`就浑身难受,那也需要打开护士数拍(参考`X-WOT`这关中的`xx-----`)。
|
||||
|
||||
> 此外像马克的短轨道,需调用自定义方法来完成,语句为`SetRowLength(轨道编号[0索引的], 轨道长度[1~7的整数])`。如果你还不明白自定义方法是什么,需要先翻到[自定义方法](../pages/custommethod.md)看看。考虑到这玩意问的人比较多,所以就先写在此处了。
|
||||
|
||||
最后的选项“**分解为自由时长节拍**”较为复杂,我们放到[这里](/pages/moreclassicbeats)再介绍。
|
||||
|
||||
## 护士节奏提示
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||

|
||||
|
||||
**类型:**“**普通**”表示像武士一样的普通拍子节奏,“**单发**”表示像咖啡师一样的单发拍子节奏。需要注意的是,切换轨道类型的同时也会清空轨道上的所有节拍,因此建议在一开始就确定好轨道的类型。
|
||||
**类型:**“**普通**”表示像武士一样的普通拍子节奏,“**单发**”表示像咖啡师一样的单发拍子节奏。虽然现在单发和普通拍子可以共存,但需要注意的是,切换轨道类型的同时也会清空轨道上的所有节拍,因此建议在一开始就确定好轨道的类型。
|
||||
|
||||
**玩家:**P1,P2表示玩家1和玩家2,CPU表示电脑演示。
|
||||
|
||||
|
||||
@@ -7,10 +7,15 @@
|
||||
- [Sterix_Craft砹氪硒](https://space.bilibili.com/349090681)
|
||||
- [T_Terrence](https://space.bilibili.com/455443751)
|
||||
- [mfgujhgh](https://space.bilibili.com/1369651)
|
||||
- [喜欢精灵宝可梦的黄黄](https://space.bilibili.com/589687399)
|
||||
- [龙俟城](https://space.bilibili.com/589687399)
|
||||
- [卢毅](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)
|
||||
- [obugs](https://space.bilibili.com/498017546)
|
||||
- [zyx](https://space.bilibili.com/2045355693)
|
||||
- 视频制作:
|
||||
- [吾夜犹明](https://space.bilibili.com/29219948)
|
||||
- [山不转水到渠成](https://space.bilibili.com/4870582)
|
||||
@@ -40,7 +45,7 @@
|
||||
- 表格维护:
|
||||
- [自定义方法表](/pages/appendix_custommethods.md)
|
||||
- [RaYmondCheung](https://space.bilibili.com/1579208)
|
||||
- [ChocoWeat](https://space.bilibili.com/588693542)
|
||||
- [ChocoWheat](https://space.bilibili.com/588693542)
|
||||
- [制谱规范](/pages/appendix_levelrules.md)
|
||||
- [o0O0o0l0o0O0o](https://space.bilibili.com/272324550)
|
||||
- [相关资源](/pages/appendix_resources.md)
|
||||
|
||||
@@ -90,6 +90,11 @@
|
||||
|
||||
`排位顺序`:同一时间设置多个自定义方法时,你可能需要让这些事件按一定顺序生效,这个时候就需要设置这个参数了。这个参数支持负数,数字越小,事件越早生效。
|
||||
|
||||
## 快捷查询
|
||||
|
||||
<div class="custommethods-search">
|
||||
</div>
|
||||
|
||||
## 我知道你还想问什么
|
||||
|
||||
你也许会有这种疑问:为什么官方要设置一个“调用自定义方法”,像写代码一样完成一些明明是很成熟的功能和特效?为什么不把它们也做成普通的事件直接添加就好了?
|
||||
|
||||
@@ -49,14 +49,14 @@
|
||||
</div>
|
||||
|
||||
<!--
|
||||
| 普通拍子轨道 | 人物 | 前六拍左侧 | 前六拍中段 | 第二拍左侧 | 第二拍右侧 | 心脏之前 | 心脏 |
|
||||
| 普通拍子轨道 | 人物 | 前六拍左侧 | 前六拍中段 | 第七拍左侧 | 第七拍右侧 | 心脏之前 | 心脏 |
|
||||
| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|
||||
| 轨道1 | -0.5 | 1 | 0.5 | 1 | 0 | -2 | -2.5 |
|
||||
| 轨道2 | -10.5 | -9 | -9.5 | -9 | -10 | -12 | -12.5 |
|
||||
| 轨道3 | -20.5 | -19 | -19.5 | -19 | -20 | -22 | -22.5 |
|
||||
| 轨道4 | -30.5 | -29 | -29.5 | -29 | -30 | -32 | -32.5|
|
||||
|
||||
| 单发拍子轨道 | 人物 | 前六拍左侧 | 前六拍中段 | 第二拍左侧 | 第二拍右侧 | 心脏之前 | 心脏 |
|
||||
| 单发拍子轨道 | 人物 | 前六拍左侧 | 前六拍中段 | 第七拍左侧 | 第七拍右侧 | 心脏之前 | 心脏 |
|
||||
| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|
||||
-->
|
||||
**删除**:删除这个精灵。
|
||||
@@ -110,6 +110,21 @@
|
||||
|
||||
**时长与缓速:**同其他事件。
|
||||
|
||||
## 混合精灵图
|
||||
可以将精灵图的颜色与场景混合。
|
||||
|
||||
混合模式将进行以下计算(超过255的按255算,小于0按0算,小数四舍五入):
|
||||
|
||||
假设背景色为RGB(r1,g1,b1)
|
||||
|
||||
精灵图颜色为RGB(r2.g2.b2)
|
||||
|
||||
**附加(add 线性减淡)**模式显示的颜色为RGB(r1+r2,g1+g2,b1+b2)
|
||||
|
||||
**叠加(mul 正片叠底)**模式显示的颜色为RGB(r1*r2/255.g1*g2/255.b1*b2/255)
|
||||
|
||||
**反转(inv 反色)**模式显示的颜色为RGB(rl-r2,b1-b2,g1-g2)
|
||||
|
||||
## 精灵的使用技巧
|
||||
|
||||
**1、作为场景物体**
|
||||
|
||||
@@ -86,6 +86,8 @@
|
||||
|
||||
**另存为**:保存为额外的一个文件。
|
||||
|
||||
**测试**:直接开始游玩关卡。
|
||||
|
||||
**导出以发布**:导出以发布:将谱面导出为 .rdzip 文件,或将谱面上传至创意工坊。
|
||||
|
||||
**退出**:退出编辑器,记得先保存。
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
# 表达式
|
||||
|
||||
在节奏医生编辑器中,为了增加灵活性与可玩性,很多地方都支持使用表达式在游戏运行时动态决定实际的效果。这种表达式被称作 **RDCode**。
|
||||
|
||||
## 数据类型
|
||||
|
||||
类似于其他编程语言,RDCode 中有且仅有一些预定义的数据类型。
|
||||
|
||||
### 常量
|
||||
表示一个确定的值,其值在关卡制作时就已经确立。
|
||||
|
||||
### 变量
|
||||
表示一个不定的值,其值可能会在关卡运行过程中被赋值语句更改。
|
||||
|
||||
- **访问权限**
|
||||
为了保证关卡运行的稳定,一些变量会设置访问权限:
|
||||
- **只读**
|
||||
此变量可以参与表达式求值(读),但不能被赋值(写)。
|
||||
- **只写**
|
||||
此变量仅允许被赋值(写)而不能参与表达式求值(读)。
|
||||
- **可读写**
|
||||
此变量既能够参与表达式求值(读)也能够被赋值(写)。
|
||||
|
||||
- #### 整形(Integer/int)
|
||||
即整数。
|
||||
整形可以自动参与浮点型数据的数学运算。
|
||||
你可以直接使用整形常量并参加运算,例如 `2026`, `-308`, `999`, `0`。
|
||||
- #### 浮点型(Single/Float/float)
|
||||
可以带有小数部分的数字。
|
||||
例如 `3.1415`, `200.1`, `-9.99`。
|
||||
> 在将浮点型转换为整型的操作(如赋值操作)时,将遵循**向最近偶数舍入**的原则(与大多数编程语言中的**向下取整**原则不同),即若计算结果为 `0.5`,那么它对应的整数值为 `0`;而 `1.5` 将对应 `2`。
|
||||
- #### 布尔型(Boolean/bool)
|
||||
仅 `true` 或 `false` 以表示启用或禁用等。
|
||||
> 在**自定义方法**中,
|
||||
|
||||
- #### 字符串型(String/string)
|
||||
一串字符。
|
||||
不参与运算,仅在调用自定义方法时作为参数存在。
|
||||
值得注意的是,不同于其他语言的双引号 `"STRING"` 等表示方式,RDCode 的字符串表示是 `str:STRING`,即在字符串的前面加上一个 `str:` 前缀。
|
||||
一般而言,在 RDCode 内用到字符串型的地方都只能在一系列候选词中选择一个填入,例如在选择角色或缓速类型时。
|
||||
例如 `str:Samurai`, `str:Linear`
|
||||
|
||||
- #### 预定义变量
|
||||
节奏医生为整数、浮点数、布尔类型各预定义了 10 个可读写变量,分别以 `i`, `f`, `b` 开头,即 `i0`-`i9`, `f0`-`f9`, `b0`-`b9`。
|
||||
一些只读或只写的变量可在[自定义方法表](../pages/appendix_custommethods.md)查到。
|
||||
|
||||
## 运算类型
|
||||
|
||||
- **数学运算符**
|
||||
`+` `-` `*` `/` `%`
|
||||
- **逻辑运算符**
|
||||
`And` `Or` `Not`
|
||||
> 在 `And` `Or` 的两侧、`Not` 的右侧只支持布尔型数据。
|
||||
- **比较运算符**
|
||||
`>` `<` `>=` `<=` `==` `<>`
|
||||
- **函数调用**
|
||||
如 `Rand`, `IIf`, `atLeastRank`
|
||||
> 所有的可用的自定义方法请查阅[自定义方法表](../pages/appendix_custommethods.md)。
|
||||
> 表内标注的方法按照每个参数的含义及其类型表示,
|
||||
> 例如 `SetMistakeWeight(int RowID, float Weight)` 中,注明了此方法需要一个 int 类型(即整形)的值表示 RowID 和一个 float 类型(即浮点型)的值表示 Weight,
|
||||
> 你可以这样使用:`SetMistakeWeight(0, 2)`,表示将轨道 1 的错误权重设为 2。
|
||||
|
||||
## 语句类型
|
||||
只能在自定义方法中使用。
|
||||
|
||||
- **自增/自减**
|
||||
在变量后面添加 `++` 或 `--` 使变量本身加 1 或减 1。
|
||||
> 布尔变量不支持自增/自减。
|
||||
例如 `i2++`。
|
||||
|
||||
- **赋值**
|
||||
在变量和表达式之间使用 `=` 将变量的值设为表达式的值。
|
||||
例如 `f3 = 20 * f5`。
|
||||
|
||||
- **调用**
|
||||
调用[自定义方法](../pages/appendix_custommethods.md)。
|
||||
|
||||
## 表达式的用途
|
||||
|
||||
### 条件
|
||||
- 在使用[条件](../pages/condition.md)的自定义条件模式时,可以定义一个自定义条件,用于决定赋予此条件的事件能否在播放关卡时启用。
|
||||
- 在条件的表达式限制下我们难以直接写出用 `And` 或 `Or` 组合的形式;但是我们可以通过设立多个自定义条件并分别添加对应的表达式,应用于事件上,或是执行多次自定义表达式并赋值给预定变量,再在条件内组合。
|
||||
- 在**条件**内无法使用 `>=` `<=`。~~怀疑是史山代码发力了~~
|
||||
- 在**条件**内若有 `>` `<` 存在时不允许有括号嵌套。~~史山代码还在发力~~
|
||||
- 逻辑运算符的优先级比比较运算符更高。
|
||||
|
||||
### 自定义方法
|
||||
- 自定义方法中的表达式仅在赋值和调用行为时才能使用,其中赋值时以 `[变量]=[表达式]` 形式将对应的变量设为计算后的值,调用时将表达式填入对应的参数的位置。
|
||||
例如 `b0 = b1 Or Not b2 And 3 > f2`。
|
||||
- 自增或自减运算的左值仅能使用变量名,不能使用表达式。
|
||||
- 在将布尔型数据转换为整形或浮点型的操作(如参与数学运算)时,其值将退化为整形,其中 `true` 对应 `1`,`false` 对应 `0`。
|
||||
- 在将整形或浮点型数据转换为布尔型的操作(如赋值操作)时,其值将遵循**非 `0` 即 `true`** 的原则,即若计算结果为 `0`,那么它对应的布尔值为 `false`,否则为 `true`。
|
||||
- 实际上在**自定义方法**内进行数学运算时,所有数据都将转换为浮点型再参与运算。
|
||||
- 比较运算符的优先级比逻辑运算符更高。
|
||||
- `Rand` 方法既不能包含表达式形式的参数,也不能参与计算。
|
||||
|
||||
### 自定义方法(注释)
|
||||
- 注释型自定义方法的参数不支持表达式,仅支持单独的值或变量。
|
||||
|
||||
### 事件参数
|
||||
- 部分事件的属性支持填入表达式,如移动轨道、移动精灵图的位置、轴点、尺寸、角度等。
|
||||
- 需要用花括号 `{}` 将表达式括起来以表示这是一个表达式。
|
||||
- 其他同**自定义方法**。
|
||||
|
||||
### 内插字符串
|
||||
- 部分事件的字符串类型属性支持将表达式插入字符串,如浮动文字、显示状态牌等。
|
||||
- 需要用花括号 `{}` 将表达式括起来以表示游戏需要将表达式的值替换表达式插入原字符串中。
|
||||
- 其他同**自定义方法**。
|
||||
@@ -1,148 +0,0 @@
|
||||
# 浮动文字
|
||||
|
||||
## 浮动文字基本设置
|
||||
|
||||
如果我们要制作一首歌曲的谱面,一般而言都会考虑将歌词显示在画面中,这是一种简单粗暴,但能快速提升整体观感的做法。要在画面中加上字幕,我们需要在紫色的版块中找到**浮动文字**事件。
|
||||
|
||||
选择这个事件后,我们可以发现最开始的两行很有Word的感觉。
|
||||
|
||||

|
||||
|
||||
**aA**:可以调整字号大小,字号基本上没有上限,如果设置太大的话,文字就会**超出屏幕**。
|
||||
|
||||
**旋转**:可以旋转浮动文字框,注意是**整个文本框的旋转**,而不是每个字单独旋转。
|
||||
|
||||
**AB**:两个颜色分别是字的颜色和字符描边的颜色,刚才所说的字号里面,**只会包含字符本体的大小**,描边是没有算在里面的。
|
||||
|
||||
**↔**:指定浮动文字横向的基准位置。
|
||||
|
||||
**↕**:指定浮动文字纵向的基准位置。
|
||||
|
||||

|
||||
|
||||
**位置**:指的是基准的位置。可以按一下准星符号再在预览画面窗口中点选位置。有条件精准找到位置的话还是建议在`X`和`Y`栏中输入具体数值。**点击右边的`%`按键可以切换屏幕像素点和屏幕百分比两种输入方式**。
|
||||
|
||||

|
||||
|
||||
**文字**:就是输入文本的地方了。纯英文文本是使用的像素字体,带有中文字符的情况下会全部变成矢量字体,如果你想要纯英文文本也显示矢量字体的话,可以回车键再在第二行输入一些中文,如下图所示。当文字框里没有中文时就无法输入中文,需在游戏外部打好要插入的文本,并通过复制粘贴的方式输入。
|
||||
|
||||

|
||||
|
||||
另外,目前已知中文繁体以及日语假名都可以在画面中正常显示。
|
||||
|
||||

|
||||
|
||||
**创建文本递进**:如果想要把一整句歌词按歌词节奏一个一个地显示出来,就需要在文本中使用“`/`”将它们隔开。如果想要一个一个地覆盖掉之前显示的内容,就需要在文本中使用`回车键`将他们隔开。之后点击下面的“创建文本递进”,在工作区里面可以拖动右箭头事件来调整时机。如果你做好了又不想要了,那么再把下面的开启改成关闭即可,无需手动删除。如果你又反悔了,还是想要,再改成开启,又会恢复记录。
|
||||
|
||||
```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、**在文本的最后放一个竖线“\|”或者下划线“\_”就可以做出打字的效果了。
|
||||
|
||||

|
||||
|
||||
```
|
||||
ぼ|
|
||||
ぼく|
|
||||
僕|
|
||||
僕の|
|
||||
僕のゆ|
|
||||
僕のゆめ|
|
||||
僕の夢|
|
||||
僕の夢
|
||||
|
||||
そ|
|
||||
そう、|
|
||||
そう、わ|
|
||||
そう、わた|
|
||||
そう、わたし|
|
||||
そう、私|
|
||||
そう、私の|
|
||||
そう、私のゆ|
|
||||
そう、私のゆめ|
|
||||
そう、私の夢|
|
||||
```
|
||||
|
||||
**7、**创建了一组文本递进之后,只需要双击浮动文字事件本身,整组字幕都会被选中。不需要一个个手动去点选了。
|
||||
|
||||
**8、**基准的左中右会影响文本递进效果。靠左时从左向右出现文本递进;靠中时从中间挤向两侧出现文本递进;靠右时从右向左出现文本递进。
|
||||
|
||||
**9、**在文本框的最后加一个空行,就可以通过文本递进的方式设置文本的结束时间,避免了一点点数格子的烦恼。
|
||||
|
||||
**10、**在文字中的个别字符前面加上`<color=#RRGGBBAA>`,后面加上`</color>`可以改变这几个字的颜色和透明度。关于颜色的介绍由于篇幅关系将放在下一小节。
|
||||
|
||||

|
||||
|
||||
对应文本框内容为:
|
||||
|
||||
```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>
|
||||
> 【另一个我】有两份文字略微偏移重叠在一起
|
||||
|
||||
有没有发现不管是颜色效果还是显示效果,在设计上都和歌词本身有着些许联系,也就让平淡无奇的歌词字幕一下子变得生动起来。
|
||||
@@ -1,85 +1,138 @@
|
||||
# 镜厅
|
||||
|
||||
> 预警放在最前面:观看本节教程图片可能会引发光敏性癫痫,在编辑器中使用此功能也请慎重处理。
|
||||
## 镜厅的本质
|
||||
正常情况下,游戏每一帧绘制前都会清空屏幕(填充黑色),然后重新绘制所有物件。这保证了上一帧的画面不会残留。
|
||||
**但是如果不重置呢?**
|
||||
镜厅(Hall of Mirror) 就是关闭这个清空操作。上一帧的画面保留在屏幕上,新画面直接叠加在上面。
|
||||
|
||||
> 本节动图较多,如遇加载卡顿,请耐心等待。
|
||||
你可以尝试:
|
||||
- 添加一个会移动的轨道或精灵(如一个向右匀速移动的豆子盒)
|
||||
- 在预设特效中添加"镜厅"
|
||||
- 播放关卡
|
||||
你会发现,方块不再是一个清晰的个体,而是一条向右延伸的 "尾巴"。
|
||||
这是每一帧的方块叠加在一起形成的拖影。
|
||||
> 镜厅在 "主题设置" 和 "预设特效" 中都有,但请使用预设特效版本。主题设置是全局开关且难以与其他特效组合,预设特效可以灵活控制。
|
||||
|
||||
所谓的镜厅效果,就是画面在变化的时候并不清除变化过程中产生的效果,画面效果会一直叠加,然后逐渐变得混乱。
|
||||
如果不加控制,每一帧都叠加新画面,屏幕很快会被完全填满。我们需要一种机制让旧的画面逐渐淡出。
|
||||
|
||||
<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>
|
||||
## 抑制方法
|
||||
|
||||
镜厅一共能在两个地方找到,一是设置主题中的 “镜厅”,二是预设特效中的“镜厅”。**但最好使用预设特效中的**。
|
||||
### 亮度衰减
|
||||
|
||||
如果只是直接使用镜厅加上预设特效,效果一般只会越来越阴间,所以我们一般会使用预设特效里的“晕影”和“闪烁晕影”或者半透明的背景或半透明的后背景板闪光(由于设备性能差别,镜厅的效果显示可能每个人会有所不同,我一般使用20的透明度)来起到抑制的效果,同时这样也能直接做出最简单的拖尾效果。
|
||||
假设一个亮度为 100 的像素每帧向右移动 1 像素,且每帧绘制前整个画面亮度衰减为原来的 50%:
|
||||
|
||||

|
||||
| 帧 | 亮度 ||||
|
||||
|-|-:|-:|-:|-:|
|
||||
|1|100|
|
||||
|2|50|100|
|
||||
|3|25|50|100|
|
||||
|4|12.5|25|50|100|
|
||||
|
||||
拖尾效果(可以注意到镜厅留下了痕迹 ,如果想去除就需要再加上其他的效果,比如-1强度的高光)。这里再附上一些特效在遮罩后的组合(默认都已经打开了镜厅)。
|
||||
衰减率决定拖尾长度。
|
||||
节奏医生没有直接的 "衰减率" 参数,但可以通过以下方式模拟:
|
||||
|
||||

|
||||

|
||||

|
||||
#### 半透明黑色背景覆盖
|
||||
添加一个黑色背景板
|
||||
设置透明度为 20%(即每帧覆盖 20% 不透明黑色,相当于 80% 亮度保留)
|
||||
在元素移动时,原来留下的影子会逐渐被黑色覆盖,形成拖影的效果。
|
||||

|
||||

|
||||
|
||||
#### 晕影特效
|
||||
添加预设特效"晕影"或"闪烁晕影"
|
||||
晕影会从边缘向中心逐渐覆盖,产生柔和的拖影抑制
|
||||

|
||||
|
||||
一般来说直接用这些效果是不会太好的,用的时候会使用更多其他的特效进行组合。
|
||||
### 位移扭曲
|
||||
除了亮度衰减,还可以让历史画面发生位移,产生流动感。
|
||||
|
||||
### 反色(HOMVERT)
|
||||
---
|
||||
|
||||
镜厅+反色的结果往往是会让眼睛难以承受的高频闪烁,因此直接使用是禁止的,但是加上一点遮罩就可以避免这种结果。
|
||||
#### 基础位移效果
|
||||
在镜厅基础上添加屏幕滚动:x = 1, y = 1
|
||||
配合 20% 透明度黑色背景
|
||||
元素朝左上方向流动的同时会一直复制画面本身叠印起来。
|
||||

|
||||

|
||||
|
||||

|
||||
#### 屏幕分隔扭曲
|
||||
添加屏幕分隔特效:x = 2, y = 2
|
||||
画面被划分为 2×2 的块,同时会叠上原来的画面。
|
||||

|
||||
|
||||
另外,值得一提的是护士语音自带的灯光实际上是一片反色的区域,因此如果使用了镜厅,就要注意是否产生了镜厅反色(实在没办法也可以用音效代替直接使用语音来避免出现灯光)。
|
||||
### 区域控制
|
||||
镜厅是全屏效果,但有时你只想部分区域有拖影,或者需要保护某些区域不被拖影污染。
|
||||
|
||||
### 背景
|
||||
---
|
||||
|
||||
如果直接使用背景加上镜厅使用是不会有效果的,但如果我们把背景的颜色设成半透明在加上镜厅就能在保留背景的情况下加上镜厅的效果。
|
||||
#### 反色遮罩
|
||||
镜厅 + 反色(HOMVERT)会产生高频闪烁,极其伤眼,**禁止直接使用**。
|
||||
通常使用镜厅 + 反色 + 20% 透明度黑色背景的组合。
|
||||
黑色背景作为遮罩层,可以降低反色区域的对比度,消除闪烁
|
||||
> 护士语音自带的灯光是反色区域,使用镜厅时需注意,或用音效代替语音避免灯光。
|
||||
|
||||

|
||||

|
||||
|
||||
如果图片本身有透明部分,则镜厅的效果会只在透明的部分显示。
|
||||
#### 背景遮罩
|
||||
直接使用背景 + 镜厅无效果(背景完全覆盖,没有透明区域供镜厅显示)。
|
||||
设置背景为半透明(如 50% 透明度),镜厅效果只在背景的透明部分显示
|
||||
> 如果图片本身有透明通道(如 PNG),镜厅会自动只在透明区域产生拖影。
|
||||
|
||||

|
||||
|
||||
### 顶部镜厅
|
||||
|
||||
预设特效里的镜厅除了四个房间外,还可以选择在“顶部”生效,这样就能做出只用房间做不出的效果,或者通过缩放和移动房间让整个房间受到镜厅影响。我们可以利用这个干很多事。
|
||||
### 房间控制
|
||||
预设特效中的镜厅有两个作用域:
|
||||
- 四个房间:仅影响关卡内的游戏区域
|
||||
- 顶部:影响整个屏幕,包括 UI 和边框
|
||||
|
||||
#### 顶部镜厅
|
||||
##### 边框绘制
|
||||
使用顶部镜厅 + 特定物件移动
|
||||
拖影会在屏幕边缘形成 "画框" 效果
|
||||

|
||||
|
||||
##### 万花筒
|
||||
顶部镜厅 + 旋转 / 缩放房间
|
||||
整个画面产生对称的镜像拖影
|
||||

|
||||
|
||||
直接在使用主题的房间使用镜厅是不会有效果的,但如果设置透明背景再使用顶部镜厅就能起到作用(需要注意的是,有些主题设置的时候会自动设置一些效果,可以在设置主题后0.0001拍再设置其他效果来避免与主题冲突)。
|
||||
#### 房间透明化
|
||||
直接使用主题 + 镜厅无效果(主题背景不透明)。
|
||||
设置主题后,在 0.0001 拍时添加其他特效(避免与主题自动设置冲突)
|
||||
设置透明背景 + 顶部镜厅
|
||||
或者将主题放在单独房间,将该房间设为半透明,轨道物件叠加在上方
|
||||
|
||||

|
||||
|
||||
对于本身没有透明部分的主题,我们可以把主题单独放在一个房间然后把那个房间半透明化,之后把轨道单独叠在那个房间上面来达成效果。
|
||||
## 组合
|
||||
镜厅不是单独使用的特效,而是基础层。真正丰富的效果来自组合。
|
||||
|
||||
### 透明化
|
||||
### 控制维度
|
||||
|
||||
虽然在大部分情况下使用了镜厅就意味着房间的背景不再能透明,但在少数特效影响下的情况是可以的。
|
||||
维度 | 特效示例 | 作用
|
||||
---- | -------------------- | -----------------
|
||||
衰减 | 黑色背景透明度、晕影 | 控制拖尾长度
|
||||
位移 | 滚屏、海底波浪 | 让拖影流动 / 扭曲
|
||||
颜色 | 高光、反色、VHS | 改变拖影色彩
|
||||
遮罩 | 背景透明度、屏幕分隔 | 限制镜厅作用区域
|
||||
|
||||

|
||||

|
||||
### 经典组合参考
|
||||
- 拖尾基础:镜厅 + 20% 黑色背景 + 晕影
|
||||
- 流动拖尾:镜厅 + 海底波浪 (0% 强度) + 20% 黑色背景
|
||||
- 方块拖影:镜厅 + 屏幕分隔 (2×2) + 晕影
|
||||
- 蓝色光晕:镜厅 + 蓝色高光 + 晕影
|
||||
- 复古故障:镜厅 + VHS + 电影噪点
|
||||
- 雨夜效果:镜厅 + 落雨 (负数强度) + 高光 (负数强度)
|
||||
### 透明化特例
|
||||
某些特效会让背景在镜厅下保持透明:
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
也有一些特效会让背景半透明。
|
||||
|
||||

|
||||

|
||||
|
||||
与之相对的,也有部分特效会让镜厅无法透明,加上其他的特效也一样。
|
||||
|
||||

|
||||

|
||||
|
||||
### 特殊效果
|
||||
|
||||
镜厅其实不只能用来做特效,也可以用来做一些特殊的效果。比如用来画画或者猜单词,当然这些都是一般用不到且比较难实现的,放在这里只是让你们知道一下。
|
||||
|
||||
### 组合
|
||||
|
||||
上面提到的都是镜厅的一些基本的用法。但做谱的时候不可能只用这些效果,这样是做不出花样来的。要做出更多变数,就要尝试更多的组合,甚至把组合再组合,这样就能做出很多不同的效果。在想不到怎么做特效的时候这是个很好用的方法试的时候也要注意效果不能太伤眼,也不是叠的特效越多越好。丰富谱面的内容才是第一目的。
|
||||
|
||||
与此同时,我们也要知道,镜厅只是做谱时的一种手段,做特效如果只是一味的试各种特效还不去了解其他方面,是没法提高的。希望你们做谱的时候能够合理使用镜厅,让内容更丰富。
|
||||
某些特效会强制背景不透明:
|
||||

|
||||

|
||||
|
||||
## 一些陈旧的示例
|
||||
|
||||
@@ -120,13 +173,13 @@
|
||||
|
||||

|
||||
|
||||
### 镜厅 + 屏幕块
|
||||
### 镜厅 + 屏幕分隔
|
||||
|
||||
这个需要配合晕影使用,不然也会直接崩坏。
|
||||
|
||||

|
||||
|
||||
要注意屏幕块是可以填写小数的,例如填写`x = 1.05, y = 1`,自定义闪烁透明度`15%~0%`。
|
||||
要注意屏幕分隔是可以填写小数的,例如填写`x = 1.05, y = 1`,自定义闪烁透明度`15%~0%`。
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||

|
||||
|
||||
如果不对其添加任何其他设置,那么轨道就会自动变成 `—x—x—x————♥` 的模式,像`4-1`这关的矿工一样,也就是在1,3,5,7拍有按压的动画效果。当然你可以在“设置X标记”这个项目里面选择跳过节拍的形式,默认有三种情况,如果想使用“切换为修饰拍子设置”来自由决定跳过也是可以的,先在“设置X标记”里面选择NO,然后设置好自己决定的修饰拍子就行了。
|
||||
如果不对其添加任何其他设置,那么轨道会延续上一个“切换为修饰拍子设置”的模式,当然你可以在“设置X标记”这个项目里面选择跳过节拍的形式,默认有三种情况,比如选`—x—x—x`轨道就会自动变成 `—x—x—x————♥` 的模式,像`4-1`这关的矿工一样,也就是在1,3,5,7拍有按压的动画效果。
|
||||
|
||||
```rdview 7 3
|
||||
eb.AddClassicBeat 3 1[tick=3,hold=0.3,swing=0.5];
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
制作一个自制谱的第一步就是导入一首音乐。虽然编辑器本身对音频文件格式无严格要求,但还是**请使用.ogg格式的音频文件**,以减少出BUG的可能性,对后续的调整偏移和选关界面试听也有帮助。如果你需要.ogg格式但是手头只有.mp3可以使用[aconvert](https://www.aconvert.com/cn/audio/mp3-to-ogg)等软件转换。**音乐的文件名尽量只包含字母、数字和半角符号**。
|
||||
|
||||
点击左上角的**菜单→新关卡**来创建新关卡,编辑器会帮我们选择到默认位置(C:\用户\你自己的用户名\文档\Rhythm Doctor)。如果你有长期做谱的需求,建议另取一个独立文件夹,会方便管理。在这个文件夹里创建的文件夹,就代表着你制作的不同的谱面。创建文件夹后进入,输入好谱面文件名,点击确定,就成功创建了一个谱面。
|
||||
点击左上角的**菜单→新关卡**来创建新关卡,编辑器会帮我们选择到默认位置(`C:\用户\你自己的用户名\文档\Rhythm Doctor`)。如果你有长期做谱的需求,建议另取一个独立文件夹,会方便管理。在这个文件夹里创建的文件夹,就代表着你制作的不同的谱面。创建文件夹后进入,输入好谱面文件名,点击确定,就成功创建了一个谱面。
|
||||
|
||||
> 在编辑已保存的关卡时,编辑器会每隔 5 分钟在此关卡相同目录生成一个 `backup.rdlevel` 备份文件并覆盖原有 `backup.rdlevel` 文件,如果做到一半编辑器崩了没保存就可以打开这个文件来恢复数据。
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
## 调整曲速和偏移
|
||||
|
||||
接下来一点十分重要,那就是调节BPM,也就是一分钟有多少拍的意思,只有设置对了BPM才能让游戏节奏和音乐速度保持一致。排除掉一些变速曲我们可以用[ArrowVortex](https://arrowvortex.ddrnl.com/)。或者你不想额外下载软件的话,也有一些在线网站可以测试,比如[all8](https://www.all8.com/tools/bpm.htm)。
|
||||
接下来一点十分重要,那就是调节BPM(Beats Per Minute,每分钟节拍数),只有设置对了BPM才能让游戏节奏和音乐速度保持一致。如果你在制作的曲目是匀速的,可以使用一些软件如 [ArrowVortex](https://arrowvortex.ddrnl.com/),或是一些在线网站,比如[all8](https://www.all8.com/tools/bpm.htm)。
|
||||
|
||||
调整好BPM之后还需要调整偏移。我们看一下下面波形图案,点击`‐`和`+`两个按钮进行缩小和放大。
|
||||
|
||||
|
||||
@@ -1,23 +1,28 @@
|
||||
<div class="intro"></div>
|
||||
|
||||
<div onclick="location.href='https://docs.qq.com/form/page/DUFNwc1dQdHJtbXF5';" class="notice">
|
||||
<p>节奏医生夏季打谱活动正在招募中!</p>
|
||||
</div>
|
||||
|
||||
# 节奏医生中文编辑器教程
|
||||
|
||||
> 此网页正在维护中。如有任何问题,欢迎指出。
|
||||
> 此网页正在活跃维护中。
|
||||
网页已开源至[此处](https://git.obugs.cn/RDCNWebs/rd.rdlevel.cn),欢迎投稿。
|
||||
|
||||
《节奏医生》编辑器中文教程旨在以教学的形式帮助您快速了解编辑器的界面,基础功能,设计技巧和做谱规范。未经授权不得以图文,视频等形式转载,也不得以本教程内素材进行二次创作。
|
||||
> 页面内的大部分事件栏板块包含点击互动。尝试点击以获得更生动的演示。
|
||||
也可以在[此处](../pages/appendix_tools.md)游玩事件栏板块。
|
||||
|
||||
《节奏医生》编辑器中文教程旨在以教学的形式帮助您快速了解编辑器的界面,基础功能,设计技巧和做谱规范。
|
||||
|
||||
编辑器视频教程点击[此链接](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](https://jq.qq.com/?_wv=1027&k=nsPA09E4) 告知我们。你也可以在群里上传谱面给我们试玩,群友们都会热心为你提供谱面优化建议。真诚欢迎各位做谱萌新和大佬的加入。
|
||||
如果你有做谱相关的问题,或是对本教程有什么意见和建议,可以点击链接加入 QQ 群 [1044116596](https://qm.qq.com/q/giuo0RDv4Q) 告知我们。你也可以在群里上传谱面给我们试玩,群友们都会热心为你提供谱面优化建议。真诚欢迎各位做谱萌新和大佬的加入。
|
||||
|
||||
(悄悄透露一句:官方也入驻了这个群哦~)
|
||||
|
||||
> 戳这只看板娘可以获得随机 TIPS →
|
||||
> 戳这只看板娘可以获得随机 TIPS →
|
||||
|
||||
本网站内容分模块授权,请务必阅读对应<a href='/LICENSE' download='LICENSE'>条款</a>后再使用。
|
||||
|
||||
Game assets courtesy of [7th Beat Games](https://7thbe.at/). Game assets are excluded from this site's license.
|
||||
@@ -1,4 +1,4 @@
|
||||
# 普通拍子的衍生节奏型
|
||||
# 普通拍的衍生节奏型
|
||||
|
||||
## 分解为自由时长节拍
|
||||
|
||||
@@ -16,11 +16,11 @@ eb.PulseFreeTimeBeat 6 0[pulse=9];
|
||||
eb.PulseFreeTimeBeat 7 0[pulse=9];
|
||||
```
|
||||
|
||||
我们选中数字1对应的节拍,发现这个是设置起始脉冲位置的。你甚至可以将它改为第二拍,然后把六个小的`>`删掉,这样就没有任何节拍提示。如果你设计的关卡是一个和节奏医生没什么关联的创意谱(梦幻联动?),且按键密度很大,则可以考虑这样使用。相比于工作区里面重叠摆放一大堆普通普通拍子,这样会看上去更清爽。但如果你设计的就是节奏医生,**请不要在完全无节奏提示的情况下直接响起第二拍**。
|
||||
我们选中数字1对应的节拍,发现这个是设置起始脉冲位置的。你甚至可以将它改为第七拍,然后把六个小的`>`删掉,这样就没有任何节拍提示。如果你设计的关卡是一个和节奏医生没什么关联的创意谱(梦幻联动?),且按键密度很大,则可以考虑这样使用。相比于工作区里面重叠摆放一大堆普通普通拍子,这样会看上去更清爽。但如果你设计的就是节奏医生,**请不要在完全无节奏提示的情况下直接响起第七拍**。
|
||||
|
||||

|
||||
|
||||
剩下的大于号`>`即意味着心跳向右移动一格,数到7的时候则需要按拍。点选之后,把它改成 `<`,心跳还能向左移动一格;点击自定义,还可以任意指定到第几个节拍。每一组自由拍**必须使用较大的节拍作为开头**,较小的则数量不限,直到数到第二拍为止。
|
||||
剩下的大于号`>`即意味着心跳向右移动一格,数到7的时候则需要按拍。点选之后,把它改成 `<`,心跳还能向左移动一格;点击自定义,还可以任意指定到第几个节拍。每一组自由拍**必须使用较大的节拍作为开头**,较小的则数量不限,直到数到第七拍为止。
|
||||
|
||||
```rdview 10 2
|
||||
eb.AddFreeTimeBeat 1 0[pulse=1];
|
||||
@@ -41,7 +41,7 @@ eb.PulseFreeTimeBeat 9 0[pulse=9];
|
||||
|
||||
如果你想让一串自由节拍最后不需要按拍,而是节奏直接消失,就把这一组自由节拍的最后一个点选**垃圾桶**符号。
|
||||
|
||||
> 如果你设计了一段无法数到第二拍的节奏且不放置垃圾桶,那么心电图就会一直停在轨道中间。这很诡异。
|
||||
> 如果你设计了一段无法数到第七拍的节奏且不放置垃圾桶,那么心电图就会一直停在轨道中间。这很诡异。
|
||||
|
||||
接下来介绍一些社区机制。社区玩家们通过合理设计自由拍,并加以适当的提示,创造出了一些全新的节奏类型。其中一些节奏被广泛使用,并在社区中形成共识,从而延续下来。使用这些机制制作自定义关卡无需额外设计教学环节。当然如果你担心玩家不了解社区,或是你有其它自己的想法,也可以为这些节奏类型自行设计节奏提示的方法,唯一的宗旨是保证提示恰当准确。
|
||||
|
||||
@@ -49,18 +49,21 @@ eb.PulseFreeTimeBeat 9 0[pulse=9];
|
||||
|
||||
## 切分音(Syncopation)
|
||||
|
||||
切分音的概念不难理解,拍子的数量仍然为七个,但是最后一个拍子响起的时间是在6.5拍的时候,即提早了半拍。这少的半拍时间是可以发生在任意相邻两拍之间的。早期版本的编辑器需要使用自由拍来制作切分音,现在在**切换为X字拍子设置**里,点亮激活拍子下方的`->>>>>-`符号,就会将这一拍的时间缩短一半。每个轨道最多只能设置一个切分音位置。
|
||||
切分音的概念不难理解,拍子的数量仍然为七个,但是最后一个拍子响起的时间是在6.5拍的时候,即提早了半拍。这少的半拍时间是可以发生在任意相邻两拍之间的。早期版本的编辑器需要使用自由拍来制作切分音,现在在**切换为X字拍子设置**里,点亮激活拍子下方的`> > >`符号,就会将这一拍的时间缩短一半并自动添加提示音。每个轨道最多只能设置一个切分音位置。
|
||||
|
||||

|
||||
|
||||
**如何提示**
|
||||
添加完后会发现多了几个选项,各个选项效果如下:
|
||||
|
||||
> 1. 将轨道边缘染成黄色(参考颜色: `#FFFF00FF` )
|
||||
> 2. 在切分发生前的奇数拍使用“切分音嘟声-低”音效
|
||||
> 3. 在切分发生后的第一拍使用“切分音嘟声-中”音效
|
||||
> 4. 在第7拍使用“切分音嘟声-高”音效
|
||||
**摇摆**:设置切分后的按拍点距离原来的提前了(拍长*摇摆)拍。
|
||||
|
||||
需要额外注意的是,无论拍子之中是否有`X`,切分的第一个提示音、最后一个提示音以及可能存在的切分中音效都要保留,只有剩下的切分低音效是可以自行选择放置与否的。
|
||||
**音量&音高**:设置提示音的音量和音高。
|
||||
|
||||
**样式**:设置提示音的样式,鸣声是剧情模式里用到的,嘟声则是社区创造的,用哪种都可以。
|
||||
|
||||
**修饰拍子出现/消失音效**:只在使用鸣声样式才会有,用来提示切分音的出现和消失,嘟声则不需要。
|
||||
|
||||
需要额外注意的是,无论拍子之中是否有`X`,切分出现/消失和切分后第一拍的音效必须保留,只有剩下的音效是可以自行选择放置与否的。
|
||||
|
||||
## 八拍子(8 Beats)
|
||||
|
||||
@@ -83,9 +86,9 @@ eb.PulseFreeTimeBeat 8 1[pulse=9];
|
||||
> 1. 将轨道边缘染成红色(参考颜色: `#FF0000FF` )
|
||||
> 2. 在第1拍使用 `beep_mid.ogg` 自定义音效
|
||||
|
||||
不要使用内置的 `sndBeepMid` 音效!
|
||||
也可以使用内置的 `sndBeepMid` 音效。
|
||||
|
||||
八拍子也可以是摇摆拍子,只需要将所有偶数拍选择并拖动即可变成摇摆拍:
|
||||
八拍子也可以是摇摆拍,只需要将所有偶数拍选择并拖动即可变成摇摆拍:
|
||||
|
||||
```rdview 10 3
|
||||
eb.AddClassicBeat 1 0[tick=6,swing=0.5];
|
||||
@@ -99,7 +102,7 @@ eb.PulseFreeTimeBeat 7 1[pulse=9];
|
||||
eb.PulseFreeTimeBeat 8.5 1[pulse=9];
|
||||
```
|
||||
|
||||
在八拍子中,**激活拍子**与八拍子的对应关系如下图所示。不要给第1拍和第3拍设置X拍子,这样做它就相当于变回普通拍子了。
|
||||
在八拍子中,**激活拍子**与八拍子的对应关系如下图所示。不要给第1拍和第3拍设置X拍子,这样做它就相当于变回普通拍了。
|
||||
|
||||

|
||||
|
||||
|
||||