このページでは、Python を使って Gikot のアニメーションを 拡張したり、別のプログラムから呼び出したりするための方法を説明します。
Gikot ではプログラミング言語 Python を使って アニメーションを作成します。Python については www.python.org や www.python.jp に 参考となるドキュメントがあります (オライリーから出ている書籍もおすすめです)。
ただし、Java や Perl をかじったことのある人なら、 とくに Python の知識がなくてもサンプルプログラムを見よう見まねで 拡張して新しいアニメーションを作ることもできると思います (実用的なアプリケーションにしようとすると Python や UNIX の知識が必要になりますが)。
Gikot は CORBA を使ってエージェントを制御できます。 なので、基本的には CORBA オブジェクトにメソッドを直接送って エージェントを操作してもいいのですが、ここでは gutils を 使って Gikot クライアントを作ってみましょう。 gutils モジュールは CORBA へのラッパを提供し、 より簡単な方法でアニメーションが設計できるように作ってあります。
はじめに、 Emacs などで新しいファイル開いて 以下のような内容をコピペします (Python のプログラムを組むときは、あらかじめ Python-Mode を インストールしておくと便利です):
#!/usr/bin/env python # -*-Python-*- import sys from gutils import * init(sys.argv)
(注意: ファイルの文字コードは必ず EUC-JP にしてください。 現在のところ、Gikot で使われる文字コードは EUC-JP に限定されています。)
仮想空間内に新しいエージェントを生成するには、つぎのように Agent オブジェクトを作れば OK です。Agent コンストラクタの 引数にはエージェント名を指定します (この名前が以後 X のトップレベルウインドウの名前にもなります) :
a = Agent('giko')
ここでできたエージェント a
は Python オブジェクトの
インスタンスです。このインスタンスは同時に Gikot サーバ上の CORBA
オブジェクトとも連結されており、この時点でエージェントは
仮想空間につくられます。
ただし、まだこの時点ではエージェントの実体はなく、状態も「非表示」です。
幽霊のようなものが生まれただけと考えてください。
つぎにこのエージェントに実体 (フォーム) を与えてやりましょう。
これには、Agent オブジェクトの set_form
メソッドを
使います :
a.set_form(''' ∧ ∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ 〜′  ̄ ̄( ゚Д゚)%0< 逝ってよし!! UU ̄ ̄ U U \____________''')
Python では ''' 〜 '''
で囲まれた部分は
改行をふくむ文字列になります。
ここではインスタンス a
にギコ猫の形状を指定しています。
ここで、文字列の中に余計な「%0
」が含まれているのに
お気づきでしょうか。これは「アンカーポイント」と
呼ばれるもので、フォーム中に含まれる「%
数字」はすべて
アンカーポイントとみなされます (% そのものを表示したいときは
%%
のように 2個続けてください)。
ここでのアンカーポイント %0
はそのエージェントの
「中心」を表すものです。つぎにエージェントの位置を決めます。
a.movetof(0.5, 0.5)
movetof
メソッドは
画面を (0.0, 0.0) 〜 (1.0, 1.0) の矩形として、与えられた
小数 (0.5, 0.5) に対応する座標にエージェントの
アンカーポイント %0
がくるように
エージェントを移動させます。
つまりこの場合はギコ猫の顔の右端が画面中央にくるわけですね。
つぎに、update
メソッドと
show
メソッドを呼び出します。
a.update() a.show(1)
じつは set_form
メソッドや movetof
メソッドで
指定したエージェントの位置や形状は、update
メソッドを
使うことによってはじめて実際に反映されます
(画面のちらつきを抑えるためです)。
あらゆるアニメーションでは update
メソッドを
呼びだすのを忘れないようにしてください。
最後に show
メソッドを呼び出して、
エージェントの状態を「非表示」から「表示」に変更します。
これで無事ギコ猫エージェントが画面に表示されます。
では、エージェントを動かすにはどうすればいいでしょうか。
まず sleep メソッドをインポートしておきましょう。 これは与えられた秒数 (小数指定可) だけウェイトをかけるもので、 アニメーションには必須の関数です (ソースコードの美しさのために、できればこれはソースの最初で gutils などと一緒に宣言するほうがよいでしょう)。
from time import sleep
これであとは好きに動きを記述してください:
for i in range(10): a.move(10, 0) a.update() sleep(0.1)
move
というのはエージェントを指定された
ピクセル数だけ相対的に移動させるメソッドです。
この場合は 0.1 秒ごとにギコ猫が 10ピクセルずつ画面右に向かって
移動することになります。update
を呼ぶのを忘れずに。
ちなみに gutils のほとんどのメソッドはそのオブジェクト自身を 値として返します。なので、上のような例は:
for i in range(10): a.move(10, 0).update() sleep(0.1)
のように短縮して書くことも可能です。
Gikot ではプログラム中で作ったエージェントは、
プログラムが終了してもそのまま仮想世界に残ります
(他のプログラムもそれを使うかもしれないからです)。
アニメーションが終わったあとに、プログラム中で作成した
エージェントをすべて抹消したいときには、
プログラムの最後で cleanup
関数を使いましょう。
cleanup()
なお、Control-C を押す (SIGINT が送られる) と gutils は 自動的にいまのプロセスで使っているすべてのエージェントを 削除して終了します。
あとはこのスクリプトファイルに適当な名前 (giko など) をつけて、 実行可能パーミッションを立てればできあがりです。
AA を使ったアニメーションでは、エージェントの形状の一部だけを 変更したいことがあります (セリフなど)。 このようなときに Gikot では「フォーム変数」というものがサポートされています。 たとえば以下のコードを見てください:
a.set_form(''' ∧ ∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ %1〜′  ̄ ̄( ゚Д゚)%0< $1 UU ̄ ̄ U U \____________''')
この「$1
」と書かれた部分は、
エージェントを表示するとき (update するとき) に
別の内容に置きかえられます。これがフォーム変数です。
フォーム中に含まれる「$
数字」はすべて
アンカーポイントとみなされます ($ そのものを表示したいときは
$$
のように 2個続けてください)。
この内容は、set_var
メソッドによって
変更することができます。
a.set_var(1, '')
また、上の例ではアンカーポイントが 2つ (%0
と %1
)
あります。Gikot では、エージェントを移動するときに使われる
%0
のほかにもいくつものアンカーポイントを
指定することができます。アンカーポイントは、
エージェントの一部に別のエージェントを重ねたり、
AA が画面からはみ出したかどうかを検査するのに使えます。たとえば
posf
メソッドを使って先のギコ猫エージェントに対して
(x, y) = a.posf(1)
を実行すると、ギコ猫のしっぽの先端の座標が得られます。 ギコが画面左端から出てきて右端に消えるようなアニメーションの場合、 この X 座標が 1.0 を超えたかどうかでアニメーションの終了判定を 行うことができます。
プログラミングは実例を見て覚えるのがてっとり早いでしょう。
サンプルプログラムは Gikot パッケージの
examples/
ディレクトリに入っています。
ここではいくつかの基本的なテクニックを紹介しています。
ソース中にもコメントがあるので参考にしてください。
sample0.py
sample1.py
sample2.py
sample3.py
Agent オブジェクトは仮想空間上のエージェントを表します。 実際にはこれは gutils モジュールによって提供される ラッパで、CORBA オブジェクトそのものではありません。
Agent オブジェクトのメソッド:
Agent('エージェント名')
Agent set_form('フォーム文字列')
update()
メソッドを呼び出すまで
反映されません。
Agent set_var(変数番l号, '文字列')
update()
メソッドを呼び出すまで
反映されません。
Agent set_origin(アンカー番号)
moveto
メソッドなどで
移動するときの点) を指定されたアンカーに移動します。
デフォルトでは、エージェントの基点はアンカー 0 になっています。
Agent update()
set_form
や moveto
などの
コマンドは、update()
メソッドを呼び出すまで
実際の画面には反映されません (これはおもにチラつきを防ぐためです)。
Agent show(フラグ)
Agent moveto(X座標, Y座標)
update()
メソッドを呼び出すまで
反映されません。
Agent movetof(X座標, Y座標)
update()
メソッドを呼び出すまで
反映されません。
Agent move(X座標, Y座標)
update()
メソッドを呼び出すまで
反映されません。
int get_origin()
(int,int) pos(アンカー番号)
(int,int) posf(アンカー番号)
(int,int) size()
delete()
Animation オブジェクトは同時並列的に進行するアニメーションを つくるための便宜的なスレッドを提供します。
Animation オブジェクトのメソッド:
Animation(アニメーション手続き, 引数1, 引数2 ...)
stop()
(注意: これは実際にはいんちきです。 現行の Python ではスレッドに割り込みをかける方法がなく、 スレッドの終了は Agent オブジェクトのメソッドを呼びだすごとに フラグをチェックさせることによって行っています。 そのため、 Agent オブジェクトのメソッドをまったく呼びださない スレッドはこのメソッドでは終了できません)
init(コマンドライン引数 [,usage文字列 [,オプション文字列 [,ロングオプションのリスト]]])
--ior
および --geometry
オプションを処理します。
オプション文字列およびロングオプションのリストは
Python ライブラリの getopt.getopt
関数に渡すものと同じです。オプション指定がおかしな場合、
この関数は usage 文字列を表示してプロセスを終了させます。
注意: gutils モジュールの他のすべて関数を呼び出すのに先だって、 かならずこの関数を実行してください。
(int, int) world_size()
(int, int) default_pos()
--geometry
オプションに与えた
座標値を (x,y) というタプルで返します。
(int, int) default_posf()
--geometry
オプションに与えた
座標値を (x,y) というタプルで返します。ただしこのときの値は
画面に対して 0.0〜1.0 の小数に正規化されています。
cleanup()
(int, int) get_pointer()
[name1, name2, ...] get_agent_names()