danoniplus 39.1.0 → 39.3.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 CHANGED
@@ -4,12 +4,12 @@
4
4
  *
5
5
  * Source by tickle
6
6
  * Created : 2018/10/08
7
- * Revised : 2025/02/04
7
+ * Revised : 2025/02/09
8
8
  *
9
9
  * https://github.com/cwtickle/danoniplus
10
10
  */
11
- const g_version = `Ver 39.1.0`;
12
- const g_revisedDate = `2025/02/04`;
11
+ const g_version = `Ver 39.3.0`;
12
+ const g_revisedDate = `2025/02/09`;
13
13
 
14
14
  // カスタム用バージョン (danoni_custom.js 等で指定可)
15
15
  let g_localVersion = ``;
@@ -1538,6 +1538,7 @@ const makeBgCanvas = (_ctx, { w = g_sWidth, h = g_sHeight } = {}) => {
1538
1538
  const clearWindow = (_redrawFlg = false, _customDisplayName = ``) => {
1539
1539
  resetKeyControl();
1540
1540
  resetTransform();
1541
+ resetXY();
1541
1542
 
1542
1543
  // ボタン、オブジェクトをクリア (divRoot配下のもの)
1543
1544
  deleteChildspriteAll(`divRoot`);
@@ -9624,6 +9625,7 @@ const getArrowSettings = () => {
9624
9625
  g_workObj.keyCtrl = structuredClone(g_keyObj[`keyCtrl${keyCtrlPtn}`]);
9625
9626
  g_workObj.diffList = [];
9626
9627
  g_workObj.mainEndTime = 0;
9628
+ g_stateObj.layerNum = 2;
9627
9629
 
9628
9630
  g_workObj.keyGroupMaps = tkObj.keyGroupMaps;
9629
9631
  g_workObj.keyGroupList = tkObj.keyGroupList;
@@ -9672,9 +9674,6 @@ const getArrowSettings = () => {
9672
9674
  g_workObj.stepX[j] = g_keyObj.blank * stdPos + (g_headerObj.playingWidth - C_ARW_WIDTH) / 2;
9673
9675
  const baseLayer = g_keyObj[`layerGroup${keyCtrlPtn}`]?.[j] || 0;
9674
9676
  g_workObj.dividePos[j] = baseLayer * 2 + ((posj <= divideCnt ? 0 : 1) + (scrollDirOptions[j] === 1 ? 0 : 1) + (g_stateObj.reverse === C_FLG_OFF ? 0 : 1)) % 2;
9675
- if (g_stateObj.stepArea === `X-Flower`) {
9676
- g_workObj.dividePos[j] = (g_workObj.stepX[j] < (g_headerObj.playingWidth - C_ARW_WIDTH) / 2 ? 0 : 1) * 2 + g_workObj.dividePos[j] % 2;
9677
- }
9678
9677
  g_workObj.scrollDir[j] = (posj <= divideCnt ? 1 : -1) * scrollDirOptions[j] * (g_stateObj.reverse === C_FLG_OFF ? 1 : -1);
9679
9678
 
9680
9679
  eachOrAll.forEach(type => {
@@ -9692,6 +9691,24 @@ const getArrowSettings = () => {
9692
9691
  g_workObj[`frzHitShadowColors${type}`][j] = g_headerObj.frzShadowColor[colorj][1] || ``;
9693
9692
  });
9694
9693
  }
9694
+ g_workObj.orgFlatFlg = g_workObj.dividePos.every(v => v === g_workObj.dividePos[0]);
9695
+ if (g_stateObj.stepArea === `X-Flower` || (g_stateObj.stepArea.includes(`Mismatched`) && g_workObj.orgFlatFlg)) {
9696
+ for (let j = 0; j < keyNum; j++) {
9697
+ g_workObj.dividePos[j] = (g_workObj.stepX[j] < (g_headerObj.playingWidth - C_ARW_WIDTH) / 2 ? 0 : 1) * 2 + g_workObj.dividePos[j] % 2;
9698
+ }
9699
+ }
9700
+ if (g_stateObj.stepArea === `2Step`) {
9701
+ for (let j = 0; j < keyNum; j++) {
9702
+ if (g_workObj.orgFlatFlg && g_workObj.stepX[j] >= (g_headerObj.playingWidth - C_ARW_WIDTH) / 2) {
9703
+ g_workObj.dividePos[j] = Math.floor(g_workObj.dividePos[j] / 2) * 2 + (g_workObj.dividePos[j] + 1) % 2;
9704
+ g_workObj.scrollDir[j] *= -1;
9705
+ }
9706
+ if (g_workObj.dividePos[j] % 2 === (Number(g_stateObj.reverse === C_FLG_ON) + 1) % 2) {
9707
+ g_workObj.dividePos[j] = g_stateObj.layerNum + g_workObj.dividePos[j] + Number(g_stateObj.reverse === C_FLG_ON ? 1 : -1);
9708
+ g_workObj.scrollDir[j] *= -1;
9709
+ }
9710
+ }
9711
+ }
9695
9712
  g_workObj.scrollDirDefault = g_workObj.scrollDir.concat();
9696
9713
  g_workObj.dividePosDefault = g_workObj.dividePos.concat();
9697
9714
  g_stateObj.layerNum = Math.max(g_stateObj.layerNum, Math.ceil((Math.max(...g_workObj.dividePos) + 1) / 2) * 2);
@@ -9814,6 +9831,9 @@ const getArrowSettings = () => {
9814
9831
  g_workObj.drunkXFlg = false;
9815
9832
  g_workObj.drunkYFlg = false;
9816
9833
 
9834
+ // AppearanceFilterの可視範囲設定
9835
+ g_workObj.aprFilterCnt = 0;
9836
+
9817
9837
  if (g_stateObj.dataSaveFlg) {
9818
9838
  // ローカルストレージへAdjustment, HitPosition, Volume設定を保存
9819
9839
  g_storeSettings.forEach(setting => g_localStorage[setting] = g_stateObj[setting]);
@@ -9977,35 +9997,42 @@ const mainInit = () => {
9977
9997
  g_keyObj[`div${keyCtrlPtn}`] < g_keyObj[`${g_keyObj.defaultProp}${keyCtrlPtn}`].length);
9978
9998
  g_workObj.stepZoneDisp = (g_stateObj.d_stepzone === C_FLG_OFF || g_workObj.flatMode) ? C_DIS_NONE : C_DIS_INHERIT;
9979
9999
 
9980
- // Hidden+, Sudden+用のライン、パーセント表示
9981
- const filterCss = g_stateObj.filterLock === C_FLG_OFF ? g_cssObj.life_Failed : g_cssObj.life_Cleared;
9982
- [`filterBar0`, `filterBar1`, `borderBar0`, `borderBar1`].forEach(obj =>
9983
- mainSprite.appendChild(createColorObject2(obj, g_lblPosObj.filterBar, filterCss)));
9984
- borderBar0.style.top = wUnit(g_posObj.stepDiffY + g_stateObj.hitPosition);
9985
- borderBar1.style.top = wUnit(g_posObj.stepDiffY + g_posObj.arrowHeight - g_stateObj.hitPosition);
9986
-
9987
- if (g_appearanceRanges.includes(g_stateObj.appearance)) {
9988
- mainSprite.appendChild(createDivCss2Label(`filterView`, ``, g_lblPosObj.filterView));
9989
- if (g_stateObj.d_filterline === C_FLG_ON) {
9990
- $id(`filterView`).opacity = g_stateObj.opacity / 100;
9991
- $id(`filterBar0`).opacity = g_stateObj.opacity / 100;
9992
- $id(`filterBar1`).opacity = g_stateObj.opacity / 100;
9993
- }
9994
- }
9995
-
9996
10000
  // mainSprite配下に層別のスプライトを作成し、ステップゾーン・矢印本体・フリーズアローヒット部分に分ける
9997
10001
  const mainSpriteN = [], stepSprite = [], arrowSprite = [], frzHitSprite = [];
9998
10002
  const mainCommonPos = { w: g_headerObj.playingWidth, h: g_posObj.arrowHeight };
10003
+
10004
+ // Hidden+, Sudden+用のライン、パーセント表示
10005
+ const filterCss = g_stateObj.filterLock === C_FLG_OFF ? g_cssObj.life_Failed : g_cssObj.life_Cleared;
10006
+ const doubleFilterFlg = ![`Default`, `Halfway`].includes(g_stateObj.stepArea);
10007
+
9999
10008
  for (let j = 0; j < g_stateObj.layerNum; j++) {
10000
10009
  const mainSpriteJ = createEmptySprite(mainSprite, `mainSprite${j}`, mainCommonPos);
10001
10010
  mainSpriteN.push(mainSpriteJ);
10011
+ mainSpriteJ.appendChild(createColorObject2(`filterBar${j}`, g_lblPosObj.filterBar, filterCss));
10012
+ if (doubleFilterFlg) {
10013
+ mainSpriteJ.appendChild(createColorObject2(`filterBar${j % 2 == 0 ? j + 1 : j - 1}_HS`, g_lblPosObj.filterBar, filterCss));
10014
+ }
10002
10015
  addTransform(`mainSprite${j}`, `mainSprite${j}`,
10003
10016
  g_keyObj[`layerTrans${keyCtrlPtn}`]?.[0]?.[Math.floor(j / 2) + (j + Number(g_stateObj.reverse === C_FLG_ON)) % 2]);
10017
+
10004
10018
  stepSprite.push(createEmptySprite(mainSpriteJ, `stepSprite${j}`, mainCommonPos));
10005
10019
  arrowSprite.push(createEmptySprite(mainSpriteJ, `arrowSprite${j}`, Object.assign({ y: g_workObj.hitPosition * (j % 2 === 0 ? 1 : -1) }, mainCommonPos)));
10006
10020
  frzHitSprite.push(createEmptySprite(mainSpriteJ, `frzHitSprite${j}`, mainCommonPos));
10007
10021
  }
10008
10022
 
10023
+ if (g_appearanceRanges.includes(g_stateObj.appearance)) {
10024
+ mainSprite.appendChild(createDivCss2Label(`filterView`, ``, g_lblPosObj.filterView));
10025
+ if (g_stateObj.d_filterline === C_FLG_ON) {
10026
+ $id(`filterView`).opacity = g_stateObj.opacity / 100;
10027
+ for (let j = 0; j < g_stateObj.layerNum; j++) {
10028
+ $id(`filterBar${j}`).opacity = g_stateObj.opacity / 100;
10029
+ if (doubleFilterFlg) {
10030
+ $id(`filterBar${j}_HS`).opacity = g_stateObj.opacity / 100;
10031
+ }
10032
+ }
10033
+ }
10034
+ }
10035
+
10009
10036
  // ステップゾーン、フリーズアローヒット部分の生成
10010
10037
  for (let j = 0; j < keyNum; j++) {
10011
10038
  makeStepZone(j, keyCtrlPtn);
@@ -10039,7 +10066,7 @@ const mainInit = () => {
10039
10066
 
10040
10067
  // Appearanceのオプション適用時は一部描画を隠す
10041
10068
  changeAppearanceFilter(g_appearanceRanges.includes(g_stateObj.appearance) ?
10042
- g_hidSudObj.filterPos : g_hidSudObj.filterPosDefault[g_stateObj.appearance]);
10069
+ g_hidSudObj.filterPos : g_hidSudObj.filterPosDefault[g_stateObj.appearance], true);
10043
10070
 
10044
10071
  // 現在の矢印・フリーズアローの速度、個別加算速度の初期化 (速度変化時に直す)
10045
10072
  g_workObj.currentSpeed = 2;
@@ -11319,8 +11346,9 @@ const makeStepZone = (_j, _keyCtrlPtn) => {
11319
11346
  /**
11320
11347
  * アルファマスクの再描画 (Appearance: Hidden+, Sudden+ 用)
11321
11348
  * @param {number} _num
11349
+ * @param {boolean} _shiftFlg シフトキーを押したかどうかのフラグ
11322
11350
  */
11323
- const changeAppearanceFilter = (_num = 10) => {
11351
+ const changeAppearanceFilter = (_num = 10, _shiftFlg = keyIsShift()) => {
11324
11352
  const MAX_FILTER_POS = 100;
11325
11353
  const topNum = g_hidSudObj[g_stateObj.appearance];
11326
11354
  const bottomNum = (g_hidSudObj[g_stateObj.appearance] + 1) % 2;
@@ -11331,16 +11359,39 @@ const changeAppearanceFilter = (_num = 10) => {
11331
11359
  const numPlus = (g_stateObj.appearance === `Hid&Sud+` ? _num : 0);
11332
11360
  const topShape = `inset(${_num}% 0% ${numPlus}% 0%)`;
11333
11361
  const bottomShape = `inset(${numPlus}% 0% ${_num}% 0%)`;
11362
+ const appearPers = [_num, MAX_FILTER_POS - _num];
11334
11363
 
11335
11364
  for (let j = 0; j < g_stateObj.layerNum; j += 2) {
11336
11365
  $id(`arrowSprite${topNum + j}`).clipPath = topShape;
11337
11366
  $id(`arrowSprite${bottomNum + j}`).clipPath = bottomShape;
11367
+
11368
+ $id(`filterBar${topNum + j}`).top = wUnit(parseFloat($id(`arrowSprite${j}`).top) + g_posObj.arrowHeight * appearPers[topNum] / MAX_FILTER_POS);
11369
+ $id(`filterBar${bottomNum + j}`).top = wUnit(parseFloat($id(`arrowSprite${j + 1}`).top) + g_posObj.arrowHeight * appearPers[bottomNum] / MAX_FILTER_POS);
11370
+
11371
+ if (![`Default`, `Halfway`].includes(g_stateObj.stepArea)) {
11372
+ $id(`filterBar${bottomNum + j}_HS`).top = wUnit(parseFloat($id(`arrowSprite${j}`).top) + g_posObj.arrowHeight * appearPers[bottomNum] / MAX_FILTER_POS);
11373
+ $id(`filterBar${topNum + j}_HS`).top = wUnit(parseFloat($id(`arrowSprite${j + 1}`).top) + g_posObj.arrowHeight * appearPers[topNum] / MAX_FILTER_POS);
11374
+ }
11375
+
11376
+ // 階層が多い場合はShift+pgUp/pgDownで表示する階層グループを切り替え
11377
+ if (_shiftFlg && g_stateObj.d_filterline === C_FLG_ON) {
11378
+ [`${topNum + j}`, `${bottomNum + j}`].forEach(type => {
11379
+ $id(`filterBar${type}`).display = (j === g_workObj.aprFilterCnt ? C_DIS_INHERIT : C_DIS_NONE);
11380
+
11381
+ if (![`Default`, `Halfway`].includes(g_stateObj.stepArea)) {
11382
+ $id(`filterBar${type}_HS`).display = (j === g_workObj.aprFilterCnt ? C_DIS_INHERIT : C_DIS_NONE);
11383
+ }
11384
+ });
11385
+ }
11338
11386
  }
11339
- $id(`filterBar0`).top = wUnit(parseFloat($id(`arrowSprite${topNum}`).top) + g_posObj.arrowHeight * _num / MAX_FILTER_POS);
11340
- $id(`filterBar1`).top = wUnit(parseFloat($id(`arrowSprite${bottomNum}`).top) + g_posObj.arrowHeight * (MAX_FILTER_POS - _num) / MAX_FILTER_POS);
11387
+
11388
+ if (_shiftFlg) {
11389
+ g_workObj.aprFilterCnt = nextPos(g_workObj.aprFilterCnt, 2, g_stateObj.layerNum);
11390
+ }
11391
+
11341
11392
  if (g_appearanceRanges.includes(g_stateObj.appearance)) {
11342
11393
  $id(`filterView`).top =
11343
- $id(`filterBar${g_hidSudObj.std[g_stateObj.appearance][g_stateObj.reverse]}`).top;
11394
+ $id(`filterBar${(g_hidSudObj.std[g_stateObj.appearance][g_stateObj.reverse]) % 2}`).top;
11344
11395
  filterView.textContent = `${_num}%`;
11345
11396
 
11346
11397
  if (g_stateObj.appearance !== `Hid&Sud+` && g_workObj.dividePos.every(v => v === g_workObj.dividePos[0])) {
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * Source by tickle
7
7
  * Created : 2019/11/19
8
- * Revised : 2025/02/04 (v39.1.0)
8
+ * Revised : 2025/02/09 (v39.3.0)
9
9
  *
10
10
  * https://github.com/cwtickle/danoniplus
11
11
  */
@@ -1068,7 +1068,7 @@ const g_settings = {
1068
1068
  playWindows: [`Default`, `Stairs`, `R-Stairs`, `Slope`, `R-Slope`, `Distorted`, `R-Distorted`, `SideScroll`, `R-SideScroll`],
1069
1069
  playWindowNum: 0,
1070
1070
 
1071
- stepAreas: [`Default`, `Halfway`, `Mismatched`, `R-Mismatched`, `X-Flower`],
1071
+ stepAreas: [`Default`, `Halfway`, `2Step`, `Mismatched`, `R-Mismatched`, `X-Flower`],
1072
1072
  stepAreaNum: 0,
1073
1073
 
1074
1074
  frzReturns: [C_FLG_OFF, `X-Axis`, `Y-Axis`, `Z-Axis`, `Random`, `XY-Axis`, `XZ-Axis`, `YZ-Axis`, `Random+`],
@@ -1110,9 +1110,10 @@ const g_moveSettingWindow = (_changePageFlg = true, _direction = 1) => {
1110
1110
  };
1111
1111
 
1112
1112
  /**
1113
- * transform管理
1113
+ * transform, 座標管理
1114
1114
  */
1115
1115
  const g_transforms = {};
1116
+ const g_posXYs = {};
1116
1117
 
1117
1118
  /**
1118
1119
  * idごとのtransformを追加・変更
@@ -1147,6 +1148,57 @@ const resetTransform = () => {
1147
1148
  Object.keys(g_transforms).forEach(_id => g_transforms[_id] = {});
1148
1149
  };
1149
1150
 
1151
+ /**
1152
+ * 座標計算
1153
+ * @param {string} _id
1154
+ * @param {string} _typeId
1155
+ */
1156
+ const calcXY = (_id, _typeId) => {
1157
+ const _posXs = [], _posYs = [];
1158
+ Object.keys(g_posXYs[_id]).forEach(typeId => {
1159
+ _posXs.push(g_posXYs[_id][typeId][0]);
1160
+ _posYs.push(g_posXYs[_id][typeId][1]);
1161
+ });
1162
+ $id(_id).left = `${sumData(_posXs)}px`;
1163
+ $id(_id).top = `${sumData(_posYs)}px`;
1164
+ };
1165
+
1166
+ /**
1167
+ * 座標加算処理
1168
+ * @param {string} _id
1169
+ * @param {string} _typeId
1170
+ * @param {number} _x
1171
+ * @param {number} _y
1172
+ * @param {boolean} [_overwrite=false]
1173
+ */
1174
+ const addXY = (_id, _typeId, _x = 0, _y = 0, _overwrite = false) => {
1175
+ if (_overwrite) {
1176
+ delete g_posXYs?.[_id];
1177
+ }
1178
+ if (g_posXYs[_id] === undefined) {
1179
+ g_posXYs[_id] = {};
1180
+ }
1181
+ g_posXYs[_id][_typeId] = [_x, _y];
1182
+ calcXY(_id, _typeId);
1183
+ };
1184
+
1185
+ /**
1186
+ * 座標リセット処理
1187
+ * @param {string} _id
1188
+ * @param {string} _typeId
1189
+ */
1190
+ const delXY = (_id, _typeId) => {
1191
+ delete g_posXYs[_id][_typeId];
1192
+ calcXY(_id, _typeId);
1193
+ };
1194
+
1195
+ /**
1196
+ * 座標位置情報の初期化
1197
+ */
1198
+ const resetXY = () => {
1199
+ Object.keys(g_posXYs).forEach(_id => delete g_posXYs[_id]);
1200
+ };
1201
+
1150
1202
  /**
1151
1203
  * id, transformIdに合致するtransform情報の取得
1152
1204
  * @param {string} _id
@@ -1218,35 +1270,51 @@ const g_playWindowFunc = {
1218
1270
  'R-SideScroll': () => g_changeStairs(90),
1219
1271
  };
1220
1272
 
1273
+ const g_arrowGroupSprite = [`stepSprite`, `arrowSprite`, `frzHitSprite`];
1221
1274
  const g_stepAreaFunc = {
1222
1275
  'Default': () => ``,
1223
1276
  'Halfway': () => {
1224
- [`stepSprite`, `arrowSprite`, `frzHitSprite`].forEach(sprite => {
1277
+ g_arrowGroupSprite.forEach(sprite => {
1225
1278
  for (let j = 0; j < g_stateObj.layerNum; j++) {
1226
- $id(`${sprite}${j}`).top = `${(j % 2 === 0 ? 1 : -1) * (g_headerObj.playingHeight / 2 - g_posObj.stepY + (g_posObj.stepYR - C_ARW_WIDTH) / 2)}px`;
1279
+ addXY(`${sprite}${j}`, `stepArea`, 0, (j % 2 === 0 ? 1 : -1) * (g_headerObj.playingHeight / 2 - g_posObj.stepY + (g_posObj.stepYR - C_ARW_WIDTH) / 2));
1227
1280
  }
1228
1281
  });
1229
1282
  },
1230
1283
  'Mismatched': () => {
1231
- [`stepSprite`, `arrowSprite`, `frzHitSprite`].forEach(sprite => {
1232
- for (let j = 0; j < g_stateObj.layerNum; j++) {
1233
- addTransform(`${sprite}${j}`, `stepArea`, `rotate(${(j % 2 === 0 ? 1 : -1) * -15}deg)`);
1234
- }
1235
- });
1284
+ for (let j = 0; j < g_stateObj.layerNum; j++) {
1285
+ addTransform(`mainSprite${j}`, `stepArea`, `rotate(${(j % 2 === 0 ? 1 : -1) * -15}deg)`);
1286
+ }
1287
+ if (g_workObj.orgFlatFlg) {
1288
+ g_arrowGroupSprite.forEach(sprite => {
1289
+ for (let j = 2; j < Math.min(g_stateObj.layerNum, 4); j++) {
1290
+ addXY(`${sprite}${j}`, `stepArea`, 0, (j % 2 === 0 ? 1 : -1) * (g_headerObj.playingHeight / 2 - g_posObj.stepY + (g_posObj.stepYR - C_ARW_WIDTH) / 2));
1291
+ }
1292
+ });
1293
+ }
1236
1294
  },
1237
1295
  'R-Mismatched': () => {
1238
- [`stepSprite`, `arrowSprite`, `frzHitSprite`].forEach(sprite => {
1239
- for (let j = 0; j < g_stateObj.layerNum; j++) {
1240
- addTransform(`${sprite}${j}`, `stepArea`, `rotate(${(j % 2 === 0 ? 1 : -1) * 15}deg)`);
1296
+ for (let j = 0; j < g_stateObj.layerNum; j++) {
1297
+ addTransform(`mainSprite${j}`, `stepArea`, `rotate(${(j % 2 === 0 ? 1 : -1) * 15}deg)`);
1298
+ }
1299
+ if (g_workObj.orgFlatFlg) {
1300
+ g_arrowGroupSprite.forEach(sprite => {
1301
+ for (let j = 0; j < Math.min(g_stateObj.layerNum, 2); j++) {
1302
+ addXY(`${sprite}${j}`, `stepArea`, 0, (j % 2 === 0 ? 1 : -1) * (g_headerObj.playingHeight / 2 - g_posObj.stepY + (g_posObj.stepYR - C_ARW_WIDTH) / 2));
1303
+ }
1304
+ });
1305
+ }
1306
+ },
1307
+ '2Step': () => {
1308
+ g_arrowGroupSprite.forEach(sprite => {
1309
+ for (let j = Math.min(g_stateObj.layerNum, 4) / 2; j < Math.min(g_stateObj.layerNum, 4); j++) {
1310
+ addXY(`${sprite}${j}`, `stepArea`, 0, (j % 2 === 0 ? 1 : -1) * (g_headerObj.playingHeight / 2 - g_posObj.stepY + (g_posObj.stepYR - C_ARW_WIDTH) / 2));
1241
1311
  }
1242
1312
  });
1243
1313
  },
1244
1314
  'X-Flower': () => {
1245
- [`stepSprite`, `arrowSprite`, `frzHitSprite`].forEach(sprite => {
1246
- for (let j = 0; j < Math.min(g_stateObj.layerNum, 4); j++) {
1247
- addTransform(`${sprite}${j}`, `stepArea`, `rotate(${(j % 2 === 0 ? 1 : -1) * (j % 4 < 2 ? 1 : -1) * -15}deg)`);
1248
- }
1249
- });
1315
+ for (let j = 0; j < Math.min(g_stateObj.layerNum, 4); j++) {
1316
+ addTransform(`mainSprite${j}`, `stepArea`, `rotate(${(j % 2 === 0 ? 1 : -1) * (j % 4 < 2 ? 1 : -1) * -15}deg)`);
1317
+ }
1250
1318
  },
1251
1319
  };
1252
1320
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "danoniplus",
3
- "version": "39.1.0",
3
+ "version": "39.3.0",
4
4
  "description": "Dancing☆Onigiri (CW Edition) - Web-based Rhythm Game",
5
5
  "main": "index.js",
6
6
  "scripts": {