Project1

标题: MV的代码解析【持续更新】 [打印本页]

作者: LBQ    时间: 2015-10-1 14:32
标题: MV的代码解析【持续更新】
本帖最后由 LBQ 于 2015-10-3 10:27 编辑

10月3日:
有了TextManager你说我们要不要i18n
binary json可以试试
10月2日:
没有预想的那么恶心233
COFFEESCRIPT 代码复制
  1. class Scene_Crafting extends Scene_MenuBase
  2.   initialize: ->
  3.     super()
  4.   create: ->
  5.     super()
  6.     this.createBackground()
  7.     this.createWindowLayer()
  8.     this.createGoldWindow()
  9.   start: ->
  10.     super()
  11.   createGoldWindow: ->
  12.     @goldWindow = new Window_Gold(0,0)
  13.     this.addWindow(@goldWindow)


我没法用Plugin更改plugin manager
我选择死亡

pixi.js用的v2感觉很不爽,应该移植到v3的


其实重点是pixi.js啊
想想看这些可能性啊





Google closure compiler的advance编译别想了,mv代码没有预先准备最终产物没法运行
UglifyJs之类的还是可以用
Desktop版本会用Nw.js作为Js后端,可以直接开node
binary json估计是可以用


原网页:http://preorder.rpgmakerweb.com/rpg-maker-mv/



毕竟有游戏了所以解析一下吧:

1:Yanfly下手好快,现在就有脚本了是怎么回事,黑幕吗
2:渲染用的Pixi.js,我很开心

继续读代码中,游戏不知道为何玩不了只能读代码了

3:没有用npm或者commonjs之类的,直接采用的html引用脚本,这个到时候得修一下
4:主题代码被minify或者obfuscate了,不好读

5:core.js:https://www.refheap.com/110141
6:managers.js:https://www.refheap.com/110142

很明显数据库用的json
好评

7:objects.js:https://www.refheap.com/110143,太长了,refheap不知道为何不行。
objects.7z (36.89 KB, 下载次数: 60)
8:scenes.js:https://www.refheap.com/110144
9:sprites.js : https://www.refheap.com/110145
Window.prototype.initialize是什么鬼

看得出来代码是中规中矩的ruby式js....?

本来Js比Ruby更加Functional一些的,但是为了保持惯例继续用Ruby的法则...?
10:window.js:https://www.refheap.com/110146

感觉有点像用Js写Ruby代码233
还是猴子补丁,一堆猴子补丁

JAVASCRIPT 代码复制
  1. Window_BattleLog.prototype.callNextMethod = function() {
  2.     if (this._methods.length > 0) {
  3.         var method = this._methods.shift();
  4.         if (method.name && this[method.name]) {
  5.             this[method.name].apply(this, method.params)
  6.         } else {
  7.             throw new Error('Method not found: ' + method.name)
  8.         }
  9.     }
  10. };


这段代码真心诡异

全部代码打包:
mv-core-src.7z (103.88 KB, 下载次数: 78)

Scene与Scene之间切换都没有什么鬼

数据库json文件打包: data.zip (19.89 KB, 下载次数: 86)

这行走图和脸图让我蛋疼的不行

Sprite的代码:
JAVASCRIPT 代码复制
  1. Sprite.prototype._renderWebGL = function(renderSession) {
  2.     if (this.visible && this.alpha > 0) {
  3.         var spriteBatch = renderSession.spriteBatch;
  4.         if (this._filters) {
  5.             spriteBatch.flush();
  6.             renderSession.filterManager.pushFilter(this._filterBlock);
  7.             if (this.opaque) {
  8.                 renderSession.gl.clearColor(0, 0, 0, 1);
  9.                 renderSession.gl.clear(renderSession.gl.COLOR_BUFFER_BIT)
  10.             }
  11.         }
  12.         if (this._mask) {
  13.             spriteBatch.stop();
  14.             renderSession.maskManager.pushMask(this.mask, renderSession);
  15.             spriteBatch.start()
  16.         }
  17.         spriteBatch.render(this);
  18.         for (var i = 0, j = this.children.length; i < j; i++) {
  19.             this.children[i]._renderWebGL(renderSession)
  20.         }
  21.         if (this._mask) {
  22.             spriteBatch.stop();
  23.             renderSession.maskManager.popMask(this._mask, renderSession);
  24.             spriteBatch.start()
  25.         }
  26.         if (this._filters) {
  27.             spriteBatch.stop();
  28.             renderSession.filterManager.popFilter();
  29.             spriteBatch.start()
  30.         }
  31.     }
  32. };


