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

Project1

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

[交流讨论] RPG Maker MV 的源码研究 其十

[复制链接]

Lv3.寻梦者

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

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

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

x
本帖最后由 沉滞的剑 于 2019-8-20 22:32 编辑

希望论坛能支持直接写Markdown啊
==============================
在Window_Selectable之后,
RM还再次拓展了Window_Command类, 引入了Command的概念
将item封装成名称, 对应handler, 可用状态等属性的新对象
下面我们将按照惯例通过各个生命周期来了解它的原理
  1. Window_Command.prototype.initialize = function (x, y) {
  2.     this.clearCommandList();
  3.     this.makeCommandList();
  4.     var width = this.windowWidth();
  5.     var height = this.windowHeight();
  6.     Window_Selectable.prototype.initialize.call(this, x, y, width, height);
  7.     this.refresh();
  8.     this.select(0);
  9.     this.activate();
  10. };
复制代码

Window_Command具有_list属性
代表其维护的Command列表

  1. Window_Command.prototype.clearCommandList = function () {
  2.   this._list = [];
  3. };

  4. Window_Command.prototype.makeCommandList = function () {
  5. };

  6. Window_Command.prototype.addCommand = function (name, symbol, enabled, ext) {
  7.   if (enabled === undefined) {
  8.       enabled = true;
  9.   }
  10.   if (ext === undefined) {
  11.       ext = null;
  12.   }
  13.   this._list.push({ name: name, symbol: symbol, enabled: enabled, ext: ext });
  14. };
复制代码

基础的对command列表的各种操作
makeCommandList是个虚函数, 需要各个子类对其进行实现
在addCommand里可以看出来Command总共有4个属性
name, symbol, enabled 和 ext
name对应的是绘制名
symbol对应的是选择后对应的handler
enabled控制是否可选
ext应该是携带的 拓展信息

对于单个command, 也有相应的获取其属性的方法

  1. Window_Command.prototype.commandName = function (index) {
  2.   return this._list[index].name;
  3. };

  4. Window_Command.prototype.commandSymbol = function (index) {
  5.   return this._list[index].symbol;
  6. };

  7. Window_Command.prototype.isCommandEnabled = function (index) {
  8.   return this._list[index].enabled;
  9. };
复制代码

对于当前Command获取属性的方法

  1. Window_Command.prototype.currentData = function () {
  2.   return this.index() >= 0 ? this._list[this.index()] : null;
  3. };

  4. Window_Command.prototype.isCurrentItemEnabled = function () {
  5.   return this.currentData() ? this.currentData().enabled : false;
  6. };

  7. Window_Command.prototype.currentSymbol = function () {
  8.   return this.currentData() ? this.currentData().symbol : null;
  9. };

  10. Window_Command.prototype.currentExt = function () {
  11.   return this.currentData() ? this.currentData().ext : null;
  12. };
复制代码
还有一些检索特定属性, 找到command的方法

  1. Window_Command.prototype.findSymbol = function (symbol) {
  2.   for (var i = 0; i < this._list.length; i++) {
  3.       if (this._list[i].symbol === symbol) {
  4.           return i;
  5.       }
  6.   }
  7.   return -1;
  8. };

  9. Window_Command.prototype.selectSymbol = function (symbol) {
  10.   var index = this.findSymbol(symbol);
  11.   if (index >= 0) {
  12.       this.select(index);
  13.   } else {
  14.       this.select(0);
  15.   }
  16. };

  17. Window_Command.prototype.findExt = function (ext) {
  18.   for (var i = 0; i < this._list.length; i++) {
  19.       if (this._list[i].ext === ext) {
  20.           return i;
  21.       }
  22.   }
  23.   return -1;
  24. };
复制代码

讲讲绘制, 首先在Window_Selectable里有item的矩形区域的定义

  1. Window_Selectable.prototype.itemRect = function (index) {
  2.   var rect = new Rectangle();
  3.   var maxCols = this.maxCols();
  4.   rect.width = this.itemWidth();
  5.   rect.height = this.itemHeight();
  6.   rect.x = index % maxCols * (rect.width + this.spacing()) - this._scrollX;
  7.   rect.y = Math.floor(index / maxCols) * rect.height - this._scrollY;
  8.   return rect;
  9. };
复制代码



每个item按照横向铺满换行的方式排列
对于每一个itemRect, 还有一个由textPadding控制的textRect


  1. Window_Selectable.prototype.itemRectForText = function (index) {
  2.   var rect = this.itemRect(index);
  3.   rect.x += this.textPadding();
  4.   rect.width -= this.textPadding() * 2;
  5.   return rect;
  6. };
复制代码



在Window_Command中, 我们就是在这个textRect中绘制name

  1. Window_Command.prototype.drawItem = function (index) {
  2.   var rect = this.itemRectForText(index);
  3.   var align = this.itemTextAlign();
  4.   this.resetTextColor();
  5.   this.changePaintOpacity(this.isCommandEnabled(index));
  6.   this.drawText(this.commandName(index), rect.x, rect.y, rect.width, align);
  7. };
复制代码

