Project1
标题: MV的代码解析【持续更新】 [打印本页]
作者: LBQ 时间: 2015-10-1 14:32
标题: MV的代码解析【持续更新】
本帖最后由 LBQ 于 2015-10-3 10:27 编辑
10月3日:
有了TextManager你说我们要不要i18n
binary json可以试试
10月2日:
没有预想的那么恶心233
class Scene_Crafting extends Scene_MenuBase
initialize: ->
super()
create: ->
super()
this.createBackground()
this.createWindowLayer()
this.createGoldWindow()
start: ->
super()
createGoldWindow: ->
@goldWindow = new Window_Gold(0,0)
this.addWindow(@goldWindow)
class Scene_Crafting extends Scene_MenuBase
initialize: ->
super()
create: ->
super()
this.createBackground()
this.createWindowLayer()
this.createGoldWindow()
start: ->
super()
createGoldWindow: ->
@goldWindow = new Window_Gold(0,0)
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
还是猴子补丁,一堆猴子补丁
Window_BattleLog.prototype.callNextMethod = function() {
if (this._methods.length > 0) {
var method = this._methods.shift();
if (method.name && this[method.name]) {
this[method.name].apply(this, method.params)
} else {
throw new Error('Method not found: ' + method.name)
}
}
};
Window_BattleLog.prototype.callNextMethod = function() {
if (this._methods.length > 0) {
var method = this._methods.shift();
if (method.name && this[method.name]) {
this[method.name].apply(this, method.params)
} else {
throw new Error('Method not found: ' + method.name)
}
}
};
这段代码真心诡异
全部代码打包:
mv-core-src.7z
(103.88 KB, 下载次数: 78)
Scene与Scene之间切换都没有什么鬼
数据库json文件打包:
data.zip
(19.89 KB, 下载次数: 86)
这行走图和脸图让我蛋疼的不行
Sprite的代码:
Sprite.prototype._renderWebGL = function(renderSession) {
if (this.visible && this.alpha > 0) {
var spriteBatch = renderSession.spriteBatch;
if (this._filters) {
spriteBatch.flush();
renderSession.filterManager.pushFilter(this._filterBlock);
if (this.opaque) {
renderSession.gl.clearColor(0, 0, 0, 1);
renderSession.gl.clear(renderSession.gl.COLOR_BUFFER_BIT)
}
}
if (this._mask) {
spriteBatch.stop();
renderSession.maskManager.pushMask(this.mask, renderSession);
spriteBatch.start()
}
spriteBatch.render(this);
for (var i = 0, j = this.children.length; i < j; i++) {
this.children[i]._renderWebGL(renderSession)
}
if (this._mask) {
spriteBatch.stop();
renderSession.maskManager.popMask(this._mask, renderSession);
spriteBatch.start()
}
if (this._filters) {
spriteBatch.stop();
renderSession.filterManager.popFilter();
spriteBatch.start()
}
}
};
Sprite.prototype._renderWebGL = function(renderSession) {
if (this.visible && this.alpha > 0) {
var spriteBatch = renderSession.spriteBatch;
if (this._filters) {
spriteBatch.flush();
renderSession.filterManager.pushFilter(this._filterBlock);
if (this.opaque) {
renderSession.gl.clearColor(0, 0, 0, 1);
renderSession.gl.clear(renderSession.gl.COLOR_BUFFER_BIT)
}
}
if (this._mask) {
spriteBatch.stop();
renderSession.maskManager.pushMask(this.mask, renderSession);
spriteBatch.start()
}
spriteBatch.render(this);
for (var i = 0, j = this.children.length; i < j; i++) {
this.children[i]._renderWebGL(renderSession)
}
if (this._mask) {
spriteBatch.stop();
renderSession.maskManager.popMask(this._mask, renderSession);
spriteBatch.start()
}
if (this._filters) {
spriteBatch.stop();
renderSession.filterManager.popFilter();
spriteBatch.start()
}
}
};
Pixi.js的同样的方法
PIXI.Sprite.prototype._renderWebGL = function(renderSession)
{
// if the sprite is not visible or the alpha is 0 then no need to render this element
if(!this.visible || this.alpha <= 0)return;
var i,j;
// do a quick check to see if this element has a mask or a filter.
if(this._mask || this._filters)
{
var spriteBatch = renderSession.spriteBatch;
// push filter first as we need to ensure the stencil buffer is correct for any masking
if(this._filters)
{
spriteBatch.flush();
renderSession.filterManager.pushFilter(this._filterBlock);
}
if(this._mask)
{
spriteBatch.stop();
renderSession.maskManager.pushMask(this.mask, renderSession);
spriteBatch.start();
}
// add this sprite to the batch
spriteBatch.render(this);
// now loop through the children and make sure they get rendered
for(i=0,j=this.children.length; i<j; i++)
{
this.children[i]._renderWebGL(renderSession);
}
// time to stop the sprite batch as either a mask element or a filter draw will happen next
spriteBatch.stop();
if(this._mask)renderSession.maskManager.popMask(this._mask, renderSession);
if(this._filters)renderSession.filterManager.popFilter();
spriteBatch.start();
}
else
{
renderSession.spriteBatch.render(this);
// simple render children!
for(i=0,j=this.children.length; i<j; i++)
{
this.children[i]._renderWebGL(renderSession);
}
}
};
PIXI.Sprite.prototype._renderWebGL = function(renderSession)
{
// if the sprite is not visible or the alpha is 0 then no need to render this element
if(!this.visible || this.alpha <= 0)return;
var i,j;
// do a quick check to see if this element has a mask or a filter.
if(this._mask || this._filters)
{
var spriteBatch = renderSession.spriteBatch;
// push filter first as we need to ensure the stencil buffer is correct for any masking
if(this._filters)
{
spriteBatch.flush();
renderSession.filterManager.pushFilter(this._filterBlock);
}
if(this._mask)
{
spriteBatch.stop();
renderSession.maskManager.pushMask(this.mask, renderSession);
spriteBatch.start();
}
// add this sprite to the batch
spriteBatch.render(this);
// now loop through the children and make sure they get rendered
for(i=0,j=this.children.length; i<j; i++)
{
this.children[i]._renderWebGL(renderSession);
}
// time to stop the sprite batch as either a mask element or a filter draw will happen next
spriteBatch.stop();
if(this._mask)renderSession.maskManager.popMask(this._mask, renderSession);
if(this._filters)renderSession.filterManager.popFilter();
spriteBatch.start();
}
else
{
renderSession.spriteBatch.render(this);
// simple render children!
for(i=0,j=this.children.length; i<j; i++)
{
this.children[i]._renderWebGL(renderSession);
}
}
};
MV这个代码真的可以去死了,
现在我才意识到Scene是Stage的一种,EB你去死吧
Pixi用的v2,应该无大碍,先这样OTL
作者: 喵呜喵5 时间: 2015-10-1 15:13
本帖最后由 喵呜喵5 于 2015-10-1 17:21 编辑
- $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上- PluginManager.loadScript = function(name) {
- var url = this._path + name;
- var script = document.createElement('script');
- script.type = 'text/javascript';
- script.src = url;
- script.async = false;
- script.onerror = this.onError.bind(this);
- script._url = url;
- document.body.appendChild(script)
- };
复制代码
Scene
初始界面为Scene_Boot,负责加载并检查资源是否全部加载完毕
SceneManager.run(Scene_Boot);
SceneManager.call 由 push 代替,return由pop代替,goto仍然不变- SceneManager.pop()
- SceneManager.goto(Scene_Gameover)
- SceneManager.push(Scene_Save)
复制代码 存读档界面布局调整
……………………囧- this._rangeWindow.setHandler('cancel', this.popScene.bind(this));
复制代码
Game
某种程度的中文支持?还是说要出官方中文版了?
Game_System.prototype.isChinese = function() {
return $dataSystem.locale.match(/^zh/)
};
Game_System.prototype.isChinese = function() {
return $dataSystem.locale.match(/^zh/)
};
Game_Character支持寻路了,算法为A*,没有使用二叉堆等进行优化,因此为了提高效率默认设置了寻路的限制,突破限制时停止寻路,但是可以去除Game_Character.prototype.findDirectionTo = function(goalX, goalY) {
var searchLimit = this.searchLimit();
var mapWidth = $gameMap.width();
var nodeList = [];
var openList = [];
var closedList = [];
var start = {};
var best = start;
if (this.x === goalX && this.y === goalY) {
return 0
}
start.parent = null;
start.x = this.x;
start.y = this.y;
start.g = 0;
start.f = $gameMap.distance(start.x, start.y, goalX, goalY);
nodeList.push(start);
openList.push(start.y * mapWidth + start.x);
while (nodeList.length > 0) {
var bestIndex = 0;
for (var i = 0; i < nodeList.length; i++) {
if (nodeList[i].f < nodeList[bestIndex].f) {
bestIndex = i
}
}
var current = nodeList[bestIndex];
var x1 = current.x;
var y1 = current.y;
var pos1 = y1 * mapWidth + x1;
var g1 = current.g;
nodeList.splice(bestIndex, 1);
openList.splice(openList.indexOf(pos1), 1);
closedList.push(pos1);
if (current.x === goalX && current.y === goalY) {
best = current;
goaled = true;
break
}
if (g1 >= searchLimit) {
continue
}
for (var j = 0; j < 4; j++) {
var direction = 2 + j * 2;
var x2 = $gameMap.roundXWithDirection(x1, direction);
var y2 = $gameMap.roundYWithDirection(y1, direction);
var pos2 = y2 * mapWidth + x2;
if (closedList.contains(pos2)) {
continue
}
if (!this.canPass(x1, y1, direction)) {
continue
}
var g2 = g1 + 1;
var index2 = openList.indexOf(pos2);
if (index2 < 0 || g2 < nodeList[index2].g) {
var neighbor;
if (index2 >= 0) {
neighbor = nodeList[index2]
} else {
neighbor = {};
nodeList.push(neighbor);
openList.push(pos2)
}
neighbor.parent = current;
neighbor.x = x2;
neighbor.y = y2;
neighbor.g = g2;
neighbor.f = g2 + $gameMap.distance(x2, y2, goalX, goalY);
if (!best || neighbor.f - neighbor.g < best.f - best.g) {
best = neighbor
}
}
}
}
var node = best;
while (node.parent && node.parent !== start) {
node = node.parent
}
var deltaX1 = $gameMap.deltaX(node.x, start.x);
var deltaY1 = $gameMap.deltaY(node.y, start.y);
if (deltaY1 > 0) {
return 2
} else if (deltaX1 < 0) {
return 4
} else if (deltaX1 > 0) {
return 6
} else if (deltaY1 < 0) {
return 8
}
var deltaX2 = this.deltaXFrom(goalX);
var deltaY2 = this.deltaYFrom(goalY);
if (Math.abs(deltaX2) > Math.abs(deltaY2)) {
return deltaX2 > 0 ? 4 : 6
} else if (deltaY2 !== 0) {
return deltaY2 > 0 ? 8 : 2
}
return 0
};
Game_Character.prototype.searchLimit = function() {
return 12
};
Game_Character.prototype.findDirectionTo = function(goalX, goalY) {
var searchLimit = this.searchLimit();
var mapWidth = $gameMap.width();
var nodeList = [];
var openList = [];
var closedList = [];
var start = {};
var best = start;
if (this.x === goalX && this.y === goalY) {
return 0
}
start.parent = null;
start.x = this.x;
start.y = this.y;
start.g = 0;
start.f = $gameMap.distance(start.x, start.y, goalX, goalY);
nodeList.push(start);
openList.push(start.y * mapWidth + start.x);
while (nodeList.length > 0) {
var bestIndex = 0;
for (var i = 0; i < nodeList.length; i++) {
if (nodeList[i].f < nodeList[bestIndex].f) {
bestIndex = i
}
}
var current = nodeList[bestIndex];
var x1 = current.x;
var y1 = current.y;
var pos1 = y1 * mapWidth + x1;
var g1 = current.g;
nodeList.splice(bestIndex, 1);
openList.splice(openList.indexOf(pos1), 1);
closedList.push(pos1);
if (current.x === goalX && current.y === goalY) {
best = current;
goaled = true;
break
}
if (g1 >= searchLimit) {
continue
}
for (var j = 0; j < 4; j++) {
var direction = 2 + j * 2;
var x2 = $gameMap.roundXWithDirection(x1, direction);
var y2 = $gameMap.roundYWithDirection(y1, direction);
var pos2 = y2 * mapWidth + x2;
if (closedList.contains(pos2)) {
continue
}
if (!this.canPass(x1, y1, direction)) {
continue
}
var g2 = g1 + 1;
var index2 = openList.indexOf(pos2);
if (index2 < 0 || g2 < nodeList[index2].g) {
var neighbor;
if (index2 >= 0) {
neighbor = nodeList[index2]
} else {
neighbor = {};
nodeList.push(neighbor);
openList.push(pos2)
}
neighbor.parent = current;
neighbor.x = x2;
neighbor.y = y2;
neighbor.g = g2;
neighbor.f = g2 + $gameMap.distance(x2, y2, goalX, goalY);
if (!best || neighbor.f - neighbor.g < best.f - best.g) {
best = neighbor
}
}
}
}
var node = best;
while (node.parent && node.parent !== start) {
node = node.parent
}
var deltaX1 = $gameMap.deltaX(node.x, start.x);
var deltaY1 = $gameMap.deltaY(node.y, start.y);
if (deltaY1 > 0) {
return 2
} else if (deltaX1 < 0) {
return 4
} else if (deltaX1 > 0) {
return 6
} else if (deltaY1 < 0) {
return 8
}
var deltaX2 = this.deltaXFrom(goalX);
var deltaY2 = this.deltaYFrom(goalY);
if (Math.abs(deltaX2) > Math.abs(deltaY2)) {
return deltaX2 > 0 ? 4 : 6
} else if (deltaY2 !== 0) {
return deltaY2 > 0 ? 8 : 2
}
return 0
};
Game_Character.prototype.searchLimit = function() {
return 12
};
视频格式可以使用webm和mp4了(需设备支持)
Game_Interpreter.prototype.videoFileExt = function() {
if (Graphics.canPlayVideoType('video/webm') && !Utils.isMobileDevice()) {
return '.webm'
} else {
return '.mp4'
}
};
Game_Interpreter.prototype.videoFileExt = function() {
if (Graphics.canPlayVideoType('video/webm') && !Utils.isMobileDevice()) {
return '.webm'
} else {
return '.mp4'
}
};
可以通过事件指令直接获取玩家的战斗胜利和逃跑次数了
用来扩展事件指令功能增加任意个新指令的?
Game_Interpreter.prototype.command356 = function() {
var args = this._params[0].split(" ");
var command = args.shift();
this.pluginCommand(command, args);
return true
};
Game_Interpreter.prototype.pluginCommand = function(command, args) {};
Game_Interpreter.prototype.command356 = function() {
var args = this._params[0].split(" ");
var command = args.shift();
this.pluginCommand(command, args);
return true
};
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 |