查看: 48565|回复: 60

[搬运汉化] 【教學】MV教學系列:【一】手把手教你如何在MV裡自製視窗

[复制链接]

百合控

梦石
0
星屑
6548
在线时间
1275 小时
注册时间
2013-8-21
回帖
3522

开拓者

发表于 2015-12-5 10:16:22 | 显示全部楼层 |阅读模式

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

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

×
本帖最后由 余烬之中 于 2015-12-5 10:55 编辑


【教學】MV教學系列:【一】手把手教你如何在MV裡自製視窗
写在前面的一些说明



此套教程来源自台湾巴哈姆特的【James Eviat Ko / J.E.K.】,亦称【食夢】,其账号是【jamessl2】,原帖请戳我进入。

已经联系作者并取得了在66RPG的转载授权,但是我们未允许也没有权利允许二次转载,希望转载请联系原作者。

原始教程由@鑫晴 发现,并代为联系授权,特此感谢。

00.jpg

评分

参与人数 12星屑 +173 赞 +6 收起 理由
447924513 + 1
sekees + 1 塞糖
cheese401 + 1 塞糖
xzhxzh527527 + 1 我很赞同
ssrwkx + 1 塞糖
if216 + 1 写窗口是很好的硬上javascript的方法.
zaiy2863 + 7 猴子居然评分了
冷峻逸 + 30 好棒的教程(浴巾大美女么么哒).
king + 36 塞糖
c248611 + 13 塞糖

查看全部评分

萌新瑟瑟发抖
看到我请叫我去干活

百合控

梦石
0
星屑
6548
在线时间
1275 小时
注册时间
2013-8-21
回帖
3522

开拓者

 楼主| 发表于 2015-12-5 10:31:19 | 显示全部楼层
本帖最后由 余烬之中 于 2015-12-7 22:47 编辑


此楼放帖子内容

原文以繁中写成,搬运时考虑到简中与繁中也有部分文法不同,故没有强行转换为简中。看不习惯繁中的同学请点击网页左上角【繁體中文】,待其变成【简体中文】后再次点击,即可强行将文本内容转换为简中。

由于原始地址和6R的代码高亮方式有差异,对部分内容进行了调整以免除困扰,为了阅读的流畅性,并没有特别注明调整的部分。如有任何冲突,以原始地址内容为准。







展开以浏览内容
嗯,
身為巴哈萬年潛水艇的我,趁MV發燒的時候先來發個基礎教學文吧。
這次將教給各位如何用js程式碼
從零開始建構屬於自己的視窗。

需要程度:無,完全不會js也可

●教學開始●

【假設你什麼都不知道:一切的開始】

嗯,這就是我寫這篇教學文的前提,我們先假設你是個MV新手,新到不能再新的那種。
你可能還搞不清楚 js / javascript 是什麼東西,或者不知道怎麼建立一個新的 js 檔......
沒關係,我們一個一個來,請你一步一步看清楚。


【你要先搞懂的最最基礎的東西】

沒錯,即使本教學文並不著重於讓你從根本上學會 js,
但最基本的資訊一樣要搞清楚。

第一、javascript 是一種在網頁上使用的程式語言,
MV捨棄了使用多年的Ruby而採取它,就是為了方便在HTML5標準上於瀏覽器發布。
細節不需知道太多,反正我們使用的程式語言叫做 javascript,js 是它的縮寫。

第二、javascript 身為程式語言,它就是一種「特別的」文字檔,
你大可以用Dreamweaver這種高階軟體去處理它,
也可以隨便開個記事本把附檔名從 *.txt 改成 *.js 就可以了。
差別只在於高階軟體在撰寫程式碼時比較方便,
可能提供各種提示、自動完成和高亮功能。
作為教學,本文使用強化版的記事本 Notepad++,完全免費,有需要請自行前往下載。

第三、MV所有可選擇的插件都建立於該專案的 js\plugins 之下,
我們等等也要在這個地方新增 js 檔,先去找到這個位置吧。

01.JPG
(圖1:這就是我們要建立 js 檔的地方,找到了嗎?)


【進入正題:開始建立檔案】

