Project1

标题: 【优先级+确定键触发】大求助! [打印本页]

作者: 小秋橙    时间: 2022-12-14 15:05
标题: 【优先级+确定键触发】大求助!
本帖最后由 小秋橙 于 2023-4-3 21:38 编辑

在p1搜了一下发现不管是支持点击操作的MV和MZ还是只支持键盘操作的前几代板块,好像都没有一个帖子完整讲过【优先级+确定键触发】不同组合的所有情况,这里特意开贴问一下,前人种树后人乘凉。
先说「纯键盘」的情况吧,我们知道「优先级」其实可能更应该叫做「通行性」,「在人物下方」为可通行,「与人物相同」为不可通行(下面就用可通行和不可通行来指代)。
假设没有【柜台】地形,且相关事件都原地不动,那么首先向大家确认下面几条结论是否正确:

A. 可通行+仅确定键触发 = 必须先踩上去再按确定键,只要一直踩着那就按一次触发一次,没有其他触发方式。
B. 可通行+其他触发条件 = 每次踩上去触发,想再次触发必须先走开再踩上去,按确定键没有用。
C. 不可通行+仅确定键触发 = 必须在它的相邻四格并且面对它按确定键才能触发,和A一样按一次触发一次,按方向键撞击它无法触发但【会使主角转身面对它】。
D. 不可通行+其他触发条件 = 在C的基础上,也支持按方向键撞击它触发,撞击一次触发一次,没有办法【转身面对它而不触发】。

如果上面4条都是正确的,那么【主角脚下为A,面前为C】时,按下确定键会发生什么?
如果一律触发A,那么当【C被四个这样的A包围】时不就完全无法触发C了吗?如果一律触发C,那么当【A与垂直方向的两个C相邻时】不就完全无法触发A了吗?
如果是后者,那么游戏作者必须给玩家提供原地转身功能,转向没有C的方向。
如果是前者,MV或MZ可以通过点击C来触发C,因此我猜测更有可能是前者。

至于柜台,作用似乎是「把主角面前距离为2的不可通行事件(?)模拟到面前距离为1的位置」,从而化归到C或D。
如果说上面的结论都没有问题,那么当MV和MZ引入点击操作以后,事情彻底变复杂了,因为触屏设备是没有键盘的。
A在键盘操作时主角是可以「停在A上但不触发」的,而纯点击操作则不行,要么路过,要么「停下来就必须触发」(除非A旁边有不可通行的图块或事件把主角拦停),当然踩着A反复点击它可以反复触发。
C可以通过站在它旁边点击它触发(即使此时主角脚下有A也一样,这是键盘做不到的),但是无法像方向键一样「转身面对它而不触发」,换言之纯点击操作下C其实变成了D。
B和D似乎没什么变化。

