krkr进阶教程4

 

继承了kaglayer的AnimationLayer

该教程为水螅制作,未经允许,请勿转载

打开AnimationLayer.tjs,前边大段注释是asd动画的解释,有兴趣的人可以详细看看

再往后是一个叫做AnimationConductor的class定义,这个暂且按下,等到用到了再说,直接看class AnimationLayer

前边是var了几个参数,接下来是构造函数function AnimationLayer(win, par),里边除了super外还有几个赋值,重要的是这个

Anim_segments[0] = new AnimationConductor(this); // デフォルトのコンダクタ
   Anim_segments[0].number = 0;

建立了一个AnimationConductor的实体。这个AnimationConductor就是用来实现asd动画的东西,具体怎么用呢,我们回到mainwindow……查找image :的话就可以看到这么一段

image : function(elm)
{
   // 画像読み込み
   updateBeforeCh = 1;
   var start = System.getTickCount();
   getLayerFromElm(elm).loadImages(elm);
   dm(elm.storage + " 的读取花费了 " + (System.getTickCount() - start) + "ms。");
   return 0;
} incontextof this,

那些dm用的东西不用管,具体载入图片时实现的那一句就是getLayerFromElm(elm).loadImages(elm);,getLayerFromElm是mainwindow里的一个函数用来取得elm里传入的图层名的,这句话的意思就是用loadImages来载入图片。

顺便一提,比如在kag里写了[image layer=1 storage=aa page=fore left=12 top=14],就是调用了mainwindow的image函数,那些参数就全部都放在了这个传入字典elm里,比如elm.top就是14……

如果是基础的layer类,loadImages就是直接载入静态图片,但是让我们再看一遍这个结构图

Layer ( 吉里吉里ネイティヴクラス )
|
+-- KAGLayer ( このファイル )
       |
       +-- AnimationLayer ( AnimationLayer.tjs )
       |    |
       |    +-- ClickGlyphLayer ( AnimationLayer.tjs )
       |    |
       |    +-- GraphicLayer ( GraphicLayer.tjs )
       |         |
       |         +-- BaseLayer ( GraphicLayer.tjs )
       |         |
       |         +-- CharacterLayer ( GraphicLayer.tjs )
       |
       +-- MessageLayer ( MessageLayer.tjs )
       |
       +-- ButtonLayer ( ButtonLayer.tjs )
       |    |
       |    +-- LinkButtonLayer ( MessageLayer.tjs )
       |    |
       |    +-- LButtonLayer ( HistoryLayer.tjs )
       |
       +-- EditLayer ( EditLayer.tjs )
       |    |
       |    +-- LinkEditLayer ( MessageLayer.tjs )
       |
       +-- CheckBoxLayer ( CheckBoxLayer.tjs )
            |
            +-- LinkCheckBoxLayer ( MessageLayer.tjs )

平时kag中用的layer除了base层是baselayer类外,其他层都是CharacterLayer类,而这两个类都是继承了GraphicLayer类,GraphicLayer类继承的是AnimationLayer类……所以AnimationLayer里重定义了loadImages的话,这些类在执行loadImages的时候也是执行的他所重定义的内容(当然如果子类又进行了重定义那就是另外一回事了,但是目前我们在讲AnimationLayer类,于是先无视子类的情况)

AnimationLayer类里的loadImages是下边这样的……因为太长了我就把解释直接写在注释里了……