我們這次不打算沿用任何的插件,
所以打開 Notepad++,建立一個新的檔案"new 1",並選擇另存新檔為"FirstWindow.js"。
当然,并不必要是Notepad++,任何合适的文本编辑器均可。

02.JPG
(圖2:js 檔儲存位置圖)

03.JPG
(圖3:如果順利,這個時候你在遊戲裡就能看到可以安插進這個插件了)

不過當然有插沒插一點差都沒有,因為裡面空空如也。
等我們把東西寫完之後再插不遲。


【這結構看起來複雜實際上簡單無比只是長了點因為廢話很多】

一個視窗之所以能夠顯現出來,在RPG MAKER裡最主要依靠兩大架構:
Window:負責視窗本身的參數和內容
Scene:負責視窗各種運作和互動
講得簡單一點,如果視窗就是扇窗戶,
那麼Window記錄了這扇窗戶的長寬、窗框的材質、玻璃的材料等等,
而Scene記錄了窗戶怎麼左右拉、怎麼鎖住又怎麼打開,
夠明白了吧。

因此,我們準備在FirstWindow.js裡開始寫一些東西了。
首先,我們先建立Window_Testing和Scene_Testing兩個函數,如下所示:
[pre lang="javascript"]function Window_Testing() {
   
}
function Scene_Testing() {
   
}[/pre]
你一定覺得很奇怪,為什麼要這樣寫?
其實你愛怎麼寫對 js 來說都沒差,
這樣寫只是告訴你這兩個函數一個跟Window有關,一個跟Scene有關。
先這樣寫放著它空沒關係,等等再把東西寫進去。


【初始化】

RPG MAKER內建了initialize方法,作為既定初始化用,
每一個 Window 類和 Scene 類函數都需要它。
正常情況下,你不用知道initialize怎麼建起來的,
你只要知道你的兩個函數都需要這個方法,
而且寫法蠻固定的:沒必要亂寫給自己找麻煩吧?

這個範例中,我們要借用 Window_Selectable 的方法給 Window_Testing,
借用 Scene_MenuBase 的方法給 Scene_Testing,
由於 Window_Selectable 視窗有x座標、y座標、寬、高四個屬性,
函數當然要記得丟進去,一個都不能少,一個都不能多(正常來說):
因此,原程式碼就變成了
[pre lang="javascript"]function Window_Testing() {
   
}
Window_Testing.prototype.initialize = function(x, y, width, height) {
    Window_Selectable.prototype.initialize.call(this, x, y, width, height);
}

function Scene_Testing() {
   
}
Scene_Testing.prototype.initialize = function() {
    Scene_MenuBase.prototype.initialize.call(this);
};[/pre]
然後,直接在函數中引用它們,各自加上同樣的一句話:this.initialize.apply(this, arguments);
[pre lang="javascript"]function Window_Testing() {
    this.initialize.apply(this, arguments);
}
Window_Testing.prototype.initialize = function(x, y, width, height) {
    Window_Selectable.prototype.initialize.call(this, x, y, width, height);
}

function Scene_Testing() {
    this.initialize.apply(this, arguments);
}
Scene_Testing.prototype.initialize = function() {
    Scene_MenuBase.prototype.initialize.call(this);
};[/pre]
為什麼要加這兩句話?
我想...這個問題很簡單,不加這兩句我是要呼叫空函數嗎?
這兩句話基本上功能一致,講得簡單一點,
當我們呼叫這函數時,它就會去找它的initialize方法,
然後開始借用預設的初始化程式碼,嗯,超棒的。


【要素的補齊】

寫到這裡,快結束了。你臉綠了嗎?還好吧。
Scene_Testing 除了initialize之外,還需要兩個方法:create和update。
create用於建立新的 Window_Testing 視窗,
update用於對玩家作出動作時的更新回應,例如我們接下來要寫的關閉視窗這個動作。
這次東西有點多,我們分成兩個部分解釋:

[pre lang="javascript"]function Window_Testing() {
    this.initialize.apply(this, arguments);
}
Window_Testing.prototype.initialize = function(x, y, width, height) {
    Window_Selectable.prototype.initialize.call(this, x, y, width, height);
}