其中resetTextColor:
  1. Window_Base.prototype.resetTextColor = function () {
  2.   this.changeTextColor(this.normalColor());
  3. };

  4. Window_Base.prototype.changeTextColor = function (color) {
  5.   this.contents.textColor = color;
  6. };

  7. Window_Base.prototype.normalColor = function () {
  8.   return this.textColor(0);
  9. };
复制代码

嗯, 还记得Window_Base里讲的那个复古的取色写法么...

  1. Window_Base.prototype.changePaintOpacity = function (enabled) {
  2.   this.contents.paintOpacity = enabled ? 255 : this.translucentOpacity();
  3. };
  4. Window_Base.prototype.translucentOpacity = function () {
  5.   return 160;
  6. };
复制代码

这个就是根据当前command是否是enabled来确定字体的透明度了

update其实没有多少变化不过Window_Command覆写了callOkHandler
先来看一下这个方法在Window_Selectable中的调用栈

  1. Window_Selectable.prototype.update = function () {
  2.   // ...略
  3.   this.processHandling();
  4.   // ...略
  5. };

  6. Window_Selectable.prototype.processHandling = function () {
  7.   // 略....
  8.   if (this.isOkEnabled() && this.isOkTriggered()) {
  9.       this.processOk();
  10.   }
  11.   // 略....
  12. };

  13. Window_Selectable.prototype.processOk = function () {
  14.   if (this.isCurrentItemEnabled()) {
  15.       // ... 略
  16.       this.callOkHandler();
  17.       // ... 略
  18.   }
  19. };
复制代码

Window_Command修改了callOkHandler的方法:

  1. Window_Command.prototype.callOkHandler = function () {
  2.   var symbol = this.currentSymbol(); // 获取当前command的symbol
  3.   if (this.isHandled(symbol)) { // 如果存在该symbol的handler
  4.       this.callHandler(symbol); // 则呼叫这个handler
  5.   } else if (this.isHandled('ok')) { // 否则判断是否有ok
  6.       Window_Selectable.prototype.callOkHandler.call(this); // 呼叫ok
  7.   } else {
  8.       this.activate(); // 否则就重新选择一下
  9.   }
  10. };
复制代码

这里贴个activate供大家参考一下

  1. Window_Selectable.prototype.activate = function () {
  2.   Window_Base.prototype.activate.call(this);
  3.   this.reselect();
  4. };
  5. Window_Selectable.prototype.reselect = function () {
  6.   this.select(this._index);
  7. };
复制代码
最后一个refresh重绘也没有太多内容

  1. Window_Command.prototype.refresh = function () {
  2.   this.clearCommandList();
  3.   this.makeCommandList();
  4.   this.createContents();
  5.   Window_Selectable.prototype.refresh.call(this);
  6. };
复制代码

需要注意的是每次重绘Command list都会被清空重新添加
内容也要重绘, 绘制部分参见上面的drawItem
这里把相关的父类函数贴一下

  1. Window_Selectable.prototype.refresh = function () {
  2.   if (this.contents) {
  3.       this.contents.clear();
  4.       this.drawAllItems();
  5.   }
  6. };

  7. Window_Selectable.prototype.drawAllItems = function () {
  8.   var topIndex = this.topIndex();
  9.   for (var i = 0; i < this.maxPageItems(); i++) {
  10.       var index = topIndex + i;
  11.       if (index < this.maxItems()) {
  12.           this.drawItem(index);
  13.       }
  14.   }
  15. };
复制代码

收工~收工~
下次应该有新的练手内容
明天见...大概吧



评分

参与人数 2+2 收起 理由
玄羽 + 1 塞糖
康姆图帕帕 + 1 塞糖

查看全部评分

夏普的道具店

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

Lv3.寻梦者

梦石
0
星屑
1075
在线时间
133 小时
注册时间
2019-5-1
帖子
59
2
发表于 2019-8-21 13:09:48 | 只看该作者
太真实了 技术贴没人看系列。 顶一发
回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
0
星屑
14219
在线时间
718 小时
注册时间
2011-7-16
帖子
1428

开拓者

3
发表于 2019-8-21 20:30:06 | 只看该作者
楼上你说的也很真实呀
RMMV网络插件,开源免费,内含服务器端,无需强制登录,云数据,弹幕,云存档,排名,兑换码,版本检测,可自由上架下架删除。q群399090587
免打包运行MV游戏,云游戏,安卓App雷神游戏厅,在线玩游戏,上传下载游戏
开源游戏:重装机兵之重装归来【RMMV制作】全球首款按照美剧分季分集的方式发布的游戏
体素画 -- MV画3D像素图的画板
RMMV显示3D模型和场景的插件
RMMV显示spine骨骼动画的插件
RMMV秘密通道插件
突破敌群数量上限8个的插件
在rmmv中显示gif动态图片的插件
一款可以在mv游戏界面的任意位置显示任意文字的插件
RMMV Toast 插件 带物品得失提示,可以设置开启关闭 兼容yep itemcore
制作一个改名卡道具插件、调整标题页面菜单的插件、在标题页面之前显示大段文字的插件、标题页面显示版本号的插件
物品得失自动提示自动上色自动换行插件
我的Q群 663889472
另外,我的插件、范例、游戏都在这里
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2024-4-26 01:29

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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