Pixi.js的同样的方法
JAVASCRIPT 代码复制
  1. PIXI.Sprite.prototype._renderWebGL = function(renderSession)
  2. {
  3.     // if the sprite is not visible or the alpha is 0 then no need to render this element
  4.     if(!this.visible || this.alpha <= 0)return;
  5.  
  6.     var i,j;
  7.  
  8.     // do a quick check to see if this element has a mask or a filter.
  9.     if(this._mask || this._filters)
  10.     {
  11.         var spriteBatch =  renderSession.spriteBatch;
  12.  
  13.         // push filter first as we need to ensure the stencil buffer is correct for any masking
  14.         if(this._filters)
  15.         {
  16.             spriteBatch.flush();
  17.             renderSession.filterManager.pushFilter(this._filterBlock);
  18.         }
  19.  
  20.         if(this._mask)
  21.         {
  22.             spriteBatch.stop();
  23.             renderSession.maskManager.pushMask(this.mask, renderSession);
  24.             spriteBatch.start();
  25.         }
  26.  
  27.         // add this sprite to the batch
  28.         spriteBatch.render(this);
  29.  
  30.         // now loop through the children and make sure they get rendered
  31.         for(i=0,j=this.children.length; i<j; i++)
  32.         {
  33.             this.children[i]._renderWebGL(renderSession);
  34.         }
  35.  
  36.         // time to stop the sprite batch as either a mask element or a filter draw will happen next
  37.         spriteBatch.stop();
  38.  
  39.         if(this._mask)renderSession.maskManager.popMask(this._mask, renderSession);
  40.         if(this._filters)renderSession.filterManager.popFilter();
  41.  
  42.         spriteBatch.start();
  43.     }
  44.     else
  45.     {
  46.         renderSession.spriteBatch.render(this);
  47.  
  48.         // simple render children!
  49.         for(i=0,j=this.children.length; i<j; i++)
  50.         {
  51.             this.children[i]._renderWebGL(renderSession);
  52.         }
  53.  
  54.     }
  55. };


MV这个代码真的可以去死了,


现在我才意识到Scene是Stage的一种,EB你去死吧

Pixi用的v2,应该无大碍,先这样OTL
作者: 喵呜喵5    时间: 2015-10-1 15:13
本帖最后由 喵呜喵5 于 2015-10-1 17:21 编辑
  1. $gameParty.gainGold(65535)
复制代码
无比炸裂的加钱代码果然有效……防作弊迫在眉睫

不止Yanfly,Yami、Galenmerth、Neonblack等国外比较有名的脚本都有出现,并且它们写的脚本将作为首波DLC公开

======================

RMVA有的RMMV都有,不如说RMMV的脚本简直就是RMVA脚本的JS化,看着非常眼熟

相比RMVA功能上有变动的地方:

使用 TouchInput.isTriggered() / TouchInput.isPressed()  响应点击事件



Manager
Cache 改名为 ImageManager,然而实际上做的还是Cache的事,图片素材上只增加了SvActor和SvEnemy这两个用在SideView模式的素材文件夹
Vocab 改名为 TextManager,各种改名Manager等,Audio也分出来作为Manager了……
插件脚本作为新节点贴在body上
  1. PluginManager.loadScript = function(name) {
  2.     var url = this._path + name;
  3.     var script = document.createElement('script');
  4.     script.type = 'text/javascript';
  5.     script.src = url;
  6.     script.async = false;
  7.     script.onerror = this.onError.bind(this);
  8.     script._url = url;
  9.     document.body.appendChild(script)
  10. };
