danoniplus 43.3.0 → 43.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/js/danoni_main.js +145 -63
- package/js/lib/danoni_constants.js +13 -9
- package/package.json +1 -1
package/js/danoni_main.js
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Source by tickle
|
|
6
6
|
* Created : 2018/10/08
|
|
7
|
-
* Revised : 2026/01/
|
|
7
|
+
* Revised : 2026/01/12
|
|
8
8
|
*
|
|
9
9
|
* https://github.com/cwtickle/danoniplus
|
|
10
10
|
*/
|
|
11
|
-
const g_version = `Ver 43.
|
|
12
|
-
const g_revisedDate = `2026/01/
|
|
11
|
+
const g_version = `Ver 43.5.0`;
|
|
12
|
+
const g_revisedDate = `2026/01/12`;
|
|
13
13
|
|
|
14
14
|
// カスタム用バージョン (danoni_custom.js 等で指定可)
|
|
15
15
|
let g_localVersion = ``;
|
|
@@ -3551,10 +3551,6 @@ const headerConvert = _dosObj => {
|
|
|
3551
3551
|
setIntVal(getQueryParamVal(`h`), g_sHeight), g_sHeight);
|
|
3552
3552
|
$id(`canvas-frame`).height = wUnit(g_sHeight);
|
|
3553
3553
|
}
|
|
3554
|
-
if (!(_dosObj.heightVariable || g_presetObj.heightVariable || false)) {
|
|
3555
|
-
obj.heightLockFlg = true;
|
|
3556
|
-
g_settings.playWindows = g_settings.playWindows.filter(val => !val.endsWith(`Slope`) && !val.endsWith(`SideScroll`));
|
|
3557
|
-
}
|
|
3558
3554
|
|
|
3559
3555
|
// 曲名
|
|
3560
3556
|
obj.musicTitles = [`musicName`];
|
|
@@ -8408,8 +8404,6 @@ const exSettingInit = () => {
|
|
|
8408
8404
|
const spriteList = setSpriteList(g_settingPos.exSetting);
|
|
8409
8405
|
|
|
8410
8406
|
createGeneralSetting(spriteList.playWindow, `playWindow`);
|
|
8411
|
-
lblPlayWindow.title += g_headerObj.heightLockFlg ? g_msgObj.sideScrollDisable : g_msgObj.sideScrollMsg;
|
|
8412
|
-
|
|
8413
8407
|
createGeneralSetting(spriteList.stepArea, `stepArea`);
|
|
8414
8408
|
createGeneralSetting(spriteList.frzReturn, `frzReturn`);
|
|
8415
8409
|
createGeneralSetting(spriteList.shaking, `shaking`);
|
|
@@ -11337,6 +11331,7 @@ const getArrowSettings = () => {
|
|
|
11337
11331
|
g_workObj.scrollDir = [];
|
|
11338
11332
|
g_workObj.scrollDirDefault = [];
|
|
11339
11333
|
g_workObj.dividePos = [];
|
|
11334
|
+
g_workObj.scale = g_keyObj.scale;
|
|
11340
11335
|
g_workObj.stepRtn = structuredClone(g_keyObj[`stepRtn${keyCtrlPtn}`]);
|
|
11341
11336
|
g_workObj.stepHitRtn = structuredClone(g_keyObj[`stepRtn${keyCtrlPtn}`]);
|
|
11342
11337
|
g_workObj.arrowRtn = structuredClone(g_keyObj[`stepRtn${keyCtrlPtn}`]);
|
|
@@ -11344,6 +11339,34 @@ const getArrowSettings = () => {
|
|
|
11344
11339
|
g_workObj.diffList = [];
|
|
11345
11340
|
g_workObj.mainEndTime = 0;
|
|
11346
11341
|
|
|
11342
|
+
const rotateBy = (val, delta) => {
|
|
11343
|
+
// numeric
|
|
11344
|
+
const n = Number(val);
|
|
11345
|
+
if (Number.isFinite(n)) return n + delta;
|
|
11346
|
+
|
|
11347
|
+
// "type:deg"
|
|
11348
|
+
const [type, degStr = `0`] = String(val).split(`:`);
|
|
11349
|
+
const deg = Number(degStr);
|
|
11350
|
+
return Number.isFinite(deg) ? `${type}:${deg + delta}` : val;
|
|
11351
|
+
};
|
|
11352
|
+
const changeStepRtn = (_name, _angle) =>
|
|
11353
|
+
g_workObj[_name] = g_workObj[_name].map(v => rotateBy(v, _angle));
|
|
11354
|
+
|
|
11355
|
+
if (g_stateObj.playWindow.endsWith(`SideScroll`)) {
|
|
11356
|
+
if (g_stateObj.rotateEnabled) {
|
|
11357
|
+
const sign = g_stateObj.playWindow === `SideScroll` ? 1 : -1;
|
|
11358
|
+
changeStepRtn(`stepRtn`, 90 * sign);
|
|
11359
|
+
changeStepRtn(`stepHitRtn`, 90 * sign);
|
|
11360
|
+
changeStepRtn(`arrowRtn`, 90 * sign);
|
|
11361
|
+
}
|
|
11362
|
+
const div = g_keyObj[`div${keyCtrlPtn}`];
|
|
11363
|
+
const divMax = g_keyObj[`divMax${keyCtrlPtn}`] ?? posMax;
|
|
11364
|
+
const denom = (Math.max(div, divMax - div) + 1) * g_keyObj.blank;
|
|
11365
|
+
if (Number.isFinite(denom) && denom > 0) {
|
|
11366
|
+
g_workObj.scale *= Math.min(g_sHeight / denom, 1);
|
|
11367
|
+
}
|
|
11368
|
+
}
|
|
11369
|
+
|
|
11347
11370
|
g_workObj.keyGroupMaps = tkObj.keyGroupMaps;
|
|
11348
11371
|
g_workObj.keyGroupList = tkObj.keyGroupList;
|
|
11349
11372
|
|
|
@@ -11733,7 +11756,7 @@ const mainInit = () => {
|
|
|
11733
11756
|
|
|
11734
11757
|
// ステップゾーン、矢印のメインスプライトを作成
|
|
11735
11758
|
const mainSprite = createEmptySprite(divRoot, `mainSprite`, mainCommonPos);
|
|
11736
|
-
addTransform(`mainSprite`, `root`, `scale(${
|
|
11759
|
+
addTransform(`mainSprite`, `root`, `scale(${g_workObj.scale})`);
|
|
11737
11760
|
addXY(`mainSprite`, `root`, g_workObj.playingX, g_posObj.stepY - C_STEP_Y + g_headerObj.playingY);
|
|
11738
11761
|
|
|
11739
11762
|
// 曲情報・判定カウント用スプライトを作成(メインスプライトより上位)
|
|
@@ -14171,10 +14194,30 @@ const resultInit = () => {
|
|
|
14171
14194
|
lblAutoView.style.fontSize = wUnit(20);
|
|
14172
14195
|
}
|
|
14173
14196
|
|
|
14174
|
-
|
|
14175
|
-
|
|
14176
|
-
|
|
14177
|
-
|
|
14197
|
+
// ゲージ推移グラフの描画
|
|
14198
|
+
const gaugeTransitionCanvas = document.createElement(`canvas`);
|
|
14199
|
+
gaugeTransitionCanvas.id = `graphGaugeTransition`;
|
|
14200
|
+
gaugeTransitionCanvas.width = g_limitObj.gaugeTransitionWidth;
|
|
14201
|
+
gaugeTransitionCanvas.height = g_limitObj.gaugeTransitionHeight;
|
|
14202
|
+
|
|
14203
|
+
createEmptySprite(divRoot, `gaugeTransitionWindow`, g_windowObj.gaugeTransition, g_cssObj.result_PlayDataWindow).appendChild(gaugeTransitionCanvas);
|
|
14204
|
+
|
|
14205
|
+
multiAppend(divRoot,
|
|
14206
|
+
createCss2Button(`btnGaugeTransition`, `i`, () => true, {
|
|
14207
|
+
x: g_sWidth / 2 - 250, y: 185, w: 30, h: 30, siz: g_limitObj.jdgCharaSiz,
|
|
14208
|
+
resetFunc: () => changeGaugeTransition(), cxtFunc: () => changeGaugeTransition(),
|
|
14209
|
+
}, g_cssObj.button_Mini),
|
|
14210
|
+
);
|
|
14211
|
+
multiAppend(gaugeTransitionWindow,
|
|
14212
|
+
createCss2Button(`btnGaugeTrL`, `<`, () => true, {
|
|
14213
|
+
x: -45, y: 35, w: 20, h: 30, siz: g_limitObj.jdgCharaSiz,
|
|
14214
|
+
resetFunc: () => moveCursor(keyIsShift() ? -10 : -1),
|
|
14215
|
+
}, g_cssObj.button_Setting),
|
|
14216
|
+
createCss2Button(`btnGaugeTrR`, `>`, () => true, {
|
|
14217
|
+
x: -25, y: 35, w: 20, h: 30, siz: g_limitObj.jdgCharaSiz,
|
|
14218
|
+
resetFunc: () => moveCursor(keyIsShift() ? 10 : 1),
|
|
14219
|
+
}, g_cssObj.button_Setting),
|
|
14220
|
+
);
|
|
14178
14221
|
g_stateObj.gaugeTransitionViewFlg = false;
|
|
14179
14222
|
|
|
14180
14223
|
const changeGaugeTransition = () => {
|
|
@@ -14189,16 +14232,11 @@ const resultInit = () => {
|
|
|
14189
14232
|
}
|
|
14190
14233
|
};
|
|
14191
14234
|
|
|
14192
|
-
// ゲージ推移グラフの描画
|
|
14193
|
-
const gaugeTransitionCanvas = document.createElement(`canvas`);
|
|
14194
|
-
gaugeTransitionCanvas.id = `graphGaugeTransition`;
|
|
14195
|
-
gaugeTransitionCanvas.width = g_limitObj.gaugeTransitionWidth;
|
|
14196
|
-
gaugeTransitionCanvas.height = g_limitObj.gaugeTransitionHeight;
|
|
14197
|
-
|
|
14198
|
-
createEmptySprite(divRoot, `gaugeTransitionWindow`, g_windowObj.gaugeTransition, g_cssObj.result_PlayDataWindow).appendChild(gaugeTransitionCanvas);
|
|
14199
|
-
|
|
14200
14235
|
const startFrame = g_detailObj.startFrame[g_stateObj.scoreId];
|
|
14201
|
-
|
|
14236
|
+
let playingFrame = g_detailObj.playingFrameWithBlank[g_stateObj.scoreId];
|
|
14237
|
+
if (playingFrame <= 0) {
|
|
14238
|
+
playingFrame = 1;
|
|
14239
|
+
}
|
|
14202
14240
|
const transitionObj = { frame: [0], life: [g_workObj.lifeInit] };
|
|
14203
14241
|
|
|
14204
14242
|
const frame = transitionObj.frame;
|
|
@@ -14215,57 +14253,101 @@ const resultInit = () => {
|
|
|
14215
14253
|
|
|
14216
14254
|
const context = gaugeTransitionCanvas.getContext(`2d`);
|
|
14217
14255
|
context.lineWidth = 2;
|
|
14218
|
-
let preY, preX;
|
|
14219
|
-
const borderY = g_limitObj.gaugeTransitionHeight - g_workObj.lifeBorder * g_limitObj.gaugeTransitionHeight / g_headerObj.maxLifeVal;
|
|
14220
14256
|
|
|
14221
|
-
|
|
14222
|
-
|
|
14223
|
-
const y = g_limitObj.gaugeTransitionHeight - life[i] * g_limitObj.gaugeTransitionHeight / g_headerObj.maxLifeVal;
|
|
14257
|
+
const drawGaugeGraph = () => {
|
|
14258
|
+
context.clearRect(0, 0, gaugeTransitionCanvas.width, gaugeTransitionCanvas.height);
|
|
14224
14259
|
|
|
14225
|
-
|
|
14226
|
-
|
|
14227
|
-
context.moveTo(x, y);
|
|
14228
|
-
|
|
14229
|
-
} else {
|
|
14230
|
-
context.moveTo(preX, preY);
|
|
14231
|
-
context.lineTo(x, preY);
|
|
14260
|
+
let preX, preY;
|
|
14261
|
+
const borderY = g_limitObj.gaugeTransitionHeight - g_workObj.lifeBorder * g_limitObj.gaugeTransitionHeight / g_headerObj.maxLifeVal;
|
|
14232
14262
|
|
|
14233
|
-
|
|
14234
|
-
|
|
14235
|
-
|
|
14236
|
-
} else if (life[i - 1] >= g_workObj.lifeBorder && life[i] >= g_workObj.lifeBorder) {
|
|
14237
|
-
context.lineTo(x, y);
|
|
14238
|
-
context.strokeStyle = g_graphColorObj.clear;
|
|
14263
|
+
for (let i = 0; i < frame.length; i++) {
|
|
14264
|
+
const x = frame[i] * g_limitObj.gaugeTransitionWidth / playingFrame;
|
|
14265
|
+
const y = g_limitObj.gaugeTransitionHeight - life[i] * g_limitObj.gaugeTransitionHeight / g_headerObj.maxLifeVal;
|
|
14239
14266
|
|
|
14240
|
-
|
|
14241
|
-
context.lineTo(x, borderY);
|
|
14242
|
-
context.strokeStyle = g_graphColorObj.failed;
|
|
14243
|
-
context.stroke();
|
|
14267
|
+
if (i === 0) {
|
|
14244
14268
|
context.beginPath();
|
|
14245
|
-
context.moveTo(x,
|
|
14246
|
-
|
|
14247
|
-
context.
|
|
14269
|
+
context.moveTo(x, y);
|
|
14270
|
+
} else {
|
|
14271
|
+
context.moveTo(preX, preY);
|
|
14272
|
+
context.lineTo(x, preY);
|
|
14273
|
+
|
|
14274
|
+
if (life[i - 1] === 0 && life[i] === 0) {
|
|
14275
|
+
context.strokeStyle = g_graphColorObj.failed;
|
|
14276
|
+
|
|
14277
|
+
} else if (life[i - 1] >= g_workObj.lifeBorder && life[i] >= g_workObj.lifeBorder) {
|
|
14278
|
+
context.lineTo(x, y);
|
|
14279
|
+
context.strokeStyle = g_graphColorObj.clear;
|
|
14280
|
+
|
|
14281
|
+
} else if (life[i - 1] < g_workObj.lifeBorder && life[i] >= g_workObj.lifeBorder) {
|
|
14282
|
+
context.lineTo(x, borderY);
|
|
14283
|
+
context.strokeStyle = g_graphColorObj.failed;
|
|
14284
|
+
context.stroke();
|
|
14285
|
+
context.beginPath();
|
|
14286
|
+
context.moveTo(x, borderY);
|
|
14287
|
+
context.lineTo(x, y);
|
|
14288
|
+
context.strokeStyle = g_graphColorObj.clear;
|
|
14289
|
+
|
|
14290
|
+
} else if (life[i - 1] >= g_workObj.lifeBorder && life[i] < g_workObj.lifeBorder) {
|
|
14291
|
+
context.lineTo(x, borderY);
|
|
14292
|
+
context.strokeStyle = g_graphColorObj.clear;
|
|
14293
|
+
context.stroke();
|
|
14294
|
+
context.beginPath();
|
|
14295
|
+
context.moveTo(x, borderY);
|
|
14296
|
+
context.lineTo(x, y);
|
|
14297
|
+
context.strokeStyle = g_graphColorObj.failed;
|
|
14298
|
+
|
|
14299
|
+
} else {
|
|
14300
|
+
context.lineTo(x, y);
|
|
14301
|
+
context.strokeStyle = g_graphColorObj.failed;
|
|
14302
|
+
}
|
|
14248
14303
|
|
|
14249
|
-
} else if (life[i - 1] >= g_workObj.lifeBorder && life[i] < g_workObj.lifeBorder) {
|
|
14250
|
-
context.lineTo(x, borderY);
|
|
14251
|
-
context.strokeStyle = g_graphColorObj.clear;
|
|
14252
14304
|
context.stroke();
|
|
14253
14305
|
context.beginPath();
|
|
14254
|
-
context.moveTo(x, borderY);
|
|
14255
|
-
context.lineTo(x, y);
|
|
14256
|
-
context.strokeStyle = g_graphColorObj.failed;
|
|
14257
|
-
|
|
14258
|
-
} else {
|
|
14259
|
-
context.lineTo(x, y);
|
|
14260
|
-
context.strokeStyle = g_graphColorObj.failed;
|
|
14261
14306
|
}
|
|
14262
|
-
|
|
14263
|
-
|
|
14264
|
-
context.beginPath();
|
|
14307
|
+
preX = x;
|
|
14308
|
+
preY = y;
|
|
14265
14309
|
}
|
|
14266
|
-
preX = x;
|
|
14267
|
-
preY = y;
|
|
14268
14310
|
}
|
|
14311
|
+
drawGaugeGraph();
|
|
14312
|
+
|
|
14313
|
+
let cursorFrame = 0; // 現在のカーソル位置(frame)
|
|
14314
|
+
const moveCursor = (sec = 1) => {
|
|
14315
|
+
cursorFrame = Math.max(0, Math.min(playingFrame, cursorFrame + sec * g_fps));
|
|
14316
|
+
drawOverlay();
|
|
14317
|
+
};
|
|
14318
|
+
|
|
14319
|
+
const frameToX = (_frame) => {
|
|
14320
|
+
return _frame / playingFrame * gaugeTransitionCanvas.width;
|
|
14321
|
+
};
|
|
14322
|
+
|
|
14323
|
+
// 既存のグラフを再描画しつつ縦線と時間を重ねる
|
|
14324
|
+
const drawOverlay = () => {
|
|
14325
|
+
// 既存のグラフを再描画
|
|
14326
|
+
drawGaugeGraph();
|
|
14327
|
+
|
|
14328
|
+
const ctx = context;
|
|
14329
|
+
const x = frameToX(cursorFrame);
|
|
14330
|
+
|
|
14331
|
+
// 縦線
|
|
14332
|
+
ctx.beginPath();
|
|
14333
|
+
ctx.moveTo(x, 0);
|
|
14334
|
+
ctx.lineTo(x, gaugeTransitionCanvas.height);
|
|
14335
|
+
ctx.strokeStyle = "#009999";
|
|
14336
|
+
ctx.lineWidth = 1.5;
|
|
14337
|
+
ctx.stroke();
|
|
14338
|
+
|
|
14339
|
+
// 時間表示
|
|
14340
|
+
const timer = transFrameToTimer(cursorFrame + startFrame);
|
|
14341
|
+
ctx.font = `14px ${getBasicFont()}`;
|
|
14342
|
+
ctx.fillStyle = "#009999";
|
|
14343
|
+
ctx.textAlign = x > gaugeTransitionCanvas.width * 0.8 ? C_ALIGN_RIGHT : C_ALIGN_LEFT;
|
|
14344
|
+
ctx.fillText(
|
|
14345
|
+
`${timer}`,
|
|
14346
|
+
x > gaugeTransitionCanvas.width * 0.8 ? x - 5 : x + 5,
|
|
14347
|
+
g_limitObj.gaugeTransitionHeight - 35
|
|
14348
|
+
);
|
|
14349
|
+
};
|
|
14350
|
+
drawOverlay();
|
|
14269
14351
|
|
|
14270
14352
|
// ユーザカスタムイベント(初期)
|
|
14271
14353
|
const currentDateTime = new Date().toLocaleString();
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Source by tickle
|
|
7
7
|
* Created : 2019/11/19
|
|
8
|
-
* Revised : 2026/01/
|
|
8
|
+
* Revised : 2026/01/12 (v43.5.0)
|
|
9
9
|
*
|
|
10
10
|
* https://github.com/cwtickle/danoniplus
|
|
11
11
|
*/
|
|
@@ -165,6 +165,10 @@ $id(`canvas-frame`).margin = C_DIS_AUTO;
|
|
|
165
165
|
|
|
166
166
|
const g_btnWidth = (_multi = 1) => Math.min(g_sWidth, g_limitObj.btnBaseWidth) * _multi;
|
|
167
167
|
const g_btnX = (_multi = 0) => g_btnWidth(_multi) + Math.max((g_sWidth - g_limitObj.btnBaseWidth) / 2, 0);
|
|
168
|
+
const g_slopeAngle = () => (Math.atan2(
|
|
169
|
+
g_sHeight,
|
|
170
|
+
g_keyObj[`minWidth${g_headerObj.keyLabels[g_stateObj.scoreId]}`] || g_keyObj.minWidthDefault
|
|
171
|
+
) * 180) / Math.PI * 2 - 40;
|
|
168
172
|
|
|
169
173
|
// 固定ウィンドウサイズ
|
|
170
174
|
const g_windowObj = {
|
|
@@ -1543,8 +1547,8 @@ const g_playWindowFunc = new Map([
|
|
|
1543
1547
|
['Default', () => ``],
|
|
1544
1548
|
['Stairs', () => g_changeStairs(-8)],
|
|
1545
1549
|
['R-Stairs', () => g_changeStairs(8)],
|
|
1546
|
-
['Slope', () => g_changeStairs(-
|
|
1547
|
-
['R-Slope', () => g_changeStairs(
|
|
1550
|
+
['Slope', () => g_changeStairs(-g_slopeAngle())],
|
|
1551
|
+
['R-Slope', () => g_changeStairs(g_slopeAngle())],
|
|
1548
1552
|
['Distorted', () => g_changeSkew(-15)],
|
|
1549
1553
|
['R-Distorted', () => g_changeSkew(15)],
|
|
1550
1554
|
['SideScroll', () => g_changeStairs(-90)],
|
|
@@ -2486,6 +2490,8 @@ const g_shortcutObj = {
|
|
|
2486
2490
|
KeyX: { id: `btnTweet`, reset: true }, // x
|
|
2487
2491
|
KeyD: { id: `btnGitter`, reset: true }, // Discord
|
|
2488
2492
|
KeyP: { id: `btnCopyImage` },
|
|
2493
|
+
ArrowLeft: { id: `btnGaugeTrL` },
|
|
2494
|
+
ArrowRight: { id: `btnGaugeTrR` },
|
|
2489
2495
|
Backspace: { id: `btnRetry` },
|
|
2490
2496
|
},
|
|
2491
2497
|
};
|
|
@@ -4286,9 +4292,8 @@ const g_lang_msgObj = {
|
|
|
4286
4292
|
d_arroweffect: `矢印・フリーズアローモーションの有効化設定`,
|
|
4287
4293
|
d_special: `作品固有の特殊演出の有効化設定`,
|
|
4288
4294
|
|
|
4289
|
-
playWindow: `ステップゾーン及び矢印の位置を全体的に回転する等の設定です。\n[Stairs/Slope] ステップゾーンを階段状にします\n[Distorted]
|
|
4290
|
-
|
|
4291
|
-
sideScrollDisable: `\n\nウィンドウの高さの自動拡張が無効のため、Slope, SideScrollは使用できません`,
|
|
4295
|
+
playWindow: `ステップゾーン及び矢印の位置を全体的に回転する等の設定です。\n[Stairs/Slope] ステップゾーンを階段状にします\n[Distorted] 画面を歪ませます\n` +
|
|
4296
|
+
`[SideScroll] 横スクロールモードになります`,
|
|
4292
4297
|
stepArea: `ステップゾーンの位置を変更します。\n[Halfway] ステップゾーンが中央に表示されます\n[2Step] ステップゾーンが2段に分かれて流れてきます\n` +
|
|
4293
4298
|
`[Mismatched/R-Mismatched] スクロールの向きが上下で異なる方向に流れます\n` +
|
|
4294
4299
|
`[X-Flower] レーンが花びらのように広がります\n[Alt-Crossing] レーンが交互に違う方向から流れます`,
|
|
@@ -4380,9 +4385,8 @@ const g_lang_msgObj = {
|
|
|
4380
4385
|
d_arroweffect: `Enable sequences' animations`,
|
|
4381
4386
|
d_special: `Enable setting of special effects to the work`,
|
|
4382
4387
|
|
|
4383
|
-
playWindow: `This is the setting for overall rotation of the step zone and arrow position, etc.\n[Stairs/Slope] The step zone is in a staircase shape.\n[Distorted] Distorts the screen
|
|
4384
|
-
|
|
4385
|
-
sideScrollDisable: `\n\nSlope, SideScroll cannot be used because \nautomatic window height expansion is disabled.`,
|
|
4388
|
+
playWindow: `This is the setting for overall rotation of the step zone and arrow position, etc.\n[Stairs/Slope] The step zone is in a staircase shape.\n[Distorted] Distorts the screen.\n` +
|
|
4389
|
+
`[SideScroll] It becomes a side scroll mode.`,
|
|
4386
4390
|
stepArea: `Change the position of the step zone.\n[Halfway] Step zones are centered.\n[2Step] Step zones are divided into two layers.\n` +
|
|
4387
4391
|
`[Mismatched/R-Mismatched] Scroll direction flows in different directions up and down.\n` +
|
|
4388
4392
|
`[X-Flower] Lanes spread out like flower petals.\n[Alt-Crossing] Lanes flow from different directions alternately.`,
|