function loadImages(elm)
{
   // loadImages オーバーライド
   // elm は読み込み情報
   if(elm === void)
//如果什么都没传入就直接释放图片,然后结束操作返回
   {
    freeImage();
    return;
   }

   Anim_loadParams = %[];
   (Dictionary.assign incontextof Anim_loadParams)(elm);
// 将传入的字典复制给Anim_loadParams

   clearAnim();
//清除图层上的动画,因为重新载入图片了,原来上边的内容就要被清掉,clearAnim()的具体内容自己看吧……我就不一个一个讲了不然会没完没了的……||||||||||

   Anim_partialImageInfo = void;
//这里也是清除原来的信息

   var taginfo = super.loadImages(elm.storage, elm.key);
//读入图片,同时把返回值赋给临时变量taginfo,layer类的loadImages本身是会返回一个字典的,内容大致是画面情报位置之类的

   if(taginfo)
   {
    (Dictionary.assign incontextof taginfo)(elm, false);
    elm = taginfo;
   }
//把传入的那个字典参数elm合并到taginfo里,再赋值给elm(就是说现在elm里和taginfo里都是原来两个字典的合并)

   var ud, lr;
   if(elm.flipud !== void && +elm.flipud)
   {
    // 如果elm里flipud参数不是空的就进行flipUD(),这个函数用来翻转图片,具体内容也请直接自己看……
   //这个所谓的flipud参数不是空的的意思就是,你在kag里写了[image storage=xxx layer=xx   flipud=true]……
    flipUD();
    ud = true;
   }
   else
   {
    ud = false;
   }

   if(elm.fliplr !== void && +elm.fliplr)
   {
    // 左右翻转
    flipLR();
    lr = true;
   }
   else
   {
    lr = false;
   }

   if(elm.clipleft !== void)
   {
    // 指定了clip的情况,这里可以看出必须要填clipleft,不然只填其他几个clip不填clipleft会被程序无视……
   // 顺便说一下,认真看过layer类的说明的人就会知道,layer是有image大小和图层大小两个概念的,如下图所示

//就像是走马灯一样,我们可以看到前边的木框,后边的图片却可以所以移动来改变我们可以看到的部分,注意imageleft,imagetop的坐标是以显示出来的区域的左上角为0,0的相对坐标。另外不可以让image层没有的部分在显示出来的区域露出来,那样会报错……
//所以所谓的clip就是把图片load出来之后根据你填写的参数设定了显示出来的区域的大小和位置,而所谓asd动画……他就是走马灯……

    width = +elm.clipwidth;
    height = +elm.clipheight;
    var cl = elm.clipleft;
    if(lr) cl = imageWidth - cl - width;
    var ct = elm.cliptop;
    if(ud) ct = imageHeight - ct - height;
    imageLeft = -cl;
    imageTop = -ct;
   }
   else
   {
    setSizeToImageSize();
   }

   {
    var mode = ltAlpha;
//这边是图像模式的赋值

    if(elm.mode !== void)
    {
     var layertypeinfo = imageTagLayerType[elm.mode];
     if(layertypeinfo !== void)
      mode = layertypeinfo.type;
    }

    type = mode;
   }

   // 色補正
   face = dfAuto;
   applyColorCorrection(this, elm);

   // 可视、位置、不透明度、层位置(index)
   if ( elm !== void && elm.pos !== void ) {
    // 如果在image里写了pos这个参数(写了left、right、center这类的),就是用那个位置作为底面中心,这个是给立绘用的,具体这几个参数对应的坐标是放在scPositionX这个字典里的,我记得config里有对他的设定
    left= window.scPositionX[elm.pos] - width 2;
    top = window.scHeight - height;
   }
   else
//如果没设定pos就用设定的left和top来放图的位置
   {
    if(elm.left !== void) left = +elm.left;
    if(elm.top !== void) top = +elm.top;
   }
   if(elm.visible !== void) visible = +elm.visible;
   if(elm.opacity !== void) opacity = +elm.opacity;
   absolute = +elm.index if elm.index !== void;

   // 最后这段就是载入asd动画了
   Anim_storageName =
    Storages.getPlacedPath(
     Storages.chopStorageExt(elm.storage) + ".asd");
//首先是寻找有没有图片同名的asd文件
   if(Anim_storageName != ')
   {
//如果有的话就执行loadAnimInfo
    loadAnimInfo(0, '); 
   }
}

那么,就来看看loadAnimInfo是什么……

function loadAnimInfo(segment, label)
{

   if(Anim_storageName == ')
    throw new Exception(
     ("对于" + Anim_loadParams !== void ? Anim_loadParams.storage : "") +
     "没有动画信息");
//如果不存在asd文件就抛出错误

   var seg;
   if(Anim_segments[segment] === void)
   {
//segment刚才传入的值是0,Anim_segments[0]在构造函数里已经被定义为了AnimationConductor类的实体……如果只用kag的话,是不存在出现使用Anim_segments[1]之类的情况的,在kag里一个层也就会用到Anim_segments[0]这一个AnimationConductor,对于kag来说这个步骤其实没太大意义,不过如果用tjs写的话,就可以随意了
    Anim_segments[segment] = seg = new AnimationConductor(this);
    seg.number = segment;
   }
   else
   {
    // 已经被定义过的情况下执行停止动画
    (seg = Anim_segments[segment]).stop();
   }

//接下来对这个AnimationConductor类进行各种赋值
   seg.startLabel = label;
   seg.stopping = false;
   seg.running = true;
   seg.clearCallStack();
   seg.interrupted = Anim_interrupted;
   seg.loadScenario(Anim_storageName);
   if(label != ') seg.goToLabel(label);
   seg.startProcess(true);
}

最后执行了这个AnimationConductor的startProcess,那么,现在我们可以来看看AnimationConductor类到底都能做些什么了……

AnimationConductor继承的是BaseConductor,BaseConductor继承的是KAGParser……KAGParser的方法列表如下

コンストラクタ
KAGParser
メソッド
assign ( KAGParser オブジェクトのコピー )
callLabel ( 現在位置をスタックに積んでの、指定ラベルへの移動 )
clear ( オブジェクトのクリア )
clearCallStack ( call タグ呼び出しスタックのクリア )
getNextTag ( 次のタグを得る )
goToLabel ( 指定ラベルへの移動 )
interrupt ( interrupted 状態にする )
loadScenario ( シナリオの読み込み )
resetInterrupt ( interrupted 状態の解除 )
restore ( 辞書配列からオブジェクトの状態を復元する )
store ( オブジェクトの状態を辞書配列に書き出す )
プロパティ
callStackDepth ( call タグ呼び出しスタックの深さ )
curLabel ( 現在のラベル )
curLine ( 現在行の行数 )
curLineStr ( 現在行の文字列 )
curPos ( 現在行における文字の位置 )
curStorage ( 現在のストレージ )
debugLevel ( デバッグレベル )
ignoreCR ( 改行を無視するかどうか )
macroParams ( 現在実行されているマクロの引数 )
macros ( マクロの入った辞書配列 )
イベント
onAfterReturn ( return タグで復帰した )
onCall ( call タグが呼ばれた )
onJump ( jump タグが呼ばれた )
onLabel ( ラベルを通過した )
onReturn ( return タグが呼ばれた )
onScenarioLoad ( シナリオ読み込みが開始した )
onScenarioLoaded ( シナリオ読み込みが終了した )
onScript ( iscript ブロックを通過した )

startProcess是BaseConductor的函数,其他那些参数和方法就都是KAGParser的了(BaseConductor有进行重定义不过基本还是super的)所以具体内容可以直接查阅kr2doc……所以其实asd脚本和ks脚本写起来也没太大区别了,可以用标签可以用变量可以用macro可以用条件判断……

这样,AnimationLayer就到此为止……



TOP

访客数: 3128242
aa