复制代码


Scene

初始界面为Scene_Boot,负责加载并检查资源是否全部加载完毕
SceneManager.run(Scene_Boot);

SceneManager.call 由 push 代替,return由pop代替,goto仍然不变
  1. SceneManager.pop()
  2. SceneManager.goto(Scene_Gameover)
  3. SceneManager.push(Scene_Save)
复制代码
存读档界面布局调整


……………………囧
  1. this._rangeWindow.setHandler('cancel', this.popScene.bind(this));
复制代码


Game

某种程度的中文支持?还是说要出官方中文版了?
JAVASCRIPT 代码复制
  1. Game_System.prototype.isChinese = function() {
  2.     return $dataSystem.locale.match(/^zh/)
  3. };


Game_Character支持寻路了,算法为A*,没有使用二叉堆等进行优化,因此为了提高效率默认设置了寻路的限制,突破限制时停止寻路,但是可以去除
JAVASCRIPT 代码复制
  1. Game_Character.prototype.findDirectionTo = function(goalX, goalY) {
  2.     var searchLimit = this.searchLimit();
  3.     var mapWidth = $gameMap.width();
  4.     var nodeList = [];
  5.     var openList = [];
  6.     var closedList = [];
  7.     var start = {};
  8.     var best = start;
  9.     if (this.x === goalX && this.y === goalY) {
  10.         return 0
  11.     }
  12.     start.parent = null;
  13.     start.x = this.x;
  14.     start.y = this.y;
  15.     start.g = 0;
  16.     start.f = $gameMap.distance(start.x, start.y, goalX, goalY);
  17.     nodeList.push(start);
  18.     openList.push(start.y * mapWidth + start.x);
  19.     while (nodeList.length > 0) {
  20.         var bestIndex = 0;
  21.         for (var i = 0; i < nodeList.length; i++) {
  22.             if (nodeList[i].f < nodeList[bestIndex].f) {
  23.                 bestIndex = i
  24.             }
  25.         }
  26.         var current = nodeList[bestIndex];
  27.         var x1 = current.x;
  28.         var y1 = current.y;
  29.         var pos1 = y1 * mapWidth + x1;
  30.         var g1 = current.g;
  31.         nodeList.splice(bestIndex, 1);
  32.         openList.splice(openList.indexOf(pos1), 1);
  33.         closedList.push(pos1);
  34.         if (current.x === goalX && current.y === goalY) {
  35.             best = current;
  36.             goaled = true;
  37.             break
  38.         }
  39.         if (g1 >= searchLimit) {
  40.             continue
  41.         }
  42.         for (var j = 0; j < 4; j++) {
  43.             var direction = 2 + j * 2;
  44.             var x2 = $gameMap.roundXWithDirection(x1, direction);
  45.             var y2 = $gameMap.roundYWithDirection(y1, direction);
  46.             var pos2 = y2 * mapWidth + x2;
  47.             if (closedList.contains(pos2)) {
  48.                 continue
  49.             }
  50.             if (!this.canPass(x1, y1, direction)) {
  51.                 continue
  52.             }
  53.             var g2 = g1 + 1;
  54.             var index2 = openList.indexOf(pos2);
  55.             if (index2 < 0 || g2 < nodeList[index2].g) {
  56.                 var neighbor;
  57.                 if (index2 >= 0) {
  58.                     neighbor = nodeList[index2]
  59.                 } else {
  60.                     neighbor = {};
  61.                     nodeList.push(neighbor);
  62.                     openList.push(pos2)
  63.                 }
  64.                 neighbor.parent = current;
  65.                 neighbor.x = x2;
  66.                 neighbor.y = y2;
  67.                 neighbor.g = g2;
  68.                 neighbor.f = g2 + $gameMap.distance(x2, y2, goalX, goalY);
  69.                 if (!best || neighbor.f - neighbor.g < best.f - best.g) {
  70.                     best = neighbor
  71.                 }
  72.             }
  73.         }
  74.     }
  75.     var node = best;
  76.     while (node.parent && node.parent !== start) {
  77.         node = node.parent
  78.     }
  79.     var deltaX1 = $gameMap.deltaX(node.x, start.x);
  80.     var deltaY1 = $gameMap.deltaY(node.y, start.y);
  81.     if (deltaY1 > 0) {
  82.         return 2
  83.     } else if (deltaX1 < 0) {
  84.         return 4
  85.     } else if (deltaX1 > 0) {
  86.         return 6
  87.     } else if (deltaY1 < 0) {
  88.         return 8
  89.     }
  90.     var deltaX2 = this.deltaXFrom(goalX);
  91.     var deltaY2 = this.deltaYFrom(goalY);
  92.     if (Math.abs(deltaX2) > Math.abs(deltaY2)) {
  93.         return deltaX2 > 0 ? 4 : 6
  94.     } else if (deltaY2 !== 0) {
  95.         return deltaY2 > 0 ? 8 : 2
  96.     }
  97.     return 0
  98. };
  99. Game_Character.prototype.searchLimit = function() {
  100.     return 12
  101. };
