Gikot プログラミングガイド

back

Last modified: Sat Sep 21 15:49:38 2002

このページでは、Python を使って Gikot のアニメーションを 拡張したり、別のプログラムから呼び出したりするための方法を説明します。



1. Python を使ったプログラミング

Gikot ではプログラミング言語 Python を使って アニメーションを作成します。Python については www.python.orgwww.python.jp に 参考となるドキュメントがあります (オライリーから出ている書籍もおすすめです)。

ただし、Java や Perl をかじったことのある人なら、 とくに Python の知識がなくてもサンプルプログラムを見よう見まねで 拡張して新しいアニメーションを作ることもできると思います (実用的なアプリケーションにしようとすると Python や UNIX の知識が必要になりますが)。


2. Gikot クライアントのつくりかた

骨組み

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 を超えたかどうかでアニメーションの終了判定を 行うことができます。


3. サンプルプログラムを見る

プログラミングは実例を見て覚えるのがてっとり早いでしょう。

サンプルプログラムは Gikot パッケージの examples/ ディレクトリに入っています。 ここではいくつかの基本的なテクニックを紹介しています。 ソース中にもコメントがあるので参考にしてください。

sample0.py
もっとも簡単なサンプルです。 ギコを画面中央に表示し、終了します。 アニメーションは行いません。 これはほとんどすべての Gikot クライアントの骨組みとなるものです。
sample1.py
変数と sleep を使った簡単なアニメーションのサンプルです。
sample2.py
Gikot では、AA の大きさや画面サイズを なるべく意識せずにプログラミングできるようになっています。 これはその一例で、2つのアンカーポイントを使ったサンプルです。
sample3.py
スレッドを使ったアニメーションのサンプルで、 (゚д゚) と (゚∀゚) が独立に移動します。

4. gutils 関数リファレンス

Agent オブジェクト

Agent オブジェクトは仮想空間上のエージェントを表します。 実際にはこれは gutils モジュールによって提供される ラッパで、CORBA オブジェクトそのものではありません。

Agent オブジェクトのメソッド:

Agent('エージェント名')
与えられた名前をもつエージェントのオブジェクトを 仮想空間から取得し返します。与えられた名前のエージェントが ない場合は新たに仮想空間にそれを作成します。 エージェントが最初に作成された時にはそのフォームおよび 変数の内容は空で、非表示になっています。
Agent set_form('フォーム文字列')
エージェントにフォーム文字列を指定します。 実際のエージェントの表示は update() メソッドを呼び出すまで 反映されません。
Agent set_var(変数番l号, '文字列')
エージェントのフォーム中にある変数 ($0, $1, $2, ...) の内容を 与えられた文字列に置換します。 実際のエージェントの表示は update() メソッドを呼び出すまで 反映されません。
Agent set_origin(アンカー番号)
エージェントの基点 (moveto メソッドなどで 移動するときの点) を指定されたアンカーに移動します。 デフォルトでは、エージェントの基点はアンカー 0 になっています。
Agent update()
エージェントを再描画します。 set_formmoveto などの コマンドは、update() メソッドを呼び出すまで 実際の画面には反映されません (これはおもにチラつきを防ぐためです)。
Agent show(フラグ)
エージェントの表示および非表示を切りかえます。 フラグが 1 ならば表示、0 ならば非表示になります。 エージェントが作成されたさい、デフォルトは非表示になっています。
Agent moveto(X座標, Y座標)
エージェントを指定された座標に移動します。 負の値を指定すると画面右端 (あるいは下端) からの指定とみなされます。 実際のエージェントの表示は update() メソッドを呼び出すまで 反映されません。
Agent movetof(X座標, Y座標)
エージェントを指定された座標に移動しますが、 このときの座標は画面に対して 0.0〜1.0 の小数で指定します。 負の値を指定すると画面右端 (あるいは下端) からの指定とみなされます。 実際のエージェントの表示は update() メソッドを呼び出すまで 反映されません。
Agent move(X座標, Y座標)
エージェントを指定された相対値だけ移動させます。 実際のエージェントの表示は update() メソッドを呼び出すまで 反映されません。
int get_origin()
現在のエージェントの基点であるアンカー番号を整数で返します。
(int,int) pos(アンカー番号)
エージェントの指定されたアンカーの、現在の座標を (x,y) のタプルで返します。
(int,int) posf(アンカー番号)
エージェントの指定されたアンカーの、現在の座標を (x,y) のタプルで返します。ただしこのときの値は 画面に対して 0.0〜1.0 の小数に正規化されています。
(int,int) size()
現在のエージェントのサイズをピクセル単位で (width,height) のタプルで返します。
delete()
エージェントを仮想世界から抹消します。 delete メソッドを一回呼び出すと、もう そのエージェントのどんなメソッドも呼ぶことはできません。

Animation オブジェクト

Animation オブジェクトは同時並列的に進行するアニメーションを つくるための便宜的なスレッドを提供します。

Animation オブジェクトのメソッド:

Animation(アニメーション手続き, 引数1, 引数2 ...)
新しくアニメーション用のスレッドを生成し、 与えられた手続きを走らせます。この手続きには ここで与えた引数のリストが渡されます。
stop()
スレッドを終了させます。

(注意: これは実際にはいんちきです。 現行の Python ではスレッドに割り込みをかける方法がなく、 スレッドの終了は Agent オブジェクトのメソッドを呼びだすごとに フラグをチェックさせることによって行っています。 そのため、 Agent オブジェクトのメソッドをまったく呼びださない スレッドはこのメソッドでは終了できません)

その他のユーティリティ関数

init(コマンドライン引数 [,usage文字列 [,オプション文字列 [,ロングオプションのリスト]]])
クライアントを初期化し、Gikot サーバに接続します。 このとき --ior および --geometry オプションを処理します。 オプション文字列およびロングオプションのリストは Python ライブラリの getopt.getopt 関数に渡すものと同じです。オプション指定がおかしな場合、 この関数は usage 文字列を表示してプロセスを終了させます。

注意: gutils モジュールの他のすべて関数を呼び出すのに先だって、 かならずこの関数を実行してください。

(int, int) world_size()
仮想世界のサイズをピクセル単位で (width,height) というタプルで返します。
(int, int) default_pos()
ユーザが --geometry オプションに与えた 座標値を (x,y) というタプルで返します。
(int, int) default_posf()
ユーザが --geometry オプションに与えた 座標値を (x,y) というタプルで返します。ただしこのときの値は 画面に対して 0.0〜1.0 の小数に正規化されています。
cleanup()
現在のプロセスで作成したエージェントをすべて抹消します。
(int, int) get_pointer()
現在のマウスポインタの座標をピクセル単位で (x,y) というタプルで返します。
[name1, name2, ...] get_agent_names()
現在、仮想世界に表示されているすべてのエージェント名を リストにして返します。