吉里吉里MainWindow.tjs渐进中……

作者 Odaimoko/影风秦 日期 2017-05-14
吉里吉里MainWindow.tjs渐进中……

为什么写这个

学习记录+指点迷津。

内容

由于主要是学习记录,只有我看到哪里,读过之后,才会记录在这里。

如果你看到了,想问我某个函数做什么,我很荣幸。联系方式吗–>>最下面有我的邮箱。btw欢迎到百度吉里吉里吧做客哦哦。

补充学习资料:

我做的一些范例:

我做的游戏:

开始吧

使用的是KAGeXpress3。KCDDP有下载。打开krkr,按Ctrl+F12,吉里吉里[Kirikiri] 2 执行内核 version 2.30.2.420-zhcn ( TJS version 2.4.27 )。

tagHandlers

有一段这样

1
2
3
4
5
6
7
8
9
10
11
var mainConductor; // メインのコンダクタ
var extraConductor; // 予備のコンダクタ
var conductor; // 現在のコンダクタ
...
// タグハンドラ/コンダクタを作成
tagHandlers = getHandlers();
mainConductor = new Conductor(this, tagHandlers);
add(mainConductor);
conductor = mainConductor;
extraConductor = new Conductor(this, tagHandlers);
add(extraConductor);

我们一般不都是写的ks文件吗,ks文件里面的东西怎么解读的呢?对ks文件的解读就用的就是一个叫KAGParser的类,这个类是封在krkr.exe里面的,KAG自己在Conductor.tjs里面继承了它,加强了功能。继承树长这样

1
2
3
KAGParser
|---BaseConductor
|---Conductor

这里mainConductor和extraConductor都是Conductor的实例。大家可能看到过这样的错误,就是这儿来的。

1
messagelayer.tjs(1561)[(function) addButton] <-- mainwindow.tjs(4463)[(function expression) (anonymous)] <-- conductor.tjs(427)[(function) onTag] <-- conductor.tjs(95)[(function) timerCallback]

也就是说,conductor一家子,就是用来处理ks文件的对象。

为什么可以用kag.tagHandlers.image(%[])之类的命令

最上面的那儿有一句tagHandlers = getHandlers();,那么就来看看getHandlers长啥样吧。

getHandlers函数在MainWindow里面只用了tagHandlers = getHandlers();一次,也只有用这一次的必要。getHandlers函数开头是

1
2
3
function getHandlers()
{
return %[ // 辞書配列オブジェクト

也就是说,这个函数的唯一目的是返回一个tjs字典,接下来看这个字典对象的元素是啥:

1
2
3
4
5
6
7
8
9
10
11
12
每个字典元素的格式如下:
函数的名字 : function(elm)
{
// 函数内容
} incontextof this,
不用「函数的名字 : 」,而是「"函数的名字" => 」也没问题。
incontextof this 是为了能让函数在本类(MainWindow类)的对象的
上下文中正确的运行而必要的。
incontextof this は、関数が正しく このクラスの
オブジェクトのコンテキスト上で動くようにするために必要。

先别管什么上下文之类的是啥,总之这就是一个ks里的的tag如何导致图像啊文字啊等等的显示、隐藏、渐变操作的实质地点。

例子最棒了!举个简单易懂的

1
2
3
4
5
6
7
8
9
10
11
12
13
nowait : function(elm)
{
// 一時的にノーウェイトで実行
enterNoWait();
return 0;
} incontextof this,
endnowait : function(elm)
{
// nowait の解除
leaveNoWait();
return 0;
} incontextof this,
函数体 函数名
nowait enterNoWait(); return 0;
endnowait leaveNoWait(); return 0;

你在ks里写一个@nowait,所做的相当于@eval exp="enterNoWait()"

自定义tag也可以在这里实现,当然也可以写macro,但是macro里面不让iscript,不能执行大片的tjs式子呢(其实可以把一大片写成一个函数,然后macro里面eval这个函数;或者在某个label(*开头的那玩意)下面写iscript,写完之后endscript和return,在macro里call这个label等等)。还是来个例子。

1
2
3
4
5
6
hh : function(elm)
{
dm(elm.t); // dm是Debug.message函数的缩写,这个函数的作用是在控制台中打印后面的信息
return 0; // 不return 个什么东西的话会报错(默认返回void)。
} incontextof this,

在first.ks里写 @hh t="ddsssawd2"。运行krkr,按Shift+F4打开控制台:

1
2
15:41:43 first.ks : @hh t="ddsssawd2"
15:41:43 ddsssawd2

锵锵!因为tag之后的storage=jj.png一类的会被解析成字典形式,所以传入函数的elm对象就是一个带有这些参数的字典。于是你就可以用

kag.tagHandlers.image(%[storage:"config",layer:"0",page:"fore",visible:true]);

来执行kag语句了。

为了方便管理自定义命令,建议新开一个ks或者tjs文件,在里面这样写

1
2
3
4
5
kag.tagHandlers.hh = function(elm)
{
dm(elm.t); // dm是Debug.message函数的缩写,这个函数的作用是在控制台中打印后面的信息
return 0; // 不return 个什么东西的话会报错(默认返回void)。
} incontextof kag;

注意这里是类的外部,所以必须要incontextof 具体的实例,我们具体的MainWindow实例当然就是kag啦。

存读相关

插件的存读

存储全局变量时

1
2
3
4
5
6
7
8
9
10
function saveSystemVariables()
{
// システム変数の保存
if(!isMain) return;
// プラグインを呼ぶ
forEachEventHook('onSaveSystemVariables',
function(handler, f) { handler(); } incontextof this);

这里说明,在保存系统变量之前,会先调用所有插件的onSaveSystemVariables函数。插件的详细内容在Plugin.tjs里面,很简单。

存储f,也就是存档变量时

internalStoreFlags函数里。

1
2
3
4
5
6
7
8
9
function internalStoreFlags(f){
...
f.prevEmptyLine = prevEmptyLine;
// storeHook
forEachEventHook('onStore',
function(handler, f) { handler(f.flags, f.options); } incontextof this,
%[flags:f, options:void]);
}

和存储全局变量时不同,插件在存储存档变量的时候是在最后调用。

另外提示一句,就这一个函数来看,如果你想用存档变量保存些啥东西,就别和这里面的名字冲突了。比如

1
2
3
4
5
6
7
8
9
10
11
12
...
f.lastSaveDataName = lastSaveDataName;
f.quaking = quaking;
f.quakePhase = quakePhase;
f.historyWriteEnabled = historyWriteEnabled;
f.historyEnabled = historyEnabled;
f.currentNum = currentNum;
f.currentPage = currentPage;
f.currentWithBack = currentWithBack;
f.chUserMode = chUserMode;
f.chSpeed = chSpeed;
...

不过这些都是系统(kag)相关的名字,想冲突也只有你自己想写系统的时候才会吧。