找回密码
 注册用户
查看: 160|回复: 0

[RMMV] 【汉化】滑动拼图小游戏

[复制链接]

88

主题

7

回帖

1277

积分

资深会员

积分
1277
发表于 2024-6-1 14:47:17 | 显示全部楼层 |阅读模式
本帖最后由 烁灵 于 2024-6-20 17:48 编辑

增加一个滑动拼图小游戏。
可以选择用光标/方向键控制。
游戏结果将记录在指定变量里,变量ID在插件配置里修改。
试了一下就算是 3*3 玩起来也很反人类啊!


原贴:Sliding puzzle minigame | RPG Maker Forums (rpgmakerweb.com)


预览:
QQ截图20240601142751.png


范例:https://www.123pan.com/s/uBKyVv-VzF3A.html 提取码:JAUd

汉化脚本:命名为 MAC_SlidingPuzzle.js
  1. /*:
  2. * @plugindesc (v1.0) 增加一个滑动拼图小游戏
  3. * 汉化 by 烁灵 更多脚本请访问 www.hknmtt.com
  4. * @author Mac15001900
  5. *
  6. * @param Interface
  7. *
  8. * @param Puzzle size
  9. * @desc 拼图像素尺寸,强烈建议设置为格子的倍数值
  10. * @default 540
  11. * @parent Interface
  12. *
  13. * @param Lines colour
  14. * @desc 格子分割线颜色,留空隐藏分割线,使用CSS的颜色格式
  15. * @type text
  16. * @default white
  17. * @parent Interface
  18. *
  19. * @param Control scheme
  20. * @desc "Cursor" 表示用光标控制当前格子. "Slide" 表示用方向键直接控制对应方向的格子.
  21. * @type select
  22. * @default Slide
  23. * @option 光标 Cursor
  24. * @value Cursor
  25. * @option 滑动 Slide
  26. * @value Slide
  27. * @option 滑动 Slide (反向)
  28. * @value Slide (inverted)
  29. * @parent Interface
  30. *
  31. * @param Timer
  32. * @desc 是否显示计时器.
  33. * @type boolean
  34. * @default true
  35. * @on Shown
  36. * @off Hidden
  37. * @parent Interface
  38. *
  39. * @param Move counter
  40. * @desc 是否记录步数.
  41. * @type boolean
  42. * @default false
  43. * @on Shown
  44. * @off Hidden
  45. * @parent Interface
  46. *
  47. * @param Outputs
  48. *
  49. * @param Victory
  50. * @text Victory switch
  51. * @desc 当胜利时,该开关为 ON,放弃时为 OFF.
  52. * @type number
  53. * @parent Outputs
  54. * @default 0
  55. *
  56. * @param Total seconds
  57. * @text 记录总秒数的变量 ID
  58. * @desc 游戏时间总秒数将记录到该变量
  59. * @type number
  60. * @parent Outputs
  61. * @default 0
  62. *
  63. * @param Display seconds
  64. * @text 秒数变量 ID
  65. * @desc 当游戏结束时,计时器上的 秒 数(0 ~ 59)将记录到该变量.
  66. * @type number
  67. * @parent Outputs
  68. * @default 0
  69. *
  70. * @param Display minutes
  71. * @text 分钟数变量 ID
  72. * @desc 当游戏结束时,计时器上的 分钟 数将记录到该变量.
  73. * @type number
  74. * @parent Outputs
  75. * @default 0
  76. *
  77. * @param Move count
  78. * @text 步数变量 ID
  79. * @desc 游戏总步数将记录到该变量
  80. * @type number
  81. * @parent Outputs
  82. * @default 0
  83. *
  84. * @param Text
  85. *
  86. * @param Exit
  87. * @desc 退出按钮的文本
  88. * @type text
  89. * @default 退出
  90. * @parent Text
  91. *
  92. * @param Cancel
  93. * @desc 取消按钮的文本
  94. * @type text
  95. * @default 取消
  96. * @parent Text
  97. *
  98. * @param Sounds
  99. *
  100. * @param Cursor sound
  101. * @desc 光标音效,设置为 "None" 则不使用音效
  102. * @type file
  103. * @dir audio/se
  104. * @parent Sounds
  105. * @default Cursor1
  106. *
  107. * @param Slide sound
  108. * @desc 键盘音效,设置为 "None" 则不使用音效
  109. * @type file
  110. * @dir audio/se
  111. * @parent Sounds
  112. * @default Wind7
  113. *
  114. * @param Victory music
  115. * @desc 胜利 ME,设置为 "None" 则不使用音效
  116. * @type file
  117. * @dir audio/me
  118. * @parent Sounds
  119. * @default Victory1
  120. *
  121. *
  122. * @help 此插件增加一个拼图小游戏
  123. *
  124. * 你可以使用 SlidingPuzzle 事件指令打开小游戏, 参数时格子数和 /img/pictures 文件夹
  125. * 中的图片文件名。格子数可以使用变量的值制定,写法 "v42" 表示使用 42 号变量的值。
  126. *
  127. * 例如:
  128. * SlidingPuzzle 4 Fountain
  129. * 将开启 4x4 的拼图,使用 "Fountain.png" 图片文件。
  130. *
  131. * 只需 1 张图片即可,它会被自动切割,图片不会被缩放,因此建议使用与拼图窗口一致的图片
  132. * (默认是 540x540), 使用大图片也可以,他们会被自动裁切。
  133. *
  134. * 经过的时间、步数、是否胜利、是否放弃都会被记录在插件设置的变量里。
  135. *
  136. * ---------------------------------------------------------------------------------
  137. *
  138. * 在游戏中也可以使用 SlidingPuzzleParam 指令改变插件参数。新的数值跟在变量名后边,使用
  139. * 下划线代替空格。例如:
  140. *
  141. * SlidingPuzzleParam Lines_colour crimson
  142. * 将会改变分割线的颜色。
  143. *
  144. * 重要提示: 这些提示不会被存档保存,游戏重启后会恢复,因此需要在执行 SlidingPuzzle 前
  145. * 重新设置
  146. *
  147. * ---------------------------------------------------------------------------------
  148. *
  149. * This plugin is available under the MIT Licence. You're free to use it in any
  150. * games, commercial or not, or use the code in your own plugins. Credit is
  151. * appreciated, but not required.
  152. */


  153. var Imported = Imported || {}
  154. Imported.MAC_SlidingPuzzle = "1.0";
  155. window.MAC_SlidingPuzzle = {};


  156. void function ($) {

  157.     let params = PluginManager.parameters('MAC_SlidingPuzzle');
  158.     let puzzleArguments = null;
  159.     $.LINE_WIDTH = 4; //Width of the grid lines, in pixels
  160.     $.VICTORY_ANIMATION_DURATION = 60 * 3; //How long the victory animation lasts, in frames
  161.     $.TIMER_WIDTH = 108; //Width of the timer window (and the move counter), in pixels
  162.     $.params = params;

  163.     void ((alias) => {
  164.         Game_Interpreter.prototype.pluginCommand = function (command, args) {
  165.             if (command.toLowerCase() === 'slidingpuzzle') {
  166.                 console.log("Starting sliding puzzle");
  167.                 puzzleArguments = [...args];
  168.                 if (puzzleArguments.length < 2) throw new RangeError("MAC_SlidingPuzzle: You must specify a puzzle size and an image.");
  169.                 if (!Number.isInteger(numberValue(puzzleArguments[0]))) throw new TypeError("MAC_SlidingPuzzle: The size of the puzzle must be a number or a variable identifier (e.g. v42).");
  170.                 if (numberValue(puzzleArguments[0]) < 2) throw new Error("MAC_SlidingPuzzle: The minimum size of a sliding puzzle is 2.");
  171.                 if (numberValue(puzzleArguments[0]) > 100) console.warn("MAC_SlidingPuzzle: Starting a puzzle that's larger than 100x100. Are you sure that's what you wanted to do?");
  172.                 if (puzzleArguments[1].includes(".png")) throw new Error("MAC_SlidingPuzzle: Do not include the extension in name of the image.");
  173.                 SceneManager.push(Scene_SlidingPuzzle);
  174.             } else if (command.toLowerCase() === 'slidingpuzzleparam') {
  175.                 let name = args[0].replace(/_/g, ' ');
  176.                 if (typeof params[name] === 'undefined') console.warn(name + " is not an existing plugin parameter");
  177.                 params[name] = args[1];
  178.             }
  179.             alias.call(this, command, args);

  180.         }
  181.     })(Game_Interpreter.prototype.pluginCommand);


  182.     //--------------------- Window_SlidingPuzzle ---------------------

  183.     //--------- Initialisation ---------
  184.     function Window_SlidingPuzzle() {
  185.         this.initialize.apply(this, arguments);
  186.     };
  187.     Window_SlidingPuzzle.prototype = Object.create(Window_Command.prototype);
  188.     Window_SlidingPuzzle.prototype.constructor = Window_SlidingPuzzle;
  189.     Window_SlidingPuzzle.prototype.initialize = function (image, size) {
  190.         Window_Command.prototype.initialize.call(this, 0, 0);
  191.         this.size = Number(size);
  192.         this.cells = this.size * this.size;
  193.         this.cellWidth = numberValue(params['Puzzle size']) / this.size;

  194.         //Creating the board
  195.         this.values = [...Array(this.cells).keys()];
  196.         this.shuffleArray(this.values);
  197.         while (this.values.filter((v, i) => v === i).length > this.cells * 0.7) this.shuffleArray(this.values); //If over 70% is already correct, reshuffle
  198.         let zeroIndex = this.values.indexOf(0);
  199.         this.values[zeroIndex] = this.values[0];
  200.         this.values[0] = 0;
  201.         this.ensureSolvability(this.values);

  202.         //Initialising internal variables
  203.         this.lastKeyStates = [false, false, false, false]; //Which movement keys were held on last frame [up, down, left, right]
  204.         this.animations = {};
  205.         this.framesPassed = 0; //How many frames passed since the puzzle started (i.e. the image has loaded)
  206.         this.moves = 0; //Move counter
  207.         this.victory = false; //Whether the player has won
  208.         this.finished = false; //Whether the game is done, i.e. victory is achieved and the victory animation is done

  209.         //Resising the window
  210.         this.height = numberValue(params['Puzzle size']) + this.standardPadding() * 2 + $.LINE_WIDTH;
  211.         this.x = Graphics.boxWidth / 2 - this.width / 2;
  212.         this.y = Graphics.boxHeight / 2 - this.height / 2;
  213.         this.refresh();
  214.         this.activate();
  215.         this.select(0);

  216.         //Loading the image
  217.         let bmp = ImageManager.loadPicture(image);
  218.         bmp.addLoadListener(function () {
  219.             this.image = bmp;
  220.             this.framesPassed = 0;
  221.             if (bmp.width < numberValue(params['Puzzle size']) || bmp.height < numberValue(params['Puzzle size'])) throw Error(`MAC_SlidingPuzzle: ${image} is too small to fill the puzzle. Use a larger image or decrease the window size.`);
  222.             this.refresh();
  223.         }.bind(this));
  224.     }

  225.     Window_SlidingPuzzle.prototype.shuffleArray = function (array) {
  226.         for (let i = array.length - 1; i > 0; i--) {
  227.             let j = Math.floor(Math.random() * (i + 1));
  228.             let temp = array[i];
  229.             array[i] = array[j];
  230.             array[j] = temp;
  231.         }
  232.     }

  233.     Window_SlidingPuzzle.prototype.ensureSolvability = function (values) {
  234.         if (this.isSolvable(values)) return;
  235.         //If not solvable, swap tiles 1 and 2 to change polarity
  236.         let oneIndex = values.indexOf(1);
  237.         let twoIndex = values.indexOf(2);
  238.         values[oneIndex] = 2;
  239.         values[twoIndex] = 1;
  240.     }

  241.     //Using logic from https://www.geeksforgeeks.org/check-instance-15-puzzle-solvable/
  242.     Window_SlidingPuzzle.prototype.isSolvable = function (values) {
  243.         //Count inversions
  244.         let inversions = 0;
  245.         for (let i = 0; i < values.length - 1; i++) {
  246.             if (values[i] === 0) continue;
  247.             for (let j = i + 1; j < values.length; j++) {
  248.                 if (values[j] === 0) continue;
  249.                 if (values[i] > values[j]) inversions++;
  250.             }
  251.         }
  252.         //Check if solvable
  253.         if (this.size % 2 == 0) {
  254.             if (Math.floor(values.indexOf(0) / this.size) % 2 == 0) return inversions % 2 === 0;
  255.             else return inversions % 2 !== 0;
  256.         } else return inversions % 2 === 0;
  257.     }


  258.     Window_SlidingPuzzle.prototype.makeCommandList = function () {
  259.         for (let i = 0; i < this.cells; i++) {
  260.             this.addCommand(i + 1, 'ok', true, i);
  261.         }
  262.     }

  263.     //--------- Puzzle logic ---------
  264.     Window_SlidingPuzzle.prototype.update = function () {
  265.         Window_Command.prototype.update.call(this);
  266.         this.updateAnimations();
  267.         this.framesPassed++;
  268.         if (this.victory && !this.finished) {
  269.             if (this.framesPassed - this.victoryTime >= $.VICTORY_ANIMATION_DURATION) {
  270.                 this.finished = true;
  271.                 this.pause = true;
  272.             }
  273.             this.refresh();
  274.         }
  275.     }

  276.     //Swaps the tile at the given index with the empty one.
  277.     Window_SlidingPuzzle.prototype.swapTile = function (index) {
  278.         let zeroIndex = this.values.indexOf(0);
  279.         this.values[zeroIndex] = this.values[index];
  280.         this.values[index] = 0;
  281.         this.moves++;
  282.         this.refresh();
  283.         this.checkForVictory();

  284.         this.startAnimation(index, zeroIndex);
  285.         if (params["Slide sound"]) AudioManager.playSe({ name: params["Slide sound"], volume: 100, pitch: 100 });
  286.     }

  287.     Window_SlidingPuzzle.prototype.checkForVictory = function () {
  288.         if (this.values.every((v, i) => v === i)) {
  289.             console.log("Victory!");
  290.             this.victory = true;
  291.             this.victoryTime = this.framesPassed;
  292.             this.setupOutputs();
  293.             if (params["Victory music"].length > 0) AudioManager.playMe({ name: params["Victory music"], volume: 100, pitch: 100 });
  294.             this.select(-1); //This effectively hides the cursor
  295.         }
  296.     }

  297.     Window_SlidingPuzzle.prototype.setupOutputs = function () {
  298.         $gameSwitches.setValue(Number(params["Victory"]), this.victory)
  299.         let seconds = Math.floor(this.framesPassed / 60);
  300.         $gameVariables.setValue(Number(params["Total seconds"]), seconds);
  301.         $gameVariables.setValue(Number(params["Display seconds"]), seconds % 60);
  302.         $gameVariables.setValue(Number(params["Display minutes"]), Math.floor(seconds / 60));
  303.         $gameVariables.setValue(Number(params["Move count"]), this.moves);
  304.     }

  305.     Window_SlidingPuzzle.prototype.exit = function () {
  306.         this.close();
  307.         setTimeout(() => {
  308.             SceneManager.pop();
  309.         }, 200);
  310.     }

  311.     //--------- Handling input ---------
  312.     Window_SlidingPuzzle.prototype.moveCursor = function (dx, dy) {
  313.         if (this.victory) return;
  314.         switch (params["Control scheme"]) {
  315.             case "Cursor":
  316.                 this.select(this.offsetIndex(this.index(), dx, dy));
  317.                 if (Input.isPressed('ok')) this.processOk();
  318.                 break;
  319.             case "Slide":
  320.                 dx *= -1;
  321.                 dy *= -1;
  322.             case "Slide (inverted)":
  323.                 if (dx !== 0 && dy !== 0) { //Make sure we're only moving in one dimension at a time
  324.                     this.moveCursor(params["Control scheme"] === "Slide" ? -dx : dx, 0);
  325.                     dx = 0;
  326.                 }
  327.                 //Check if it'd move out of bounds
  328.                 let index = this.values.indexOf(0);
  329.                 if (index % this.size === 0 && dx < 0 || index % this.size === this.size - 1 && dx > 0 ||
  330.                     index < this.size && dy < 0 || index >= this.cells - this.size && dy > 0) return;
  331.                 this.swapTile(this.offsetIndex(index, dx, dy));
  332.                 break;
  333.             default: console.error("Invalid control scheme");
  334.         }
  335.     }

  336.     Window_SlidingPuzzle.prototype.offsetIndex = function (index, dx, dy) {
  337.         if (dx !== 0)
  338.             index = Math.floor(index / this.size) * this.size + (index % this.size + dx + this.size) % this.size;
  339.         if (dy !== 0)
  340.             index = (this.cells + index + dy * this.size) % this.cells;
  341.         return index;
  342.     }

  343.     Window_SlidingPuzzle.prototype.processCursorMove = function () {
  344.         if (this.isCursorMovable()) {
  345.             let lastIndex = this.index();
  346.             let dx = 0; dy = 0;
  347.             //RM's Input doesn't understand the concept of pressing two keys on the same frame, so we need to hack around it a bit to make diagonal movement reliable
  348.             let doRepeats = (Input._pressedTime >= Input.keyRepeatInterval * 2 && Input._pressedTime % Input.keyRepeatInterval === 0);
  349.             if (Input.isPressed('up') && (!this.lastKeyStates[0] || doRepeats)) dy--;
  350.             if (Input.isPressed('down') && (!this.lastKeyStates[1] || doRepeats)) dy++;
  351.             if (Input.isPressed('left') && (!this.lastKeyStates[2] || doRepeats)) dx--;
  352.             if (Input.isPressed('right') && (!this.lastKeyStates[3] || doRepeats)) dx++;
  353.             if (dx !== 0 || dy !== 0) this.moveCursor(dx, dy);
  354.             if (this.index() !== lastIndex) {
  355.                 if (params["Cursor sound"]) AudioManager.playSe({ name: params["Cursor sound"], volume: 100, pitch: 100 });
  356.             }
  357.             this.lastKeyStates = ['up', 'down', 'left', 'right'].map(k => Input.isPressed(k));
  358.         }
  359.     };

  360.     Window_SlidingPuzzle.prototype.processOk = function () {
  361.         if (this._closing) return;
  362.         if (this.finished) this.exit();
  363.         if (this.victory) return;
  364.         let zeroIndex = this.values.indexOf(0);
  365.         let index = this.index();
  366.         //Check if they're neighbours
  367.         if (Math.abs(zeroIndex - index) === 1 && Math.floor(zeroIndex / this.size) === Math.floor(index / this.size) ||
  368.             Math.abs(zeroIndex - index) === this.size && zeroIndex % this.size === index % this.size) {
  369.             this.swapTile(index);
  370.         }
  371.     }

  372.     Window_SlidingPuzzle.prototype.onTouch = function (triggered) {
  373.         if (this._closing) return;
  374.         if (this.finished) {
  375.             this.exit();
  376.             return;
  377.         }
  378.         var x = this.canvasToLocalX(TouchInput.x);
  379.         var y = this.canvasToLocalY(TouchInput.y);
  380.         var hitIndex = this.hitTest(x, y);
  381.         if (hitIndex >= 0) {
  382.             this.select(hitIndex);
  383.             this.processOk();
  384.         }
  385.     }

  386.     //--------- Graphical stuff ---------
  387.     Window_SlidingPuzzle.prototype.maxCols = function () {
  388.         return this.size;
  389.     };

  390.     Window_SlidingPuzzle.prototype.spacing = function () {
  391.         return 1;
  392.     };

  393.     Window_SlidingPuzzle.prototype.itemHeight = function () {
  394.         return numberValue(params['Puzzle size']) / this.size;
  395.     };

  396.     Window_SlidingPuzzle.prototype.windowWidth = function () {
  397.         return numberValue(params['Puzzle size']) + this.standardPadding() * 2 + $.LINE_WIDTH;
  398.     };

  399.     Window_SlidingPuzzle.prototype.refresh = function () {
  400.         Window_Command.prototype.refresh.call(this);
  401.         if (this.finished) return;
  402.         if (params["Lines colour"].length > 0) {
  403.             let ctx = this.contents._context;
  404.             ctx.beginPath();
  405.             ctx.lineWidth = $.LINE_WIDTH;
  406.             if (this.victory) ctx.globalAlpha = 1 - (this.framesPassed - this.victoryTime) / $.VICTORY_ANIMATION_DURATION;
  407.             let cellSize = numberValue(params['Puzzle size']) / this.size;
  408.             //Draw vertical lines
  409.             for (let i = 0; i <= this.size; i++) {
  410.                 ctx.moveTo(i * cellSize + $.LINE_WIDTH / 2, 0);
  411.                 ctx.lineTo(i * cellSize + $.LINE_WIDTH / 2, this.height);
  412.             }
  413.             //Draw horizontal lines
  414.             for (let i = 0; i <= this.size; i++) {
  415.                 ctx.moveTo(0, i * cellSize + $.LINE_WIDTH / 2);
  416.                 ctx.lineTo(this.width, i * cellSize + $.LINE_WIDTH / 2);
  417.             }
  418.             ctx.strokeStyle = params["Lines colour"];
  419.             ctx.stroke();
  420.             ctx.globalAlpha = 1;
  421.         }
  422.     }

  423.     Window_SlidingPuzzle.prototype.drawItem = function (index) {
  424.         if (!this.image) return;
  425.         if (this.values[index] === 0) {
  426.             if (!this.victory) return;
  427.             this.contents._context.globalAlpha = (this.framesPassed - this.victoryTime) / $.VICTORY_ANIMATION_DURATION;
  428.         }

  429.         let s = this.cellWidth; //Size of a single cell
  430.         let xg = (index % this.size); //Positions in the grid
  431.         let yg = Math.floor(index / this.size);
  432.         let xi = (this.values[index] % this.size); //Positions in the source image
  433.         let yi = Math.floor(this.values[index] / this.size);
  434.         if (this.animations[index]) {
  435.             xg += this.animations[index].dx;
  436.             yg += this.animations[index].dy;
  437.         }
  438.         this.contents.blt(this.image, xi * s, yi * s, s, s, xg * s + $.LINE_WIDTH / 2, yg * s + $.LINE_WIDTH / 2);
  439.         if (this.values[index] === 0) this.contents._context.globalAlpha = 1;
  440.     };

  441.     //--------- Handling animations ---------
  442.     Window_SlidingPuzzle.prototype.updateAnimations = function () {
  443.         let needsRefresh = false;
  444.         for (let i in this.animations) {
  445.             if (!this.animations[i]) continue;
  446.             this.animations[i].dx *= 0.7;
  447.             this.animations[i].dy *= 0.7;
  448.             this.animations[i].framesLeft--;
  449.             if (this.animations[i].framesLeft <= 0) {
  450.                 delete this.animations[i];
  451.             }
  452.             needsRefresh = true;
  453.         }
  454.         if (needsRefresh) this.refresh();
  455.     }

  456.     Window_SlidingPuzzle.prototype.startAnimation = function (startIndex, endIndex) {
  457.         this.animations[endIndex] = {
  458.             dx: (startIndex % this.size) - (endIndex % this.size),
  459.             dy: Math.floor(startIndex / this.size) - Math.floor(endIndex / this.size),
  460.             framesLeft: 60,
  461.         };
  462.     }

  463.     Window_SlidingPuzzle.prototype.skipVictoryAnimation = function () {
  464.         if (this.finished) return;
  465.         this.framesPassed = this.victoryTime + $.VICTORY_ANIMATION_DURATION - 1;
  466.     }

  467.     //--------- Cursor tweaks ---------
  468.     //Overwriting this to change the order parts are added and make sure the cursor is on top. Otherwise it would render below the images.
  469.     Window_SlidingPuzzle.prototype._createAllParts = function () {
  470.         this._windowSpriteContainer = new PIXI.Container();
  471.         this._windowBackSprite = new Sprite();
  472.         this._windowCursorSprite = new Sprite();
  473.         this._windowFrameSprite = new Sprite();
  474.         this._windowContentsSprite = new Sprite();
  475.         this._downArrowSprite = new Sprite();
  476.         this._upArrowSprite = new Sprite();
  477.         this._windowPauseSignSprite = new Sprite();
  478.         this._windowBackSprite.bitmap = new Bitmap(1, 1);
  479.         this._windowBackSprite.alpha = 192 / 255;
  480.         this.addChild(this._windowSpriteContainer);
  481.         this._windowSpriteContainer.addChild(this._windowBackSprite);
  482.         this._windowSpriteContainer.addChild(this._windowFrameSprite);
  483.         this.addChild(this._windowContentsSprite);
  484.         this.addChild(this._downArrowSprite);
  485.         this.addChild(this._upArrowSprite);
  486.         this.addChild(this._windowPauseSignSprite);
  487.         if (params["Control scheme"] === "Cursor") this.addChild(this._windowCursorSprite); //That's the only mode where we need the cursor sprite
  488.         if (this._createColorFilter) this._createColorFilter(); //For compatibility with Window Upgrade, which calls this function in an alias of Window
  489.     };

  490.     Window_SlidingPuzzle.prototype.itemRect = function (index) {
  491.         var rect = new Rectangle();
  492.         var maxCols = this.maxCols();
  493.         rect.width = this.itemWidth();
  494.         rect.height = this.itemHeight();
  495.         rect.x = index % maxCols * (rect.width + this.spacing()) - this._scrollX + $.LINE_WIDTH / 2;
  496.         rect.y = Math.floor(index / maxCols) * rect.height - this._scrollY + $.LINE_WIDTH / 2;
  497.         return rect;
  498.     };

  499.     //--------------------- Exit confirmation ---------------------
  500.     function Window_SlidingPuzzleExitConfirmation() {
  501.         this.initialize.apply(this, arguments);
  502.     };

  503.     Window_SlidingPuzzleExitConfirmation.prototype = Object.create(Window_Command.prototype);
  504.     Window_SlidingPuzzleExitConfirmation.prototype.constructor = Window_SlidingPuzzleExitConfirmation;
  505.     Window_SlidingPuzzleExitConfirmation.prototype.initialize = function () {
  506.         Window_Command.prototype.initialize.call(this, 0, 0);
  507.         this.x = Graphics.boxWidth / 2 - this.width / 2;
  508.         this.y = Graphics.boxHeight / 2 - this.height / 2;
  509.         this.refresh();
  510.         this.activate();
  511.         this.select(1);
  512.     }

  513.     Window_SlidingPuzzleExitConfirmation.prototype.makeCommandList = function () {
  514.         this.addCommand(params["Exit"], "ok");
  515.         this.addCommand(params["Cancel"], "ok");
  516.     }

  517.     //--------------------- Window_Timer ---------------------
  518.     function Window_Timer() {
  519.         this.initialize.apply(this, arguments);
  520.     };

  521.     Window_Timer.prototype = Object.create(Window_Base.prototype);
  522.     Window_Timer.prototype.constructor = Window_Timer;
  523.     Window_Timer.prototype.initialize = function (parent) {
  524.         Window_Base.prototype.initialize.call(this, 0, 0, $.TIMER_WIDTH, this.fittingHeight(1));
  525.         this.mainWindow = parent;
  526.         this.refresh();
  527.     }

  528.     Window_Timer.prototype.refresh = function () {
  529.         this.contents.clear();
  530.         let totalFrames = this.mainWindow.victory ? this.mainWindow.victoryTime : this.mainWindow.framesPassed;
  531.         let seconds = Math.floor(totalFrames / 60);
  532.         let minutes = Math.floor(seconds / 60);
  533.         seconds %= 60;
  534.         let text = `${String(minutes).padZero(2)}:${String(seconds).padZero(2)}`;
  535.         if (minutes > 99) text = `${minutes}m`;
  536.         this.drawText(text, 0, 0, this.contentsWidth(), "center");
  537.     }

  538.     Window_Timer.prototype.update = function () {
  539.         Window_Base.prototype.update.call(this);
  540.         this.refresh();
  541.     }

  542.     //--------------------- Window_MoveCounter ---------------------
  543.     function Window_MoveCounter() {
  544.         this.initialize.apply(this, arguments);
  545.     };

  546.     Window_MoveCounter.prototype = Object.create(Window_Base.prototype);
  547.     Window_MoveCounter.prototype.constructor = Window_MoveCounter;
  548.     Window_MoveCounter.prototype.initialize = function (parent, y) {
  549.         Window_Base.prototype.initialize.call(this, 0, y, $.TIMER_WIDTH, this.fittingHeight(1));
  550.         this.mainWindow = parent;
  551.         this.refresh();
  552.     }

  553.     Window_MoveCounter.prototype.refresh = function () {
  554.         this.contents.clear();
  555.         let text = `${this.mainWindow.moves}`;
  556.         this.drawText(text, 0, 0, this.contentsWidth(), "right");
  557.     }

  558.     Window_MoveCounter.prototype.update = function () {
  559.         Window_Base.prototype.update.call(this);
  560.         this.refresh();
  561.     }

  562.     //--------------------- Scene_SlidingPuzzle ---------------------


  563.     function Scene_SlidingPuzzle() {
  564.         this.initialize.apply(this, arguments);
  565.     }

  566.     Scene_SlidingPuzzle.prototype = Object.create(Scene_MenuBase.prototype);
  567.     Scene_SlidingPuzzle.prototype.constructor = Scene_SlidingPuzzle;

  568.     Scene_SlidingPuzzle.prototype.initialize = function () {
  569.         Scene_MenuBase.prototype.initialize.call(this);
  570.     };

  571.     Scene_SlidingPuzzle.prototype.create = function () {
  572.         Scene_MenuBase.prototype.create.call(this);
  573.         this.mainWindow = new Window_SlidingPuzzle(puzzleArguments[1], puzzleArguments[0]);
  574.         this.mainWindow.setHandler('cancel', this.onCancelButton.bind(this));
  575.         this.addWindow(this.mainWindow);
  576.         $.mainWindow = this.mainWindow;
  577.         if (params["Timer"] === "true") {
  578.             this.timerWindow = new Window_Timer(this.mainWindow);
  579.             $.timerWindow = this.timerWindow;
  580.             this.addWindow(this.timerWindow);
  581.         }
  582.         if (params["Move counter"] === "true") {
  583.             this.moveCounterWindow = new Window_MoveCounter(this.mainWindow, this.timerWindow ? this.timerWindow.height : 0);
  584.             $.moveCounterWindow = this.moveCounterWindow;
  585.             this.addWindow(this.moveCounterWindow);
  586.         }
  587.     };

  588.     Scene_SlidingPuzzle.prototype.terminate = function () {
  589.         Scene_MenuBase.prototype.terminate.call(this);
  590.     };

  591.     Scene_SlidingPuzzle.prototype.update = function () {
  592.         Scene_MenuBase.prototype.update.call(this);
  593.     }

  594.     Scene_SlidingPuzzle.prototype.onCancelButton = function () {
  595.         if (this.mainWindow.finished) {
  596.             this.mainWindow.activate();
  597.             this.mainWindow.processOk();
  598.             return;
  599.         }
  600.         if (this.mainWindow.victory) {
  601.             this.mainWindow.skipVictoryAnimation();
  602.             this.mainWindow.activate();
  603.             return;
  604.         }
  605.         this.cancelWindow = new Window_SlidingPuzzleExitConfirmation();
  606.         this.cancelWindow.setHandler('ok', this.onCancelWindowOk.bind(this));
  607.         this.cancelWindow.setHandler('cancel', () => { this.mainWindow.activate(); this.cancelWindow.close(); });
  608.         this.addWindow(this.cancelWindow);
  609.     }

  610.     Scene_SlidingPuzzle.prototype.onCancelWindowOk = function () {
  611.         if (this.cancelWindow.index() === 0) {
  612.             this.mainWindow.setupOutputs();
  613.             this.cancelWindow.close();
  614.             this.mainWindow.exit();
  615.         }
  616.         else {
  617.             this.cancelWindow.close();
  618.             this.mainWindow.activate();
  619.         }
  620.     }

  621.     //--------------------- Misc utils ---------------------

  622.     /**
  623.     * Converts a string (from plugin parameters or commands) to a number, regardless is that string contains a number literal of a variable indentifier
  624.     * @param {String|Number} string A number or variable indentifier (in the form v42 or v0042)
  625.     * @returns The string converted to a number
  626.     */
  627.     numberValue = function (string) {
  628.         if (string[0] === 'v') return $gameVariables.value(Number(string.replace(/^v0*/, '')));
  629.         else return Number(string);
  630.     }

  631. }(MAC_SlidingPuzzle);
复制代码


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册用户

本版积分规则

Archiver|QQ群: 48625831|爱上RPG|哈库纳玛塔塔 |网站地图 Clicky

GMT+8, 2024-10-23 13:24 , Processed in 0.077074 second(s), 21 queries .

Powered by Discuz! X3.5

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表