function Scene_Testing() {
    this.initialize.apply(this, arguments);
}
Scene_Testing.prototype.initialize = function() {
    Scene_MenuBase.prototype.initialize.call(this);
};
// ************** 第一个部分
Scene_Testing.prototype.create = function() {
Scene_MenuBase.prototype.create.call(this);
    this._commandWindow = new Window_Testing(0, 0, 400, 200);
    this.addWindow(this._commandWindow);
};
// ************** 第二个部分
Scene_Testing.prototype.update = function() {
    if (Input.isTriggered('escape') || Input.isTriggered('cancel')) {
        this._commandWindow.hide();
        SceneManager.goto(Scene_Map);
    }
};[/pre]
第一个部分:
一開始跟上一段一樣,從借用的地方去呼叫方法,只不過多了兩句話。
第一句話是建立一個新的Window_Testing物件,
第二句話則是將這個物件用addWindow方法顯示出來。

第二个部分:
這裡則是一個 if 判斷式,
系統會偵測我們的行為,如果在 Scene_Testing 這個場景按下了
鍵盤上的 ESC 或者平板上的取消鍵時,
就把我們剛剛顯示的 Window_Testing 物件,也就是我們叫出來的視窗給隱藏起來,
並且回到地圖場景上。
如果沒有這句話,那麼你只能叫出視窗,
叫出來之後就一點反應也不會有了,也不能退出XD

至於為什麼是地圖場景呢?其實你要回到哪個場景都可以,
只是因為這個範例等等要做的事情與地圖場景有關,所以先如此設定。


【你有的我也要有】

接著,剩最後一個重點。請在以下位置加入這两句話:
Window_Testing.prototype = Object.create(Window_Selectable.prototype); 和 Scene_Testing.prototype = Object.create(Scene_MenuBase.prototype);
[pre lang="javascript"]function Window_Testing() {
    this.initialize.apply(this, arguments);
}
Window_Testing.prototype = Object.create(Window_Selectable.prototype);
Window_Testing.prototype.initialize = function(x, y, width, height) {
    Window_Selectable.prototype.initialize.call(this, x, y, width, height);
}

function Scene_Testing() {
    this.initialize.apply(this, arguments);
}
Scene_Testing.prototype = Object.create(Scene_MenuBase.prototype);
Scene_Testing.prototype.initialize = function() {
    Scene_MenuBase.prototype.initialize.call(this);
};
Scene_Testing.prototype.create = function() {
Scene_MenuBase.prototype.create.call(this);
    this._commandWindow = new Window_Testing(0, 0, 400, 200);
this.addWindow(this._commandWindow);
}
Scene_Testing.prototype.update = function() {
    if (Input.isTriggered('escape') || Input.isTriggered('cancel')) {
        this._commandWindow.hide();
        SceneManager.goto(Scene_Map);
    }
};[/pre]
這兩句話的意思嗎?舉Window_Testing為例,
就是Window_Testing表示:只要是Window_Selectable有的方法,我都要有啦www
這個可不是上面我們說過的「借用」而已,
你要把它想成繼承嘛也行,但看在我眼裡比較像是複製www
如果你沒加這兩句,基本上會出現找不到方法(undefined)的錯誤喔。


【辛辛苦苦熬到現在終於可以測試了】

好了,到這裡整個基本程式碼大功告成了。
它基本上是最簡單的自製視窗結構,所有你之後想自製的視窗全都可以以它為藍圖去增修。
當然,細節上之後我們再說。總之趕快來做個測試吧。

04.JPG
(圖4:你家程式碼應該長成類似這個模樣)

05.JPG
(圖5:請記得打開你引用的插件)

怎麼作測試呢?
很簡單。
在你的地圖上任意一格新增一個事件,然後在內容處選擇腳本,寫入

SceneManager.goto(Scene_Testing)

就可以了。
06.JPG
(圖6:人物隨便選都行,反正它是個事件)

接下來不用我說了吧?
進入遊戲,用你的角色去碰這個事件!


【一片空白的視窗......】

我知道,你想跟我說,這視窗什麼都沒有啊!
是啊,因為它就真的什麼都沒有。
所有的東西都要你自己加,不管是全新的還是調用data內的,都需要額外的程式碼。
例如:

[pre lang="javascript"]Window_Testing.prototype.initialize = function(x, y, width, height) {
    Window_Selectable.prototype.initialize.call(this, x, y, width, height);
    var textW = 360;
    var textH = 0;
    this.drawText("這是你的第一個自製視窗", 0, 0, textW, 'left');
    textH += this.lineHeight();
    this.drawText("靠左", 0, textH, textW, 'left');
    textH += this.lineHeight();
    this.drawText("置中", 0, textH, textW, 'center');
    textH += this.lineHeight();
    this.drawText("靠右", 0, textH, textW, 'right');
}[/pre]

你把中间這段程式碼加進去,存檔之後再開一次試試。

如何,你看到字了嗎?


【教練,可是這樣不好看......】

哦?
在這一篇教學的尾聲,你還想要什麼?
通常來說,我們不會把程式碼完全從頭到尾寫在initialize裡,
這樣既難看又雜亂,程式碼一多很容易被自己弄混。
所以,我們就這樣辦吧!

[pre lang="javascript"]Window_Testing.prototype.initialize = function(x, y, width, height) {
    Window_Selectable.prototype.initialize.call(this, x, y, width, height);
    this.drawSomeText();
}

Window_Testing.prototype.drawSomeText = function() {
    var textW = 360;
    var textH = 0;
    this.drawText("這是你的第一個自製視窗", 0, 0, textW, 'left');
    textH += this.lineHeight();
    this.drawText("靠左", 0, textH, textW, 'left');
    textH += this.lineHeight();
    this.drawText("置中", 0, textH, textW, 'center');
    textH += this.lineHeight();
    this.drawText("靠右", 0, textH, textW, 'right');
}[/pre]

如何?
有沒有開始覺得自己像是個專業的程式設計師了?


【教學ENDING】

理所當然,要成為專業你我可能都還有很長的路要走,
但是到這裡為止,第一篇教學真的要結束了,很長很長對吧?
其實占版面的都是程式碼和聊天般的廢話,只是想讓你別一開始就接觸太專業的東西。
剩下的你可以自己參考插件作者的寫法琢磨,
我也是不停在學習著,只是把自己先領略的部分丟出來給想要的人。

也許你覺得做了這麼多,也不過就是寫出一個陽春的視窗罷了,值得嗎?
其實在過程中,你得到的東西比想像中更多。

那麼,下次見了。

P.S. 如果老骨頭還記得精華區RGSS2有類似的文章,沒錯,本篇的確啟發自埃特。

点评

我最喜欢这种手把手的教学方式……谢谢搬运,也感谢原作者  发表于 2015-12-6 19:35

评分

参与人数 4星屑 +90 收起 理由
火烧兔子 + 30 开始学习!
判约之轮 + 30 作为启蒙教学……不能更赞
c248611 + 24 塞糖
高须小龙 + 6 精品文章

查看全部评分

萌新瑟瑟发抖
看到我请叫我去干活
回复 2 0

使用道具 举报

梦石
6
星屑
3071
在线时间
1825 小时
注册时间
2014-8-20
回帖
233

开拓者剧作品鉴家

发表于 2015-12-7 22:24:56 | 显示全部楼层
本帖最后由 真_真空 于 2015-12-7 22:44 编辑

挑个虫,很小的错误啦,最后一段代码里
Window_Testing.prototype.initialize = function(x, y, width, height) {
    Window_Selectable.prototype.initialize.call(this, x, y, width, height);
    this.drawSometext();
}
这句话 this.drawSometext();改成 this.drawSomeText();
我说怎么直接复制会出错= =

很不错的教程

评分

参与人数 1梦石 +1 收起 理由
余烬之中 + 1 认可答案

查看全部评分

回复 1 0

使用道具 举报

梦石
0
星屑
50
在线时间
68 小时
注册时间
2014-7-8
回帖
28
发表于 2016-1-9 16:34:35 | 显示全部楼层
【教學】MV教學系列:【一】手把手教你如何在MV裡自製視窗
看起来是一个系列的样子,所以说【二】【三】【四】【五】有吗?

点评

