赞 | 65 |
VIP | 231 |
好人卡 | 2 |
积分 | 19 |
经验 | 35171 |
最后登录 | 2024-9-15 |
在线时间 | 1554 小时 |
Lv3.寻梦者
- 梦石
- 0
- 星屑
- 1912
- 在线时间
- 1554 小时
- 注册时间
- 2013-4-13
- 帖子
- 917
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
本帖最后由 沉滞的剑 于 2019-10-21 00:12 编辑
当在JS拓展功能的时候会面临两个选择:
1. 修改现有的类(Mixin)
本质上是将原有类的原型上增加新的属性
亦或
2. 从现有的类的基础上派生出信的类(继承)
本质上是将新的类的原型指向旧类的原型
这两种方法是RM中插件拓展的基础, 必须要掌握
我现在要做一个拥有Window_Base的功能且能拖拽的窗口
最常见的做法就是新建一个继承于Window_Base的新类
可能的写法就是:
- class Window_Draggable extends Window_Base {
- update() {...}
- }
复制代码
但如果我要让全部继承于Window_Base的窗口都可以拖拽
我就需要拓展Window_Base的原型
可能的写法
- const update = Window_Base.prototype.update;
- Window_Base.prototype.update = function() {
- update.call(this);
- ...
- };
复制代码
但是如果我们要提供给其他插件作者基于任意窗口的可拖拽拓展呢?
如果是新的类, 我们可以选择高阶类(HighOrderClass)来动态生成
高阶类传入一个类, 返回一个继承于该类的新类
- const useDraggableWindow = WindowClass => {
- return class extends WindowClass {
- update() {...}
- }
- }
复制代码
如果要改变现有类的行为我们就要用混合(Mixin)
- const makeWindowDragable = WindowClass => {
- const update = WindowClass.prototype.update;
- WindowClass.prototype.update = function() {
- update.call(this);
- ...
- };
- }
复制代码
继承会创造新的类, 加深继承链的深度, 所以性能上略逊
但是继承也因为在原型链上留下了痕迹, 所以能追踪到每个属性的来源
并且可以和instanceOf这样的操作符配合使用
插播广告:自制基于高阶类型的插件
另附本次插件
- const makeWindowDragable = WindowClass => {
- const update = WindowClass.prototype.update;
- WindowClass.prototype.update = function() {
- update.call(this);
- this.updateDrag();
- };
- WindowClass.prototype.updateDrag = function() {
- const isInside = this.rect.contains(TouchInput.x, TouchInput.y);
- if (TouchInput.isTriggered() && isInside) {
- this._dragX = this.canvasToLocalX(TouchInput.x);
- this._dragY = this.canvasToLocalY(TouchInput.y);
- this._dragging = true;
- const windowList = SceneManager._scene._windowLayer.children;
- $gameTemp.draggingWin = this;
- windowList.sort(x => x === this);
- } else if (
- TouchInput.isPressed() &&
- this._dragging &&
- $gameTemp.draggingWin == this
- ) {
- this.x = TouchInput.x - this._dragX;
- this.y = TouchInput.y - this._dragY;
- } else if (TouchInput.isReleased()) {
- this._dragging = false;
- }
- };
- Object.defineProperty(WindowClass.prototype, "rect", {
- get() {
- if (
- !this._rect ||
- this._rect.x !== this.x ||
- this._rect.y !== this.y ||
- this._rect.width !== this.width ||
- this._rect.height !== this.height
- ) {
- this._rect = new Rectangle(this.x, this.y, this.width, this.height);
- }
- return this._rect;
- }
- });
- };
- const useDraggableWindow = WindowClass => {
- const hoc = class extends WindowClass {};
- makeWindowDragable(hoc);
- return hoc;
- };
- //解决重叠时边角覆盖问题
- const _maskWindow = WindowLayer.prototype._maskWindow;
- WindowLayer.prototype._maskWindow = function(window, shift) {
- _maskWindow.call(this, window, shift);
- const rect = this._windowRect;
- rect.x += 4;
- rect.y += 4;
- rect.width -= 8;
- rect.height -= 8;
- };
- WindowLayer.prototype._canvasClearWindowRect = function(
- renderSession,
- window
- ) {
- var rx = this.x + window.x;
- var ry =
- this.y + window.y + (window.height / 2) * (1 - window._openness / 255);
- var rw = window.width;
- var rh = (window.height * window._openness) / 255;
- renderSession.context.clearRect(rx + 4, ry + 4, rw - 8, rh - 8);
- };
复制代码
使用方法:
- makeWindowDragable(Window_Base);
- const Window_Draggable = useDraggableWindow(Window_Base);
复制代码 |
评分
-
查看全部评分
|