设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 2151|回复: 4
打印 上一主题 下一主题

[交流讨论] MV插件开发杂谈之Mixin与继承

[复制链接]

Lv3.寻梦者

梦石
0
星屑
1882
在线时间
1552 小时
注册时间
2013-4-13
帖子
917
跳转到指定楼层
1
发表于 2019-10-21 00:06:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
本帖最后由 沉滞的剑 于 2019-10-21 00:12 编辑

当在JS拓展功能的时候会面临两个选择:

1. 修改现有的类(Mixin)
本质上是将原有类的原型上增加新的属性
亦或
2. 从现有的类的基础上派生出信的类(继承)
本质上是将新的类的原型指向旧类的原型

这两种方法是RM中插件拓展的基础, 必须要掌握

我现在要做一个拥有Window_Base的功能且能拖拽的窗口
最常见的做法就是新建一个继承于Window_Base的新类
可能的写法就是:

  1. class Window_Draggable extends Window_Base {
  2.         update() {...}
  3. }
复制代码


但如果我要让全部继承于Window_Base的窗口都可以拖拽
我就需要拓展Window_Base的原型
可能的写法

  1. const update = Window_Base.prototype.update;
  2. Window_Base.prototype.update = function() {
  3.         update.call(this);
  4.         ...
  5. };       
复制代码


但是如果我们要提供给其他插件作者基于任意窗口的可拖拽拓展呢?

如果是新的类, 我们可以选择高阶类(HighOrderClass)来动态生成
高阶类传入一个类, 返回一个继承于该类的新类


  1. const useDraggableWindow = WindowClass => {
  2.         return class extends WindowClass {
  3.                 update() {...}
  4.         }
  5. }
复制代码


如果要改变现有类的行为我们就要用混合(Mixin)

  1. const makeWindowDragable = WindowClass => {
  2.         const update = WindowClass.prototype.update;
  3.         WindowClass.prototype.update = function() {
  4.                 update.call(this);
  5.                 ...
  6.         };
  7. }
复制代码


继承会创造新的类, 加深继承链的深度, 所以性能上略逊
但是继承也因为在原型链上留下了痕迹, 所以能追踪到每个属性的来源
并且可以和instanceOf这样的操作符配合使用

插播广告:自制基于高阶类型的插件




另附本次插件

  1. const makeWindowDragable = WindowClass => {
  2.   const update = WindowClass.prototype.update;
  3.   WindowClass.prototype.update = function() {
  4.     update.call(this);
  5.     this.updateDrag();
  6.   };
  7.   WindowClass.prototype.updateDrag = function() {
  8.     const isInside = this.rect.contains(TouchInput.x, TouchInput.y);
  9.     if (TouchInput.isTriggered() && isInside) {
  10.       this._dragX = this.canvasToLocalX(TouchInput.x);
  11.       this._dragY = this.canvasToLocalY(TouchInput.y);
  12.       this._dragging = true;
  13.       const windowList = SceneManager._scene._windowLayer.children;
  14.       $gameTemp.draggingWin = this;
  15.       windowList.sort(x => x === this);
  16.     } else if (
  17.       TouchInput.isPressed() &&
  18.       this._dragging &&
  19.       $gameTemp.draggingWin == this
  20.     ) {
  21.       this.x = TouchInput.x - this._dragX;
  22.       this.y = TouchInput.y - this._dragY;
  23.     } else if (TouchInput.isReleased()) {
  24.       this._dragging = false;
  25.     }
  26.   };
  27.   Object.defineProperty(WindowClass.prototype, "rect", {
  28.     get() {
  29.       if (
  30.         !this._rect ||
  31.         this._rect.x !== this.x ||
  32.         this._rect.y !== this.y ||
  33.         this._rect.width !== this.width ||
  34.         this._rect.height !== this.height
  35.       ) {
  36.         this._rect = new Rectangle(this.x, this.y, this.width, this.height);
  37.       }
  38.       return this._rect;
  39.     }
  40.   });
  41. };

  42. const useDraggableWindow = WindowClass => {
  43.   const hoc = class extends WindowClass {};
  44.   makeWindowDragable(hoc);
  45.   return hoc;
  46. };

  47. //解决重叠时边角覆盖问题
  48. const _maskWindow = WindowLayer.prototype._maskWindow;
  49. WindowLayer.prototype._maskWindow = function(window, shift) {
  50.   _maskWindow.call(this, window, shift);
  51.   const rect = this._windowRect;
  52.   rect.x += 4;
  53.   rect.y += 4;
  54.   rect.width -= 8;
  55.   rect.height -= 8;
  56. };

  57. WindowLayer.prototype._canvasClearWindowRect = function(
  58.   renderSession,
  59.   window
  60. ) {
  61.   var rx = this.x + window.x;
  62.   var ry =
  63.         this.y + window.y + (window.height / 2) * (1 - window._openness / 255);
  64.   var rw = window.width;
  65.   var rh = (window.height * window._openness) / 255;
  66.   renderSession.context.clearRect(rx + 4, ry + 4, rw - 8, rh - 8);
  67. };

复制代码


使用方法:


  1. makeWindowDragable(Window_Base);
  2. const Window_Draggable = useDraggableWindow(Window_Base);
复制代码

评分

参与人数 2+2 收起 理由
白嫩白嫩的 + 1 精品文章
康姆图帕帕 + 1 塞糖

查看全部评分

夏普的道具店

塞露提亚-道具屋的经营妙方同人作品
发布帖:点击这里

Lv3.寻梦者

梦石
0
星屑
1253
在线时间
222 小时
注册时间
2018-8-27
帖子
85
2
发表于 2019-10-21 19:05:58 | 只看该作者
给大佬端茶
《大理段素义游记》填坑中...
回复 支持 反对

使用道具 举报

Lv5.捕梦者 (管理员)

老黄鸡

梦石
0
星屑
39645
在线时间
7484 小时
注册时间
2009-7-6
帖子
13483

开拓者贵宾

3
发表于 2019-10-21 19:52:36 | 只看该作者
兼容性警告,目测这样的语法部署到移动端之后无法正常工作
尽量还是不使用es5,6的语法吧

点评

可以考虑一下Babel降级吧, 不过我觉得以后H5还是类似wx那种内嵌浏览器靠谱一些...  发表于 2019-10-21 21:21
RGDirect - DirectX驱动的RGSS,点我了解.
RM全系列成套系统定制请联系QQ1213237796
不接受对其他插件维护的委托
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-4-25 07:01

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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