就目前而言 只有【一】  发表于 2016-1-11 23:33
看上去的确是一个系列的样子 然而具体什么时候出来还得看原作者 毕竟我只是搬运  发表于 2016-1-11 23:32
回复

使用道具 举报

【欧皇】

梦石
3
星屑
2055
在线时间
1004 小时
注册时间
2013-8-19
回帖
3040

开拓者

发表于 2016-1-9 16:38:21 | 显示全部楼层
为什么不用简繁转换器

点评

..问的好 我竟然无言以对  发表于 2016-1-9 16:55
QQ:2223942063
Q群:365819625
贪吃方1.4
回复

使用道具 举报

梦石
0
星屑
50
在线时间
44 小时
注册时间
2015-12-27
回帖
42
发表于 2016-1-9 17:26:18 | 显示全部楼层
这个太好了!
雪中送炭的教程,谢谢楼主和原作者
回复

使用道具 举报

梦石
0
星屑
50
在线时间
44 小时
注册时间
2015-12-27
回帖
42
发表于 2016-1-11 22:06:31 | 显示全部楼层
QQ图片20160111220013.png

评分

参与人数 1星屑 +66 收起 理由
余烬之中 + 66 塞糖

查看全部评分

回复

使用道具 举报

梦石
0
星屑
556
在线时间
224 小时
注册时间
2011-8-15
回帖
77
发表于 2016-1-13 11:42:40 | 显示全部楼层
那要调用角色信息数据要怎么写呢,比如我要调取角色信息数据放在界面至中的位置上

点评

你的头像有我二张图片,1是裸,2是有衣..  发表于 2016-8-1 16:57
回复

使用道具 举报

梦石
0
星屑
399
在线时间
115 小时
注册时间
2016-1-17
回帖
77
发表于 2016-1-17 13:16:50 | 显示全部楼层
这个要改成右键退出视窗,怎么改
回复

使用道具 举报

梦石
0
星屑
1788
在线时间
1313 小时
注册时间
2012-8-4
回帖
724
发表于 2016-1-18 16:38:33 | 显示全部楼层
我是不是写错了,发生错误
  1. function Window_Testing() {
  2.     this.initialize.apply(this, arguments);
  3. }
  4. Window_Testing.prototype = Object.create(Window_Selectable.prototype);
  5. Window_Testing.prototype.initialize = function(x, y, width, height) {
  6.     Window_Selectable.prototype.initialize.call(this, x, y, width, height);
  7.     this.drawSomeText();
  8. }

  9. Window_Testing.prototype.drawSomeText = function() {
  10.     var textW = 360;
  11.     var textH = 0;
  12.     this.drawText("這是你的第一個自製視窗", 0, 0, textW, 'left');
  13.     textH += this.lineHeight();
  14.     this.drawText("靠左", 0, textH, textW, 'left');
  15.     textH += this.lineHeight();
  16.     this.drawText("置中", 0, textH, textW, 'center');
  17.     textH += this.lineHeight();
  18.     this.drawText("靠右", 0, textH, textW, 'right');
  19. }


  20. function Scene_Testing() {
  21.     this.initialize.apply(this, arguments);
  22. }
  23. Scene_Testing.prototype = Object.create(Scene_MenuBase.prototype);
  24. Scene_Testing.prototype.initialize = function() {
  25.     Scene_MenuBase.prototype.initialize.call(this);
  26. };
  27. Scene_Testing.prototype.create = function() {
  28. Scene_MenuBase.prototype.create.call(this);
  29.     this._commandWindow = new Window_Testing(0, 0, 400, 200);
  30. this.addWindow(this._commandWindow);
  31. }
  32. Scene_Testing.prototype.update = function() {
  33.     if (Input.isTriggered('escape') || Input.isTriggered('cancel')) {
  34.         this._commandWindow.hide();
  35.         SceneManager.goto(Scene_Map);
  36.     }
  37. };
复制代码

点评

日照加一  发表于 2017-4-9 12:58
谢谢,那时候还不懂格式。  发表于 2016-1-20 23:16
这个代码不是JS格式的吧,你保存的时候检查一下是不是按JS的格式保存,然后后缀是不是.js  发表于 2016-1-20 22:12
回复

使用道具 举报

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

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部