视频格式可以使用webm和mp4了(需设备支持)
JAVASCRIPT 代码复制
  1. Game_Interpreter.prototype.videoFileExt = function() {
  2.     if (Graphics.canPlayVideoType('video/webm') && !Utils.isMobileDevice()) {
  3.         return '.webm'
  4.     } else {
  5.         return '.mp4'
  6.     }
  7. };


可以通过事件指令直接获取玩家的战斗胜利和逃跑次数了

用来扩展事件指令功能增加任意个新指令的?
JAVASCRIPT 代码复制
  1. Game_Interpreter.prototype.command356 = function() {
  2.     var args = this._params[0].split(" ");
  3.     var command = args.shift();
  4.     this.pluginCommand(command, args);
  5.     return true
  6. };
  7. Game_Interpreter.prototype.pluginCommand = function(command, args) {};


……

读累了,之后再去看还没读的Window代码吧
作者: chd114    时间: 2015-10-1 15:15
喵呜喵5 发表于 2015-9-30 22:13

$gameParty?那角色用$gameActor?
作者: taroxd    时间: 2015-10-1 15:23
不知道为什么,看着代码就完全没有入手的欲望了
作者: 喵呜喵5    时间: 2015-10-1 15:46
本帖最后由 喵呜喵5 于 2015-10-1 15:47 编辑

下载了全代码打包看了半天忽然意识到你漏了Game啊

====================

哦不对,原来Game你打包放到另一个附件里了
作者: taroxd    时间: 2015-10-1 20:59
喵呜喵5 发表于 2015-10-1 15:13
无比炸裂的加钱代码果然有效……防作弊迫在眉睫

不止Yanfly,Yami、Galenmerth、Neonblack等国外比较有名 ...

关于作弊啥的,你可以直接把 cookie 拿出来,base64 解了随便改
作者: wbsy8241    时间: 2015-10-2 03:58
数据库没任何加密或压缩吗?
txt打开就能随便改啊
作者: taroxd    时间: 2015-10-2 08:03
wbsy8241 发表于 2015-10-2 03:58
数据库没任何加密或压缩吗?
txt打开就能随便改啊

数据库在服务器端,你怎么改

当然你可以把包抓下来黑了
作者: 英顺的马甲    时间: 2015-10-2 10:13
真心觉得不想用MV,虽然跨平台这一点很不错,但是比起ruby,js有很多不方便的地方
作者: 精灵使者    时间: 2015-10-2 10:25
我目前ACE就足够使用了。
MV对我来说还很早。
作者: 刺夜之枪    时间: 2015-10-2 10:34
这猎奇的语法,虽然学过java但是感觉还是亚历山大。

