クラス化する

今回の話は正直かなりややこしい…

前回は同時実行されるフェードインアウト演出をスレッド化によって実現した。
今回はスレッド化とは別のアプローチで、同じような動作を実現してみよう。
それが今回のお題の…

クラス化だ!

クラスとは等級、階級、科目、分類といった意味で、
プログラマーにはオブジェクト指向でお馴染みだろう。
まさしくその『クラス』だ。

クラスはプログラミング用語では「オブジェクトの設計図」を意味する。
オブジェクトとは「機能的な構造を持つ部品」のようなものである。
Foooにおいて部品はデーカーだから…
Foooにおけるクラスとは

デーカーの設計図

であると言える。
Foooには独自に設計したデーカーをクラスとして定義する仕組みがある。
と言ってもなんでもかんでも自由に作れるというわけではない。
既存のデーカーを組み合わせて複雑な動作をするデーカーを定義できるのである。

クラスの定義

それではフェードインアウトをクラスとして定義してみよう。


class フェードインアウト
{
  method フェードインアウト(color $色=white, string $合成="Normal")
  {
    CreateColor(name="幕", color=$色, w=1280, h=720, blend=$合成);
  }

  method OnEnter()
  {
    Enter(to="幕");
  }

  method 開始(int $フェード=1000, int $待ち=0)
  {
    Opaque(to="幕", time=$フェード, alpha=0%, step="DecSin");
    wait $フェード;
  
    wait $待ち;

    Opaque(to="幕", time=$フェード, alpha=100%, step="AccSin");
    wait $フェード;
  }
}

なんだかちょっと不思議な表記に感じるかもしれない。
とにもかくにもこれでフェードインアウトクラスの定義ができる。

クラスの使用

定義したクラスを使ってデーカーを作るにはCreateObject命令を使う。


CreateObject(name="フェード"
  , class=@フェードインアウト(色=white, 合成="Add"));
Enter(to="フェード");

CreateObject命令で作られるデーカーはオブジェクトデーカーと呼ぶ。
オブジェクトデーカーはclassパラメータに指定されたクラスの定義に従って動作する。

1つめのフェードインアウトメソッドは、オブジェクトデーカーが作成された時に自動的に呼び出される。
このようなクラス名と同じ名前のメソッドを「コンストラクタ」と呼ぶ。
コンストラクタでは構成部品となるデーカーの作成だけをするのがお約束だ。
なのでフェードインアウトメソッドでは”幕”の作成だけしている。
ちなみにこの”幕”はオブジェクトデーカーの子として作成される。

2つめのOnEnterメソッドは、オブジェクトデーカーがEnter命令で表示された時に自動的に呼び出される。
OnEnterメソッドにはデーカーが表示される際の動作を記述する。
ここでは子として作った幕をEnterしている。

3つめの開始メソッドは、自動的に呼ばれるメソッドではない。
まったくの独自のメソッドである。
任意に呼び出して使用する。
外からオブジェクトデーカーのメソッドを呼ぶにはRequest命令を使う。


Request(to="フェード", order=@開始(待ち=5000));

これらオブジェクトデーカーの持つメソッドは、オブジェクトデーカーの管理下にあり、
スレッドと同じように呼び出し元と同時進行で実行される。
これはすなわち

デーカーがメソッドを実行してくれる

ということである!

デーカーがメソッドを
実行してくれる

ということである!!!
大事なことなので(ry

──────ばばーっと説明してきたので、
このような仕組みにいったいどんな意味があるのかわかりにくかったかもしれない。
とりあえず実際に組み込んでみよう。


style 普通 { face="MS ゴシック", size=32 }
style 小 { size=24 }
style つぶやき { interval=100, speed=250, effect="Rise" }

#base_param CreateBalloon(style="普通")
#base_param CreateFrame(outline_shape="Vivide"
  , outline_color=white, outline_thick=8)

class フェードインアウト
{
  method フェードインアウト(color $色=white, string $合成="Normal")
  {
    CreateColor(name="幕", color=$色, w=1280, h=720, blend=$合成);
  }

  method OnEnter()
  {
    Enter(to="幕");
  }

  method 開始(int $フェード=1000, int $待ち=0)
  {
    Opaque(to="幕", time=$フェード, alpha=0%, step="DecSin");
    wait $フェード;
  
    wait $待ち;

    Opaque(to="幕", time=$フェード, alpha=100%, step="AccSin");
    wait $フェード;
  }
}

method Main()
{
  CreateImage(name="背景", image="背景.png"
    , x=0, y=0);

  CreateNode(name="コマ1"
    , x=642, y=0, sx=0%);
  CreateWindow(name="コマ1/窓"
    , w=405, h=720, ox="Center", propagation="CancelParentZoom");
  CreateImage(name="コマ1/窓/画像", image="コマ1.png"
    , x=20, y=324, ox="Center", oy="Middle", sx=110%, sy=110%
    , sampling="BieLinear");
  CreateOutline(name="コマ1/枠"
    , w=405, h=720, shape="Fade", color=RGBA(0,0,0,64), thick=8
    , ox="Center", adaptive=true);

  CreateFrame(name="コマ2", image="コマ2.png"
    , x="OutRight", y=65);
  CreateFrame(name="コマ3", image="コマ3.png"
    , x=407, y=505, ox="Center", oy="Middle", sx=0%, sy=0%
    , outline_color=black);

  CreateBalloon(name="台詞1"
    , text="それにしても...<BR>腹(はら)が減(へ)った"
    , x=585, y=65, shape="Dumpling", w=300, h=185, tail=-30);
  CreateBalloon(name="コマ3/台詞2"
    , style="小", text="<FONT style='つぶやき'>クククク…"
    , x=63, y=15, shape="Rock", w=220, h=125, tail=160);

  CreateObject(name="フェード"
    , class=@フェードインアウト(色=white, 合成="Add"), silent=true);

  Enter(to="背景");
  Enter(to="コマ1");
  Enter(to="コマ1/窓");
  Enter(to="コマ1/窓/画像");
  Enter(to="コマ1/枠");
  Enter(to="フェード");
  wait 500;

  Request(to="フェード", order=@開始(待ち=5000));
  Zoom(to="コマ1", time=1000, sx=100%, step="DecSin");
  Move(to="コマ1/窓/画像", time=1000, x=-20, step="DecSin");
  WaitDecor();

  Enter(to="コマ2");
  Move(to="コマ2", time=800, x=780, step="Dec3");
  WaitDecor();

  Enter(to="台詞1", effect="Bound");
  WaitDecor();

  Enter(to="コマ3");
  Zoom(to="コマ3", time=1000, sx=100%, sy=100%, step="AccSig");
  wait 600;

  Enter(to="コマ3/台詞2", effect="Expand");
  WaitDecor();
}

何気にsilent=trueという指定が加わっているが、
これはWaitDecor命令でこのデーカーを待たないことを意味する指定だ。

こうして組み込んでみると、クラスとして定義したデーカーが
オリジナルのデーカーとして扱えるようになっている様子がよくわかるだろう。
若干定義は面倒くさいものの、慣れればスレッドよりもずっと直感的だ。

そして何よりも「デーカーがメソッドを実行してくれる」という事実がもたらす
利便性と自由度の高さは計り知れない。


Leave a Reply

*