欢迎一起讨论这些小细节(上面有任何错误和不完整的敬请指出,比如「柜台」和「事件接触」我一直没怎么研究),另外不要问我为什么要在意这些,因为rpg maker有一种作品类型叫《魔塔》……像A和C这种在键鼠和触屏之间的差异很可能就是整个游戏能否通关的区别。
作者: 小秋橙    时间: 2022-12-14 17:01
JS 代码复制下载
  1. Game_Player.prototype.triggerAction = function() {
  2.     if (this.canMove()) {
  3.         if (this.triggerButtonAction()) {
  4.             return true;
  5.         }
  6.         if (this.triggerTouchAction()) {
  7.             return true;
  8.         }
  9.     }
  10.     return false;
  11. };
  12.  
  13. Game_Player.prototype.triggerButtonAction = function() {
  14.     if (Input.isTriggered("ok")) {
  15.         if (this.getOnOffVehicle()) {
  16.             return true;
  17.         }
  18.         this.checkEventTriggerHere([0]);
  19.         if ($gameMap.setupStartingEvent()) {
  20.             return true;
  21.         }
  22.         this.checkEventTriggerThere([0, 1, 2]);
  23.         if ($gameMap.setupStartingEvent()) {
  24.             return true;
  25.         }
  26.     }
  27.     return false;
  28. };
  29.  
  30. Game_Player.prototype.triggerTouchAction = function() {
  31.     if ($gameTemp.isDestinationValid()) {
  32.         const direction = this.direction();
  33.         const x1 = this.x;
  34.         const y1 = this.y;
  35.         const x2 = $gameMap.roundXWithDirection(x1, direction);
  36.         const y2 = $gameMap.roundYWithDirection(y1, direction);
  37.         const x3 = $gameMap.roundXWithDirection(x2, direction);
  38.         const y3 = $gameMap.roundYWithDirection(y2, direction);
  39.         const destX = $gameTemp.destinationX();
  40.         const destY = $gameTemp.destinationY();
  41.         if (destX === x1 && destY === y1) {
  42.             return this.triggerTouchActionD1(x1, y1);
  43.         } else if (destX === x2 && destY === y2) {
  44.             return this.triggerTouchActionD2(x2, y2);
  45.         } else if (destX === x3 && destY === y3) {
  46.             return this.triggerTouchActionD3(x2, y2);
  47.         }
  48.     }
  49.     return false;
  50. };
  51.  
  52. Game_Player.prototype.triggerTouchActionD1 = function(x1, y1) {
  53.     if ($gameMap.airship().pos(x1, y1)) {
  54.         if (TouchInput.isTriggered() && this.getOnOffVehicle()) {
  55.             return true;
  56.         }
  57.     }
  58.     this.checkEventTriggerHere([0]);
  59.     return $gameMap.setupStartingEvent();
  60. };
  61.  
  62. Game_Player.prototype.triggerTouchActionD2 = function(x2, y2) {
  63.     if ($gameMap.boat().pos(x2, y2) || $gameMap.ship().pos(x2, y2)) {
  64.         if (TouchInput.isTriggered() && this.getOnVehicle()) {
  65.             return true;
  66.         }
  67.     }
  68.     if (this.isInBoat() || this.isInShip()) {
  69.         if (TouchInput.isTriggered() && this.getOffVehicle()) {
  70.             return true;
  71.         }
  72.     }
  73.     this.checkEventTriggerThere([0, 1, 2]);
  74.     return $gameMap.setupStartingEvent();
  75. };
  76.  
  77. Game_Player.prototype.triggerTouchActionD3 = function(x2, y2) {
  78.     if ($gameMap.isCounter(x2, y2)) {
  79.         this.checkEventTriggerThere([0, 1, 2]);
  80.     }
  81.     return $gameMap.setupStartingEvent();
  82. };
  83.  
  84. Game_Player.prototype.checkEventTriggerHere = function(triggers) {
  85.     if (this.canStartLocalEvents()) {
  86.         this.startMapEvent(this.x, this.y, triggers, false);
  87.     }
  88. };
  89.  
  90. Game_Player.prototype.checkEventTriggerThere = function(triggers) {
  91.     if (this.canStartLocalEvents()) {
  92.         const direction = this.direction();
  93.         const x1 = this.x;
  94.         const y1 = this.y;
  95.         const x2 = $gameMap.roundXWithDirection(x1, direction);
  96.         const y2 = $gameMap.roundYWithDirection(y1, direction);
  97.         this.startMapEvent(x2, y2, triggers, true);
  98.         if (!$gameMap.isAnyEventStarting() && $gameMap.isCounter(x2, y2)) {
  99.             const x3 = $gameMap.roundXWithDirection(x2, direction);
  100.             const y3 = $gameMap.roundYWithDirection(y2, direction);
  101.             this.startMapEvent(x3, y3, triggers, true);
  102.         }
  103.     }
  104. };

翻了一下MZ源码,虽然不知道RGSS几代纯键盘操作是怎么样的,但应该和MZ去掉点击操作以后剩余的逻辑差不多,MV的源码估计也差不多。
那么简单梳理一下,在MZ中「确定键」(triggerButtonAction)和「点击屏幕」(triggerTouchAction)都可以触发非B型事件(triggerAction),且一旦前者成功触发就不再同时触发后者。
「确定键」的触发优先级是:乘降载具(没用到载具系统的可以不管)、脚下的A型事件(checkEventTriggerHere)、面前1格的不可通行事件(CD型)、(面前1格为柜台时)面前2格的不可通行事件,一旦有一个成功触发就不再同时触发后者。
「点击屏幕」的触发则取决于「寻路目标点」的坐标,优先级顺序按照这个坐标分为三种情况(triggerTouchActionD1到D3),三种情况彼此没有交集,每一种情况内部一旦有一个成功触发就不再同时触发后者。
(1) 主角脚下:乘降飞艇、该点A型事件。
(2) 主角面前1格:乘降小舟或大船、该点不可通行事件、(该点为柜台时)面前2格不可通行事件。
(3) 主角面前2格:(面前1格为柜台时)该点不可通行事件。
这样就完美解释了「为什么只用键盘无法踩着A触发面前的C,而用点击却可以」。

接下来只要给玩家提供「自由行动时原地无代价转身」的功能就能解决「只用点击如何转身面向C而不触发」,于是最后一个问题就是「只用点击如何停在A上而不触发」。
这个问题刚才研究了好一会也没找到好办法,triggerTouchActionD1中的判定条件是「主角恰好位于寻路目标点」,没办法区分是「从别处走来的」还是「静止时玩家点击了主角」,我希望只有后一种情况触发A而前一种不触发,有人能帮帮我吗?
作者: 小秋橙    时间: 2022-12-16 13:35
本帖最后由 小秋橙 于 2023-4-3 21:40 编辑

啊,为什么从来都是别人提问我就跑去解答,我一提问就沉了,是因为mz比mv板块更冷清么?虽然这个问题在mv肯定也是一样的关注度但是发两份感觉不太好,嗯如果有哪位大佬有解决思路欢迎回复~




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1