不过在此想请教些问题, 是不是MV用js编程后效率会大大提高?
作者: orochi2k    时间: 2015-10-2 15:22

准备开MV开荒团。
大家填好人物卡,注意职业平衡,记得带好骰子(大雾)
作者: wbsy8241    时间: 2015-10-2 19:49
taroxd 发表于 2015-10-2 08:03
数据库在服务器端,你怎么改

当然你可以把包抓下来黑了

请问下什么是服务端啊

这游戏  数据库也就是以前的 Data 文件夹 是放在服务器上的?

也就是玩这个软件做的单机游戏必须联网?
作者: WildDagger    时间: 2015-10-9 23:37
現在公開的這個範例遊戲在本地端執行的話會有問題,因為一些瀏覽器會鎖權限不讓HTML讀取本地端檔案
(我方才測試的結果只有Firefox成功,Edge/IE/Chrome都會卡死或者是跳出「沒有讀取本地端檔案權限」的錯誤)

不過畢竟是HTML5,搭配Cordova/Phonegap功能應該會多很多,像是Geolocation/Compass/Sensor等功能應該都是可以加入的
日本那邊甚至有人已經做出課金道具系統了
(另外我是有點好奇RMMV到底是怎麼存檔的,是透過HTML5新增的Local Storage功能還是怎樣呢)

至於單機遊戲會是怎樣的格式,我個人猜應該是和Cordova/Phonegap原理一樣用EXE內包一個Browser進去,Android/iOS應該就是直接用Cordova那一套,
但因為有Cordova框架,所以就沒有直接執行HTML時會有的本地端存讀權限被鎖的問題。
作者: lukezai    时间: 2015-10-10 10:20
代码什么的完全不懂,听说MV换了JS+HTML5,正好就不用学rgss了,刚刚下了JS入门教学啃起来
作者: summer92    时间: 2015-10-13 14:06
一看到this就知道是java了,俺还是喜欢原来的ruby
作者: WildDagger    时间: 2015-10-14 14:31
看了一下代碼解析後,發現MV的儲存系統是分成兩種,一個是使用Local Storage,另一個是使用node.js的fs模組,用變數判斷是不是在客戶端來決定使用哪個
所以我猜EXE應該是用node.js的EXE框架包起來,其他的平台就使用Cordova/Phonegap框架,使用localStorage儲存(所以這次的存檔應該也是使用JSON格式)
作者: 墨凌羽    时间: 2015-10-15 01:24
求更啊 在不更就要被上边的持续更新打脸了233
之前没好好看,今天变读代码边试着写了些东西。场景window什么的
那个window还是一如既往的恶心啊
既然MV是js版的ruby那么看着Bitmap之类的是不是可以反推出RGSS里的那些玩意233
还有我比较好奇接下来是JGSSQAQ好诡异的名字
话说大体代码有扫一遍不过还是有一大堆完全不知道
脑袋炸咧
一想起three.js就激动啊 虽然直接做3D什么的不现实,不过要是封装一些比较好玩的组件什么的也很不错啊
还有粒子系统 骨骼动画什么的也有希望啊(国产的白鹭貌似有个开放的骨骼动画编辑器和库 貌似也能拿来用的样子
不过写js代码简直恶心到死啊啊啊啊啊啊
一大堆简直什么鬼的玩意
class A < B
  def initialize
     super
     .....
硬是被拖成:
function A() {
    this.initialize.apply(this, arguments)
}
A.prototype = Object.create(B.prototype);
A.prototype.constructor =A;
A.prototype.initialize = function() {
    B.prototype.initialize.call(this);

感觉以后打代码都能打废ORZ

最后,求大触带 求大腿抱
作者: DeathKing    时间: 2015-10-19 22:55
好奇是不是拿 Opal 直接编译出来的。




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