J3W用のソースプログラム(定義ファイル)のプログラミングの基本の紹 介です.リファレンスマニュアル(manual.txt)ではアセンブラの知識を前 提とした記述になっていますが,ここでは,ほとんどアセンブリ言語を知ら ない方でも理解できるように努力したつもりです. BASIC, C等の高級言語と 比較すると文法も各命令の動作も単純なのでリファレンスマニュアルととも に順に追っていけば比較的簡単ではないかと思います. 正確な説明はリファ レンスマニュアルを参照してください.
アセンブラの機能とJ3Wの機能を分けて記述していません.J3DASMとJ3Wを 組み合わせて使用した場合を想定しています. LIST1からLIST10のアセンブル済みファイルは同梱してあります.
本書中に含まれるソースコードは【4】章の一部を除いて実行可能なプログ ラムとなっています.
;<-------------- ここから ;<-------------- ここまで
に囲まれた部分を切り取ってアセンブルする(詳細は後述)ことによってJ3W から実行可能です.
まず最初のプログラムは,Hello Worldという文字列をテキストウインドウに
表示するプログラムです.グラフィックウインドウは開きません.
テキストウインドウは範囲をマウスで選択してコントロールキーとCを同時
に押すとクリップボードにコピーされます.(Windows95/98)
;<-------------- ここから ; LIST1 OUTSTR "Hello World" OUTCHR 13 STPALL ;<-------------- ここまで
「ここから」「ここまで」をエディタ等で切り取って,例えばLIST1.J3Sとし て保存します.
コマンドライン(DOSプロンプト)から
>J3DASM LIST1.J3S
のように実行するか,J3DASM.EXEのアイコンに LIST1.J3Sのアイコンをドラッ
グアンドドロップするとDOSウインドウが開き,LIST1.J3Dが生成されます.こ
のLIST1.J3DをJ3W.EXEのNEWボタンから指定するか,J3W.EXEのアイコンに
LIST1.J3Dのアイコンをドラッグアンドドロップし,STARTボタンで実行されます.
j3wの実行には Xが必要です. ktermを開いて
$ j3dasm list1.j3s
で list1.j3s は list1.j3d へアセンブルされます.
$ j3w list1.j3d
で実行されます.
セミコロンより後ろは注釈として無視されます.
命令はすべて大文字です.ラベルは最後にコロンか続く文字列で,大文字小
文字は区別されます.詳細はマニュアルの【6】 アセンブラ仕様を参照
して下さい.
OUTSTRが文字列表示用の命令です. OUTCHR 13は改行文字を出力します. (Linux版では 13[CR] は 10[LF] に内部で変換されます.)
STPALLはすべてのプロセスを停止する命令です.この場合は1つのプロセス しかありませんが,プログラム(プロセス)の最後に置くようにします.
次はレジスタ演算,条件分岐です.
;<-------------- ここから ; LIST2 LOAD R1 100 LABEL1: OUTNUM R1 OUTSTR " Hello World" OUTCHR 13 SUB R1 10 BPL LABEL1: DELPRC ;<-------------- ここまで
LOAD R1 100 は 「R1」という名の初めから用意されている容器(レジスタと
呼びます)に100を入れます.
次の行の LABEL1: はラベルと呼びジャンプ先
を指定する場合等に使用します. LABEL1: OUTNUM R1 のように空白(半角)
のあとに命令を続けることもできます. OUTNUM R1 は R1の内容を数値とし
て出力します. SUB R1 10 は R1 = R1 - 10 の意味でR1の内容から10を引き
ます. 次の行の BPL LABEL1: は条件分岐命令の1つで「もし結果が正かゼ
ロならジャンプ」します.この場合はR1の内容が正ならばLABEL1:に戻ります.
次にR1の内容が90の状態で同様な動作をして,順次 R1の内容が80,70,60,
50,40,30,20,10,0と減少します.R1が0になったとき SUB R1 10 を実行
すると,R1は-10になり,LABEL1:にジャンプすることなく次の行,この場合
DELPRCに移ってプロセスが消滅し実行は終了します.
DELPRCは,この命令を
実行するプロセスだけを削除します.それが唯一のプロセスならばプログラ
ム自体が終了します.他のプロセスを含めてすべて終了させる場合はSTPALL
命令を使用します. 無限ループのプロセスの場合でもプロセスの区切りとし
てDELPRCかSTPALLを最後に置くのがいいでしょう.
レジスタは R1以外にも RQ, RL, RX, RY, RZ, RH, RP, RB, R2, R3, R4, R5, R6があります. R1からR6は数値の入れ物として使用します.RQ から RBは 数値の入れ物として使用する以外に命令によって特別な役割を持ちます.
次は複数のプロセスを同時に実行する場合の例です. 長さの割に動作がちょっと複雑になります.
;<-------------- ここから ; LIST3 GENPRC ESC: 50 LOAD R1 0 LABEL1: OUTNUM R1 OUTCHR 13 ADD R1 1 THROW ; この命令が重要 BRA LABEL1: ; 無限ループ DELPRC ; ここから2つ目のプロセス ESC: LOAD RQ 9 ESC1: INKEY R1 ; キ−コ−ド入力 THROW ; この命令が重要 CMP R1 0x1B BNE ESC1: STPALL ; 全プロセスの終了 ;<-------------- ここまで
この例では,まず
ここで2つのプロセスの動作を考えます.
個々に考えるとどちらも無限ループかそれに近いものですが,2つのプロセ
スが同時に実行されていると「ESCキーが押されるまで0から順に1を加えてそ
れを表示する」プログラムとなります.2つめのプロセス(今後ESCプロセス
と呼びます)はESCキーが押されると STPALL に処理が移り,他のすべてのプ
ロセスを終了させるためです.
ただし複数のプロセスを同時に実行するとい
っても実際は他のプロセスに処理を渡す必要があり(物体の移動などの時間
を指定する命令では自動的に渡される.詳細は後述),ループになるプログ
ラムではTHROW命令をループ内に置いて他のプロセスに実行するチャンスを与
えてください.THROW命令があるとWindowsにも他の処理をするチャンスが与
えられます.THROW命令をループ内に置けば,安心して無限ループを持つ複数
のプロセスを同時に実行させられます.
ESCプロセスの最初の命令 LOAD RQ 9
はプロセスの識別番号を9に設定するた
めの命令です.他のプロセスからメッセージを送る場合などに使用しますが,
LIST3の場合は使用されていません.
INKEYによるキー入力はグラフィックウィンドウかテキストウィンドウがアク ティブになっている必要があります.アクティブでなくてもキー入力を有効に するためには以下のリストを使用してください.
;<-------------- ここから ESC: RAWKEY R1 0x1B ; キ−コ−ド入力 THROW CMP R1 0 BEQ ESC: STPALL ;<-------------- ここまで
LIST3の以下の部分をESCAPE.J3Iというファイルに保存します.
;<-------------- ここから ESC: LOAD RQ 9 ESC1: INKEY R1 ; キ−コ−ド入力 THROW ; この命令が重要 CMP R1 0x1B BNE ESC1: STPALL ; 全プロセスの終了 ;<-------------- ここまで
以下のように別ファイルで指定するとアセンブル時にESCAPE.J3Iが挿入され ます.LIST3と同等です.
この様に使用するファイルをインクルードファイルと呼び,J3Iという拡張子 と付けます.
;<-------------- ここから ; LIST4 GENPRC ESC: 50 LOAD R1 0 LABEL1: OUTNUM R1 OUTCHR 13 ADD R1 1 THROW ; この命令が重要 BRA LABEL1: ; 無限ループ DELPRC %ESCAPE.J3I% ;<-------------- ここまで
また以下のファイルをEYE.J3Iとして保存して下さい. 視点またはカメラとして後ろの章で使用します.
;<-------------- ここから ; EYE.J3I GENOBJ 0 0 ; 視点用オブジェクトの生成 頂点も面も不要 CLEARA LOAD RX -2000 ; 位置の指定 20m 後方 SETPOS ; 位置と角度を視点に設定 SETEYE ; このオブジェクトが見る THROW BCOLOR 0x000 ; 背景色を黒に設定 GRAPHM ; グラフィックウインドウを開く WAIT DELOBJ ; オブジェクトの削除 DELPRC ; プロセスの削除 ;<-------------- ここまで
よく使用するプログラムを集めてライブラリとして利用できます. インクルードファイル中にインクルードファイルを記述できます. ディレクトリは %../lib/abc.j3i% のように指定できます.
物体を表示する場合は,空間に「物体」と「物体を見ている物体」が存在す る必要があります.1つのプロセスは1つの物体になることができます. したがって最低でも,最初からある1つのプロセスともう1つのプロセスが必 要になります.以下の例では最初のプロセスが空の(形のない)オブジェク ト(物体)を生成し,位置をSETPOSで設定してSETEYE命令で視点を取得しま す. 2番目のプロセス(TRIANGLE:)は3角形のオブジェクトとなります.
位置を指定するために座標を指定します. すべての物体はそれぞれ自分の向 いている方向を基準として,前がX,右がY,下がZの増加する方向です. これを座標系と呼びます.回転はZ軸回りの回転(右を向く)をヘッド回転, Y軸回りの回転(上を向く)をピッチ回転,X軸回りの回転(首を右に傾け る)をバンク回転と呼びます.
一つだけ常に存在する固定された特別な座標系があり,すべての物体の座標 系の基準となります. 北を向いて立ち,北がX,東がY,下がZとなりま す.これをワールド座標系と呼びます.【9】速度と重力で解説する重 力はワールド座標系の下方向(Zが正の方向)に働きます.
ここで使用している座標系は航空力学で使用されるNED系(X:North [前], Y:East [右],Z:Down [下] )で3次元グラフィックで使用している座標系 とは異なりますが,読み換えは簡単です. 座標値は符号付き32ビット整数の範囲(+20億〜-20億)が可能です.
あまり難しく考えず「 前がX,右がY,下がZ 」だけ覚えて下さい.
;<-------------- ここから ; LIST5 GENPRC TRIANGLE: 50 ; GENOBJ 0 0 ; 視点用オブジェクトの生成 前述のEYE.J3Iと同じ CLEARA LOAD RX -2000 ; 位置の指定 20m 後方 SETPOS ; 位置と角度を視点に設定 SETEYE ; このオブジェクトが見る THROW BCOLOR 0x000 ; 背景色を黒に設定 GRAPHM ; グラフィックウインドウを開く WAIT DELOBJ ; オブジェクトの削除 DELPRC ; プロセスの削除 TRIANGLE: ; GENOBJ 6 2 ; オブジェクトの生成 6頂点 2面 DEFPNT 0 0 500 ; 頂点0 三角形の頂点座標を登録 DEFPNT 0 500 -500 ; 頂点1 DEFPNT 0 -500 -500 ; 頂点2 DEFPNT 0 0 500 ; 頂点3 頂点0と同じ DEFPNT 0 500 -500 ; 頂点4 頂点1と同じ DEFPNT 0 -500 -500 ; 頂点5 頂点2と同じ LOAD R1 6 ; 面の色指定 LOAD R2 14 DEFPLN R1 3 0 1 2 ; 面の定義 表から見て左回りに指定 DEFPLN R2 3 5 4 3 CLEARA ; RX - RB の0クリア SETPOS ; 初期位置と角度の設定 ROTH 6000 2880 ; 6秒間で360度回転 DELOBJ ; オブジェクト STPALL ; 全プロセス終了 ;<-------------- ここまで
物体の生成には GENOBJ 命令に最大頂点数と最大面数を与えて生成します. 頂点数, 面数は実際に使用する数より多くても問題ありませんが,少ないと エラーが発生します.注意して下さい.視点には頂点も面も無いのでそれぞ れ,0を渡しています.見えなくても位置と角度の情報を持ちます.また, 後述(【7】章)するCHILD命令で,頂点も面も持つ子オブジェクトを持つこ ともできます.
実際に表示するためにはGRAPHM命令を実行してグラフィックウインドウを開 く必要があります.この命令はどのプロセスが実行してもかまいませんが, 複数のウインドウを開くことはできません.
形状の定義はDEFPNT命令でX,Y,Z座標を指定して1つずつ頂点を登録し ます.頂点番号はオブジェクト毎に0から順に付けられます(UPDTVP命令で変 更可能).レジスタに面の色を代入してDEFPLN命令でレジスタ,頂点数,頂 点番号列を指定することで面を定義します.面には表と裏があり,DEFPLN命 令1つでは裏からは不可視になります.
注)「ver.5.xx特有」
1つの平面の表と裏を表示するためには頂点を表と裏で共有させないで下さい.
LIST5では同じ頂点を2回づつ登録しています.1平面の表と裏ではなく,例
立方体の頂点のような場合には頂点の共有は問題ありません.
1つの平面の表と裏で頂点を共有すると照明に使用する法線ベクトルが計算で
きないためです.
物体の運動はROTH 6000 2880で指定しています. この場合6秒間で360度 ヘッド回転(Z軸回り)して終了します.ROTx, MOVx命令を順次実行するこ とで実行しているプロセスのオブジェクトを運動させることができます.
プロセスは生成されるとき,親プロセスのレジスタをすべて引き継ぎます. これを利用することで,同じプログラムを複数のプロセスで共有して,与え る引数により異なった動作をさせることができます.
以下の例では3つの三角形が同じプログラムで別の動きをする例です. 視点を含めて4つのプロセスが同時に動作します.
;<-------------- ここから ; LIST6 CLEARA ; 引数としてレジスタに設定 LOAD RY -1000 LOAD R4 9000 ; 時間 LOAD R5 2880 ; 回転角 GENPRC TRIANGLE: 50 ; 2つめのプロセス CLEARA ; 引数としてレジスタに設定 LOAD RY 1000 LOAD R4 6000 ; 時間 LOAD R5 5760 ; 回転角 GENPRC TRIANGLE: 50 ; 3つめのプロセス CLEARA ; 引数としてレジスタに設定 LOAD RX 1000 LOAD RB 720 LOAD R4 6000 ; 時間 LOAD R5 8640 ; 回転角 GENPRC TRIANGLE: 50 ; 4つめのプロセス %EYE.J3I% ; インクルードファイル 視点用オブジェクトの生成 TRIANGLE: ; GENOBJ 6 2 ; オブジェクトの生成 6頂点 2面 DEFPNT 0 0 500 ; 頂点0 三角形の頂点座標を登録 DEFPNT 0 500 -500 ; 頂点1 DEFPNT 0 -500 -500 ; 頂点2 DEFPNT 0 0 500 ; 頂点3 頂点0と同じ DEFPNT 0 500 -500 ; 頂点4 頂点1と同じ DEFPNT 0 -500 -500 ; 頂点5 頂点2と同じ LOAD R1 13 ; 面の色指定 LOAD R2 15 DEFPLN R1 3 0 1 2 ; 面の定義 表から見て左回りに指定 DEFPLN R2 3 5 4 3 SETPOS ; 初期位置と角度の設定 ROTH R4 R5 DELOBJ ; オブジェクトの削除 STPALL ; 全プロセス終了 ;<-------------- ここまで
LIST6のTRIANGLE:は回転後,直ちにオブジェクトを削除し全プロセス終了と しているため,2つめのプロセスは9秒間回転する指定であっても,最初に STPALLを実行したプロセス(6秒後)によって終了させられます.
STPALLの代わりに DELPRC命令を置くと順次プロセスが終了して物体が消え, 最後のプロセスが終了した時点で視点プロセスのみが残ります.何も存在しな いグラフィックウンドウが残ります. 終了には QUITボタンをクリックして下 さい. ROTH命令の後ろにWAIT命令を挿入した場合も,別のプロセスからメッ セージが送られるかQUITボタンをクリックするまで一時停止します.
例えば人体のような関節を持つ物体を表現するためには階層構造を持つオブ ジェクトが必要になります. 腰をひねれば肩も腕も頭も動きます.つまり 肩も腕も首の関節も動かしていないにもかかわらず,地面に対してその位置 も角度も変化します.これは腰の座標系(フレームと呼ぶ場合もある)上に 肩の座標系が固定され,肩の座標系に頭の座標系が固定され,という具合に 親子関係を形作っています.
以下の例では同じ形の3角形の下側の頂点が関節となっています.関節は物 体の原点(0, 0, 0)の位置に来るように形状を定義すると,回転命令を普通 に使用すれば関節の動きとして表現できます.
とにかく座標系などを気にしないでLIST7を書き換えて実際に色々試してみ て下さい. 文章で読むほど難しくはないと思います.
;<-------------- ここから ; LIST7 GENPRC PARENT: 50 ; %EYE.J3I% ; インクルードファイル 視点用オブジェクトの生成 PARENT: ; BCOLOR 0x186 GENOBJ 6 2 ; オブジェクトの生成 6頂点 2面 CALL def_shape: LOAD RZ 1200 SETPOS ; 初期位置と角度の設定 CHILD Child: 50 6 2 ; 子オブジェクト CALL def_move: STPALL ; 全プロセス終了 Child: ; CALL def_shape: LOAD RZ -400 SETPOS ; 初期位置と角度の設定 CHILD GrandChild: 50 6 2 CALL def_move: STPALL ; 全プロセス終了 GrandChild: ; CALL def_shape: LOAD RZ -400 SETPOS ; 初期位置と角度の設定 CHILD GrandChild2: 50 6 2 ; このプロセスは CHILD GrandChild3: 50 6 2 ; 子が2人 CALL def_move: STPALL ; 全プロセス終了 GrandChild2: ; CALL def_shape: LOAD RZ -400 LOAD RY -100 SETPOS ; 初期位置と角度の設定 CHILD GrandChild3: 50 6 2 CALL def_move: STPALL ; 全プロセス終了 GrandChild3: ; CALL def_shape: LOAD RZ -500 LOAD RY 100 LOAD RH 720 SETPOS ; 初期位置と角度の設定 CALL def_move: STPALL ; 全プロセス終了 def_move: ; すべての物体の運動を定義 LOAD RL 15 dm: ROTH 2000 620 ; 2秒間で回転 ROTP 1000 360 ROTP 1500 -360 ROTH 1000 620 ; 2秒間で回転 ROTB 1500 360 ROTB 1000 -360 LOOP dm: DELOBJ RETURN def_shape: ; すべての物体の形状を定義 DEFPNT 0 0 0 ; 頂点0 三角形の頂点座標を登録 DEFPNT 0 180 -400 ; 頂点1 DEFPNT 0 -180 -400 ; 頂点2 DEFPNT 0 0 0 ; 頂点3 頂点0と同じ DEFPNT 0 180 -400 ; 頂点4 頂点1と同じ DEFPNT 0 -180 -400 ; 頂点5 頂点2と同じ LOAD R1 11 ; 面の色指定 LOAD R2 13 DEFPLN R1 3 0 1 2 ; 面の定義 表から見て左回りに指定 DEFPLN R2 3 5 4 3 CLEARA ; RX - RB の0クリア RETURN ;<-------------- ここまで
LIST7の例では6関節の物体が画面中央で2分間運動します.どの関節もまっ たく同じ動き(def_move:)をしていますが,全体としては,かなり複雑な動き をしていると思いませんか? それぞれの物体の形と動きを別に定義すれば, 色々試すことができると思います.
階層型オブジェクトを実現する命令は1つだけ「CHILD」命令です. この命令は「GENPRC」と「GENOBJ」を加えた命令です.ただし「生成される オブジェクトがCHILD命令を実行したプロセスのオブジェクト(の座標系)に 属している」という点が異なります.削除は DELPRCとDELOBJを使用します.
表記法は以下の形式です.
CHILD スタート位置のラベル メモリサイズ 頂点数 ポリゴン数 ←─────GENPRC───────→ ←──GENOBJ──→
親オブジェクトが先に消滅した場合は,その子供たちはそれぞれ空間内で独 立したオブジェクトになります.
複数のプロセスが独立して運動可能であることは,これまで見てきました. さて,相互作用がある場合,例えば弾丸が「おまえに命中したぞ!」と当っ た相手に伝えて,それなりの行動を期待する時,プロセスがどのように意志 疎通を行えばいいのでしょうか? これまでに何度も出てきた STPALL がヒン トになります.STPALLは存在する他のプロセスに対して「皆さん,もう終わ りだよ!後始末をして撤収!」とメッセージ(シグナルともいう)を放送し ています.これを特定の相手(プロセス)に特定のメッセージを送ることが できれば目的は達成できます.
入力キーコードをプロセス2に送るプロセスと受信したメッセージを表示する プロセスの例です.
;<-------------- ここから ; LIST8 GENPRC PROC2: 50 LOAD RQ 1 key: INKEY R1 CMP R1 0 BEQ next: SEND 2 R1 next: THROW BRA key: DELPRC PROC2: LOAD RQ 2 loop: WAIT RECEIV R1 OUTNUM R1 OUTCHR 13 CMP R1 0x1B BEQ exit: BRA loop: exit: STPALL ;<-------------- ここまで
ここで LOAD RQ 1 はプロセスのIDを1に設定する命令です.RQレジスタ に設定されている値がプロセスの識別番号になります.プロセス生成直後は すべてのレジスタがプロセスを生成したプロセスから引き継がれるためプロ セスを特定するためにはRQを再設定する必要があります.プロセスのIDが 重複する場合はシステムが管理しているプロセス管理番号の最も若いプロセ スにメッセージが渡されます.
同時に複数のプロセスが1つのプロセスに対してメッセージを送る場合もあ ります.この場合は最も大きい値のメッセージが優先されます.またメッセ ージの送出元のプロセスを識別する事はできません.プロセス間で同期しな がら複雑な動作をする場合は共有メモリを使用する必要があるでしょう. 複数のプロセス間の同期は難しい問題です.はじめはプロセスが1対1の場 合から実験して見てください.
プロセス管理番号はDISTNC命令でのみ取得できます.同一のプロセス番号を 持つプロセスを識別できます.プロセス管理番号を指定してメッセージを送 るにはSENDTO命令を使用します.同一のプロセス番号を使用する事は混乱の 元となります.なるべく避けてください.
物体が勝手に運動する例です.以下のリストでは1つの立方体が速度を持ち, 重力の影響を受けながら壁にあたると反転して跳ね回ります.衝突は立方体 の重心座標で判定していますので床と後ろの壁とのオブジェクト間の衝突判 定はしていません.床には立方体の影が動いています.
;<-------------- ここから ; LIST9 ; 立方体の弾性衝突 物体の重力,速度属性のデモ GENPRC ESC: 50 ; ESCキーで終了させるプロセス GENOBJ 0 0 ; 視点用オブジェクトの生成 CLEARA LOAD RX -2000 ; 位置の指定 20m 後方 LOAD RZ -1000 ; 位置の指定 10m 上方 SETPOS ; 位置と角度をオブジェクトに設定 SETEYE ; 視点の設定 GENPRC CUBE0: 50 ; 跳ね回る立方体のプロセス GENPRC SHADOW: 50 ; 立方体の影となるプロセス GENPRC FLOOR: 50 ; 床 動かない GENPRC WALL: 50 ; 壁 動かない THROW BCOLOR 0x100 ; 背景色を黒に設定 GRAPHM ; グラフィックモードに変更 WAIT DELOBJ ; オブジェクトの削除 ; 立方体のプロセス 不可視 位置をコントロール CUBE0: LOAD RQ 777 GENOBJ 0 0 CHILD CUBE1: 50 8 6 CLEARA ; RX - RB の0クリア LOAD RZ -2000 SETPOS ; 初期位置と角度の設定 LOAD R1 980000 ; 重力加速度 = 980cm/s^2 x 1000 SETGRV R1 ; 重力加速度の設定 CLEARA LOAD RX 170000 LOAD RY 250000 SETVEL ; 慣性速度を設定 Loop: CALL BOUNCE: ; 立方体の跳ね返り処理用手続きを呼ぶ THROW BRA Loop: STPALL ; 全プロセス終了 ; 立方体のプロセス 可視部分 CUBE1: LOAD RQ 666 ; GENOBJ 8 6 ; オブジェクトの生成 SETREF 50 ; シェイディングの明るい方50%使用 DEFPNT 150 150 -150 ; 頂点0 立方体の頂点座標を登録 DEFPNT -150 150 -150 ; 頂点1 DEFPNT -150 -150 -150 ; 頂点2 DEFPNT 150 -150 -150 ; 頂点3 DEFPNT 150 150 150 ; 頂点4 DEFPNT -150 150 150 ; 頂点5 DEFPNT -150 -150 150 ; 頂点6 DEFPNT 150 -150 150 ; 頂点7 LOAD R1 14 ; 面の色指定 DEFPLN R1 4 0 1 5 4 ; 面の設定 DEFPLN R1 4 3 7 6 2 DEFPLN R1 4 1 2 6 5 DEFPLN R1 4 0 4 7 3 DEFPLN R1 4 4 5 6 7 DEFPLN R1 4 0 3 2 1 Loop2: ROTH 3000 1440 ; 親座標系内で3秒間で180度回転するだけ BRA Loop2: DELOBJ DELPRC ; 立方体の跳ね返り処理用サブルーチン BOUNCE: GETPOS ; 現在位置を取得 LOAD RH RX ; RH := position.x LOAD RP RY ; RP := position.y LOAD RB RZ ; RB := position.z LOAD R1 0 ; Change Flag GETWVL ; 現在の速度を取得 CMP RH 850 ; 後ろの壁への衝突チェック BMI B1: AND RX RX BMI B1: NEG RX RX ; if pos.x > 850 then vx = -vx LOAD R1 1 ; Change := True B1: CMP RH -850 ; 前の壁への衝突チェック BPL B2: AND RX RX BPL B2: NEG RX RX ; if pos.x > 850 then vx = -vx LOAD R1 1 ; Change := True B2: CMP RP 850 ; 右の壁への衝突チェック BMI B3: AND RY RY BMI B3: NEG RY RY ; if pos.y > 850 then vy = -vy LOAD R1 1 ; Change := True B3: CMP RP -850 ; 左の壁への衝突チェック BPL B4: AND RY RY BPL B4: NEG RY RY ; if pos.y < -850 then vy = -vy LOAD R1 1 ; Change := True B4: CMP RB -150 ; 床への衝突チェック BMI B5: AND RZ RZ BMI B5: NEG RZ RZ ; if pos.z > -150 then vz = -vz LOAD R1 1 ; Change := True B5: CMP R1 1 ; 運動の方向に変化があれば速度を再設定 BNE B6: NOTE 9 50 127 SETWVL B6: RETURN ; リターン ; 影のプロセス SHADOW: GENOBJ 4 2 ; オブジェクトの生成 DEFPNT 150 150 0 ; 頂点0 正方形の頂点座標を登録 DEFPNT -150 150 0 ; 頂点1 DEFPNT -150 -150 0 ; 頂点2 DEFPNT 150 -150 0 ; 頂点3 LOAD R1 16 ; 面の色指定 常に黒 DEFPLN R1 4 3 2 1 0 SH1: PRCPOS 777 ; 立方体の位置を取得 LOAD RZ -5 ; 高さを床面の少し上に設定 PUSH RX ; 立方体の位置を保存 PUSH RY PUSH RZ PRCPOS 666 ; 立方体の角度を取得 POP RZ ; 立方体の位置を復帰 POP RY POP RX SETPOS ; 初期位置と角度の設定 THROW BRA SH1: WAIT STPALL ; 全プロセス終了 ; 床のプロセス FLOOR: GENOBJ 4 2 ; オブジェクトの生成 LOAD R1 40000 PRIOR R1 DEFPNT 1000 1000 0 ; 頂点0 正方形の頂点座標を登録 DEFPNT -1000 1000 0 ; 頂点1 DEFPNT -1000 -1000 0 ; 頂点2 DEFPNT 1000 -1000 0 ; 頂点3 LOAD R1 28 ; 面の色指定 DEFPLN R1 4 3 2 1 0 CLEARA ; RX - RB の0クリア SETPOS ; 初期位置と角度の設定 WAIT ; 静止 STPALL ; 全プロセス終了 ; 後壁の登録 WALL: GENOBJ 4 2 ; オブジェクトの生成 DEFPNT 1000 1000 0 ; 頂点0 DEFPNT 1000 1000 -2000 ; 頂点1 DEFPNT 1000 -1000 -2000 ; 頂点2 DEFPNT 1000 -1000 0 ; 頂点3 LOAD R1 13 ; 面の色指定 DEFPLN R1 4 0 1 2 3 CLEARA ; RX - RB の0クリア SETPOS ; 初期位置と角度の設定 WAIT ; 静止 STPALL ; 全プロセス終了 %ESCAPE.J3I% ;<-------------- ここまで
この例では7個のプロセスが存在しますが,ESCキーチェックと立方体の位置 と立方体と影のプロセスが動いているだけです.他のプロセスは終了を待っ ています.立方体の位置プロセスは自分の座標をチェックして範囲外なら方 向を反転しているだけです. 立方体の形状プロセスは単にヘッド回転して いるだけです.影のプロセスは立方体の位置を見て,さらに立方体の形状か ら角度を取得して自分を同じ位置の高さ0に置くことを繰り返しているだけで す. 重力,加速度,速度の効果はシステムが画面表示する前に自動的に処理 します.
ここで立方体のプロセスを2つに分けている理由は,立方体がどのように回 転しても地面との角度を固定するためです.自分が回転してしまうと運動の 方向の前後左右が回転してしまうためです.座標が回転しないプロセスの子 オブジェクトとして回転する立方体の形状オブジェクトがあります.
重力を有効にするには,重力の効果が必要なオブジェクト毎に
LOAD R1 980000 ; 重力加速度 980cm/s^2 x 1000 SETGRV R1
の様に設定します. SETGRV に渡す値は16ビットの整数またはレジスタで指 定します. 980000は16ビット整数の範囲にないため,レジスタで渡していま す. これは地球上の重力加速度ですが,2322600を使用すれば木星赤道上の 運動をシミュレートできます.ちなみに月面では166600です.
重力,速度,加速度は1000倍した値を与える必要があります.詳細はリファ レンスマニュアルを参照して下さい. 距離の単位としてcmを使用しています が,プログラム全体で合わせれば距離の単位は任意です.
LIST9の例では一辺3mの立方体を重心が20mの位置から落として床で跳ね返り ます.つまり18.5m落ちて跳ね返り,20mの位置まで上昇して落ちはじめます. 計算上1.943秒で18.5m落ちるはずです.マシンの速さにかかわらず同じ速度 になると思います.試して見てください.
跳ね返り処理中 NOTE 9 50 127 の行でMIDIの9チャンネルから音を出し ています.パーカション系の音が出ているはずです.
もっともらしいフライトシミュレータを作成する場合は重力の影響を表現す る必要があると思います.バンクして水平旋回等を表現できます.
形状をプログラム作成時に定義しておくのではなく,実行時にプログラムに 生成させることができます. 以下の例は3角柱を生成するサブルーチンを 呼出しています.
;<-------------- ここから ; LIST10 GENPRC TRI: 50 ; 3角柱のプロセスを生成 %EYE.J3I% ; インクルードファイル 視点用オブジェクトの生成 TRI: GENOBJ 16 10 ; オブジェクトの生成 16頂点 10面 LOAD RH 500 LOAD R1 400 LOAD R2 400 LOAD R3 12 CALL Bar33: ; 面と頂点の生成 CLEARA LOAD RP 720 SETPOS ; 位置の設定 LOAD RP 1720 LOAD RB 2720 MOVALL 20000 STPALL ; 全プロセス終了 ;--------------------------------------------------- ; 3角柱 ; L1 L1 は長さ ; +--------+ ; R1 *origin |R2 → X ; +--------+ ; Rx は正3角形の中心から頂点までの距離(30000以下のこと) ; RH:L1 ; R1:R1, R2:R2, R3:COLOR ; RX,RY,RZ:破壊 RP,RB,R4,R5,R6:保存 ; 頂点 6 面 5 ;--------------------------------------------------- Bar33: LOAD RX 0 CALL DEF_TRIPOINT: ADD RX RH LOAD R1 R2 CALL DEF_TRIPOINT: DEFPLN R3 3 2 1 0 DEFPLN R3 3 3 4 5 DEFPLN R3 4 0 1 4 3 ; 3 DEFPLN R3 4 1 2 5 4 ; 0 DEFPLN R3 4 2 0 3 5 ; 2 1 ; 5 4 RETURN ;--------------------------------------------------- ; 3角形の頂点の定義 ; R = 正3角形の中心から頂点までの距離(30000以下のこと) ; P = SQRT(R*R*3)/2 ; Q = R/2 o→y ; Z Y ↓ 0 ; 0 -R 0 z / \ ; 1 Q P / . \ ; 2 Q -P 2 ------- 1 ; ENTER R1 = R, RX = X座標, それ以外は保存される ;--------------------------------------------------- DEF_TRIPOINT: ; 頂点座標を計算で求める PUSHG PUSHA LOAD R2 R1 ; R1 = R MUL R2 R2 MUL R2 3 SQRT R2 R2 ; R2 = P = SQRT(R*R*3) DIV R2 2 LOAD R3 R1 DIV R3 2 ; R3 = Q = R/2 NEG R4 R1 ; -R NEG R5 R2 ; -P NEG R6 R3 ; -Q LOAD RZ R4 ; -R LOAD RY 0 POINT ; 頂点の登録(0) LOAD RZ R3 ; Q LOAD RY R2 ; P POINT ; 頂点の登録(1) LOAD RZ R3 ; Q LOAD RY R5 ; -P POINT ; 頂点の登録(2) POPA POPG RETURN ;<-------------- ここまで
さらに詳細な例は REVOLUTION.J3Iを参照して下さい.任意の回転体を生成 することができます.
[TOP]例えば腕を曲げる場合には肘の皮膚は伸び縮みします.動物の体は骨と それを取り巻く筋肉,そして皮膚でできています.これまでの例では 多角形の大きさは定義したまま変化することはありませんでした.
階層構造の物体(【7】章)では親オブジェクトが存在して頂点を持つ場合 には,多角形の頂点番号に負の数を使用して親オブジェクトの頂点を指定 する事ができます.独立して運動する物体間に多角形(スキン)を張る事が できます.こうして,例えば肘の関節に伸び縮みする皮膚で腕を接続しま す.負の数を使用して親オブジェクトの頂点を指定するため,親の0番頂点 は指定できないことに注意して下さい.
;<-------------- ここから ; LIST11 GENPRC PARENT: 50 ; 親のプロセスを生成 %EYE.J3I% ; インクルードファイル 視点用オブジェクトの生成 PARENT: GENOBJ 8 5 ; 親オブジェクトの生成 8頂点 5面 CHILD CHILD1: 50 8 13 ; 子オブジェクトの生成 8頂点13面 DEFPNT 200 200 0 ; 頂点0 DEFPNT -200 200 0 ; 頂点1 3 ---------- 0 z=0 DEFPNT -200 -200 0 ; 頂点2 | | DEFPNT 200 -200 0 ; 頂点3 | 7 4 | z=-2000 DEFPNT 200 200 -1000; 頂点4 | 6 5 | DEFPNT -200 200 -1000; 頂点5 | | DEFPNT -200 -200 -1000; 頂点6 2 -----------1 DEFPNT 200 -200 -1000; 頂点7 LOAD R1 15 ; 面の色指定 DEFPLN R1 4 0 1 2 3; 面の定義 表から見て左回りに指定 DEFPLN R1 4 0 3 7 4 DEFPLN R1 4 0 4 5 1 DEFPLN R1 4 5 6 2 1 DEFPLN R1 4 6 7 3 2 CLEARA LOAD RZ 1000 SETPOS ; 位置の設定 pa1: ROTH 20000 2880 ROTH 20000 -2880 BRA pa1: STPALL ; 全プロセス終了 CHILD1: DEFPNT 200 200 -300 ; 頂点0 DEFPNT -200 200 -300 ; 頂点1 3 ---------- 0 z=-1000 DEFPNT -200 -200 -300 ; 頂点2 | | DEFPNT 200 -200 -300 ; 頂点3 | 7 4 | z=-2000 DEFPNT 200 200 -1000; 頂点4 | 6 5 | DEFPNT -200 200 -1000; 頂点5 | | DEFPNT -200 -200 -1000; 頂点6 2 -----------1 DEFPNT 200 -200 -1000; 頂点7 LOAD R1 11 ; 面の色指定 DEFPLN R1 4 7 6 5 4; 面の定義 表から見て左回りに指定 DEFPLN R1 4 0 3 7 4 DEFPLN R1 4 0 4 5 1 DEFPLN R1 4 5 6 2 1 DEFPLN R1 4 6 7 3 2 ; 関節部の面を登録 LOAD R1 4 ; 面の色指定 DEFPLN R1 3 -4 3 0 ; ねじれる可能性があるため三角形を貼る DEFPLN R1 3 -4 -7 3 ; -7 ---------- -4 親の頂点 DEFPLN R1 3 -4 0 1 ; | | DEFPLN R1 3 -5 -4 1 ; | 3 0 | 子の頂点 DEFPLN R1 3 1 2 -6 ; | 2 1 | DEFPLN R1 3 -6 -5 1 ; | | DEFPLN R1 3 2 3 -7 ; -6 ---------- -5 DEFPLN R1 3 -7 -6 2 CLEARA LOAD RZ -1300 SETPOS ; 位置の設定 ch1: ROTP 3000 720 ROTP 6000 -1440 ROTP 3000 720 ROTH 3000 360 ROTH 6000 -720 ROTH 3000 360 BRA ch1: STPALL ; 全プロセス終了 ;<-------------- ここまで
この例を実行して,赤い面がスキンにあたります.伸び縮みして変形している ことが分かります.ここでは親物体1つと子物体1つですが,親1つに複数の 子を持つ場合も同様に各々の子が親の頂点を指定できます.子は常に親の頂点 だけ参照することができます.
例えばビルが立ち並ぶ世界を作成するとします.1つ1つのビルは地面に固定さ れ,動くことはありません.色々なサイズの直方体を登録する必要があります. 指定したサイズの直方体の頂点を計算して登録するプログラムもできますが. 高さ,幅,奥行きを拡大縮小することができれば,1つの大きさの立方体を登 録するルーチンを作成して,どのビルのプロセスもそのルーチンを呼び出した 後,高さ,幅,奥行きの拡大率を設定するだけで大きさの異なる直方体を作成 することができます.
物体が属している局所座標系を拡大縮小することによって,登録済みの物体の 形状を後から変更することができます.親子関係にある物体の場合も1個所だ け変更することができます.例えば,足が徐々に伸びるなどの表現ができるよ うになります.
SETSCL, GETSCL, SCALE命令は物体の所属する座標系の縮尺を設定,取得,変 更することができます.
以下のサンプルは簡単な人型の物体のアニメーションですが,ここでは特に 局所座標系のスケールの変更のデモンストレーションのために,すべて一辺の 長さが100の立方体のみで作成してみました.
J3Wには現在モデラーが用意されていませんが,モデラーを使用しなくても, ちょっとした3DCGのアニメーションを作成できる例としたつもりです.
;<-------------- ここから ; LIST12 GENPRC BODY: 50 ; 親のプロセスを生成 ; デフォルトプロセスは視点オブジェクトになる GENOBJ 0 0 ; 視点用オブジェクトの生成 頂点も面も不要 CLEARA LOAD RX -1000 ; 視点の位置の指定 SETPOS ; 位置と角度を視点に設定 SETEYE ; このオブジェクトが見る THROW BCOLOR 0x84A ; 背景色を設定 GRAPHM ; グラフィックウインドウを開く WAIT DELOBJ ; オブジェクトの削除 DELPRC ; プロセスの削除 BODY: GENOBJ 8 6 ; 親オブジェクトの生成 胴体 CALL CUBE100: CHILD R_ARM: 50 8 6 ; 子オブジェクトの生成 右腕 CHILD L_ARM: 50 8 6 ; 子オブジェクトの生成 左腕 CHILD R_THIGH: 50 8 6 ; 子オブジェクトの生成 右大腿部 CHILD L_THIGH: 50 8 6 ; 子オブジェクトの生成 左大腿部 CHILD HEAD: 50 8 6 ; 子オブジェクトの生成 頭 LOAD RX 3000 ; X軸の縮尺 LOAD RY 2000 ; Y軸の縮尺 LOAD RZ 1000 ; Z軸の縮尺 SETSCL ; 縮尺の設定 CLEARA LOAD RP 720 SETPOS ; 位置の設定 bd1: ROTB 3000 720 ; 全体の動作の定義 ROTB 6000 -1440 ; X軸まわりの回転 ROTB 3000 720 ROTH 3000 360 ; Z軸まわりの回転 ROTH 6000 -720 ROTH 3000 360 LOAD RX 2000 ; X軸の縮尺 LOAD RY 2000 ; Y軸の縮尺 LOAD RZ 2000 ; Z軸の縮尺 SCALE 4000 ; 大きくなる LOAD RX 500 ; X軸の縮尺 LOAD RY 500 ; Y軸の縮尺 LOAD RZ 500 ; Z軸の縮尺 SCALE 5000 ; 小さくなる BRA bd1: ; ずっと繰り返し STPALL ; 全プロセス終了(一応入れておく) HEAD: ; 頭 CALL CUBE100: ; 立方体の形状を設定 CLEARA LOAD RX 120 SETPOS ; 位置の設定 hd1: ; 頭部の動作 LOAD RX 2000 ; X軸の縮尺 LOAD RY 2000 ; Y軸の縮尺 LOAD RZ 2000 ; Z軸の縮尺 SCALE 5000 ; 大きくなる LOAD RX 500 ; X軸の縮尺 LOAD RY 500 ; Y軸の縮尺 LOAD RZ 500 ; Z軸の縮尺 SCALE 5000 ; 小さくなる BRA hd1: ; ずっと繰り返し WAIT ; この命令は無意味 STPALL ; 全プロセス終了(一応入れておく) R_ARM: ; 右腕 CHILD R_FARM: 50 8 6 ; 子オブジェクトの生成 右腕 CALL CUBE100: ; 立方体の形状を設定 LOAD RX 1500 ; X軸の縮尺 LOAD RY 700 ; Y軸の縮尺 LOAD RZ 700 ; Z軸の縮尺 SETSCL ; 縮尺の設定 CLEARA LOAD RX 75 ; 親座標系で測った関節の位置 LOAD RY 75 LOAD RH 720 SETPOS ; 位置の設定 ra1: ROTP 2000 720 ROTP 4000 -1440 ROTP 2000 720 BRA ra1: ; ずっと繰り返し WAIT ; この命令は無意味 STPALL ; 全プロセス終了(一応入れておく) L_ARM: ; 左腕 CHILD L_FARM: 50 8 6 ; 子オブジェクトの生成 右腕 CALL CUBE100: ; 立方体の形状を設定 LOAD RX 1500 ; X軸の縮尺 LOAD RY 700 ; Y軸の縮尺 LOAD RZ 700 ; Z軸の縮尺 SETSCL ; 縮尺の設定 CLEARA LOAD RX 75 ; 親座標系で測った関節の位置 LOAD RY -75 LOAD RH -720 SETPOS ; 位置の設定 la1: ROTP 2000 720 ; 左腕の動作 ROTP 4000 -1440 ROTP 2000 720 BRA la1: ; ずっと繰り返し WAIT ; この命令は無意味 STPALL ; 全プロセス終了(一応入れておく) R_FARM: ; 右前腕 CALL CUBE100: ; 立方体の形状を設定 LOAD RX 1500 ; X軸の縮尺 LOAD RY 800 ; Y軸の縮尺 LOAD RZ 800 ; Z軸の縮尺 SETSCL ; 縮尺の設定 CLEARA LOAD RX 120 SETPOS ; 位置の設定 rfa1: ROTP 2500 360 ; 前腕部の動作 ROTP 2500 -360 BRA rfa1: ; ずっと繰り返し WAIT ; この命令は無意味 STPALL ; 全プロセス終了(一応入れておく) L_FARM: ; 左前腕 CALL CUBE100: ; 立方体の形状を設定 LOAD RX 1500 ; X軸の縮尺 LOAD RY 800 ; Y軸の縮尺 LOAD RZ 800 ; Z軸の縮尺 SETSCL ; 縮尺の設定 CLEARA LOAD RX 120 SETPOS ; 位置の設定 lfa1: ROTP 2500 360 ; 前腕部の動作 ROTP 2500 -360 BRA lfa1: ; ずっと繰り返し WAIT ; この命令は無意味 STPALL ; 全プロセス終了(一応入れておく) R_THIGH: ; 右大腿部 CHILD R_LEG: 50 8 6 ; 子オブジェクトの生成 右腕 CALL CUBE100: ; 立方体の形状を設定 LOAD RX 2000 ; X軸の縮尺 LOAD RY 700 ; Y軸の縮尺 LOAD RZ 700 ; Z軸の縮尺 SETSCL ; 縮尺の設定 CLEARA LOAD RX -10 ; 親座標系で測った関節の位置 LOAD RY 25 LOAD RH -1440 SETPOS ; 位置の設定 WAIT ; ここでは何も動作していない STPALL ; 全プロセス終了(一応入れておく) L_THIGH: ; 左大腿部 CHILD L_LEG: 50 8 6 ; 子オブジェクトの生成 右腕 CALL CUBE100: ; 立方体の形状を設定 LOAD RX 2000 ; X軸の縮尺 LOAD RY 700 ; Y軸の縮尺 LOAD RZ 700 ; Z軸の縮尺 SETSCL ; 縮尺の設定 CLEARA LOAD RX -10 ; 親座標系で測った関節の位置 LOAD RY -25 LOAD RH -1440 SETPOS ; 位置の設定 WAIT ; ここでは何も動作していない STPALL ; 全プロセス終了(一応入れておく) R_LEG: ; 右足 CALL CUBE100: ; 立方体の形状を設定 LOAD RX 2000 ; X軸の縮尺 LOAD RY 800 ; Y軸の縮尺 LOAD RZ 800 ; Z軸の縮尺 SETSCL ; 縮尺の設定 CLEARA LOAD RX 120 SETPOS ; 位置の設定 WAIT ; ここでは何も動作していない STPALL ; 全プロセス終了(一応入れておく) L_LEG: ; 左足 CALL CUBE100: ; 立方体の形状を設定 LOAD RX 2000 ; X軸の縮尺 LOAD RY 800 ; Y軸の縮尺 LOAD RZ 800 ; Z軸の縮尺 SETSCL ; 縮尺の設定 CLEARA LOAD RX 120 SETPOS ; 位置の設定 WAIT ; ここでは何も動作していない STPALL ; 全プロセス終了(一応入れておく) CUBE100: ; 8頂点6面の立方体 DEFPNT 0 50 -50 ; 頂点0 奥 DEFPNT 0 50 50 ; 頂点1 7 ---------- 4 x=100 DEFPNT 0 -50 50 ; 頂点2 | | DEFPNT 0 -50 -50 ; 頂点3 | 3 ---- 0 | x=0 DEFPNT 100 50 -50 ; 頂点4 | 2 手前 1 | DEFPNT 100 50 50 ; 頂点5 | | DEFPNT 100 -50 50 ; 頂点6 6 -----------5 DEFPNT 100 -50 -50 ; 頂点7 LOAD R1 15 ; 面の色指定 ( テキスト参照 ) DEFPLN R1 4 0 3 2 1; 面の定義 表から見て左回りに指定 DEFPLN R1 4 4 0 1 5 DEFPLN R1 4 1 2 6 5 DEFPLN R1 4 2 3 7 6 DEFPLN R1 4 0 4 7 3 DEFPLN R1 4 4 5 6 7 RETURN ;<-------------- ここまで
例としてはチョット長くなってしまいました.画面を見ながら修正していくと, ドンドン長くなってしまいます.上の例では足に動きを付けていません.
腕の部分と同様に動きを設定することができます.さらにキー入力をチェック して各プロセスにメッセージを送るプロセスを追加し,メッセージを判断して 各関節の動作を決定するように変更すれば格闘ゲームも可能でしょう.
また CUBE100:中
LOAD R1 15 ; 面の色指定
の行を削除して,CALL CUBE100: と呼び出している部分を
LOAD R1 1 ; パーツの色指定 CALL CUBE100: ; 一辺の長さ100の立方体の登録
のように変更すると,各パーツの色を独立に設定できるようになります.
グラフィックウィンドウに文字と線分を重ね書きをすることができます. フライトシミュレータのヘッドアップディスプレイの表示のように, 例えば物体の位置,角度,経過時間などをリアルタイムに表示する場合に 使用できます.この2次元の文字と線分は一旦書き込むと常に表示されます.
文字の描画は GRCOLで表示色を設定し,GRCSRで位置を設定します.
この位置に設定は左上隅が 0 右下隅が 1999の1次元で指定します.
2次元で指定できないので少し面倒ですが (80*行)+桁 で計算できます.
GRCSRで位置を指定した後は,GRSTR(文字列),GRNUM(数値),GRCHR(文字)は
書き込み位置は更新されて続けて書き込まれます.
ウィンドウに直接描画する線分はウィンドウのピクセル位置(640x480)
で位置を指定します.この線分は登録制となっていて,0番から99番の
100本までです.登録された線分は位置を書き換えるか,GRLINCで
消去されるまで表示されたままになります.
線分を表示する場合は以下の様にレジスタに設定したのち,GRLINE命令
を実行します.
RX | x0 始点 |
RY | y0 |
RZ | 色 |
RH | x1 終点 |
RP | y1 |
RB | ライン番号(0 - 99) |
以下の例では 3次元の回転する3角形に,0.5秒ごとに表示される文字列と 高速に書き換わる2次元の線分が重ね書きされて1分間後に終了します.
;<-------------- ここから ; LIST13 GENPRC TRIANGLE: 50 ; 3角形の物体のプロセス GENPRC LINEDEMO: 50 ; 2次元の線分表示 GENPRC STR_DEMO: 50 ; 文字表示プロセス GENOBJ 0 0 ; 視点用オブジェクトの生成 CLEARA LOAD RX -1000 ; 位置の指定 SETPOS ; 位置と角度を視点に設定 SETEYE ; このオブジェクトが見る THROW BCOLOR 0x000 ; 背景色を黒に設定 GRAPHM ; グラフィックウインドウを開く WAIT DELOBJ ; オブジェクトの削除 DELPRC ; プロセスの削除 TRIANGLE: ; GENOBJ 6 2 ; オブジェクトの生成 6頂点 2面 DEFPNT 0 0 500 ; 頂点0 三角形の頂点座標を登録 DEFPNT 0 500 -500 ; 頂点1 DEFPNT 0 -500 -500 ; 頂点2 DEFPNT 0 0 500 ; 頂点3 頂点0と同じ DEFPNT 0 500 -500 ; 頂点4 頂点1と同じ DEFPNT 0 -500 -500 ; 頂点5 頂点2と同じ LOAD R1 5 ; 面の色指定 LOAD R2 14 DEFPLN R1 3 0 1 2 ; 面の定義 表から見て左回りに指定 DEFPLN R2 3 5 4 3 CLEARA ; RX - RB の0クリア SETPOS ; 初期位置と角度の設定 ROTH 60000 28800 ; 60秒間で10回転 DELOBJ ; オブジェクト STPALL ; 全プロセス終了 ; --------------------------------------------------- ; 0.5秒ごとに文字列を表示するプロセス ; --------------------------------------------------- STR_DEMO: GRCOL 7 GRCLR ; 画面上の文字をすべて消去 LOAD RL 30 sd1: LOAD RB RL CALL RandomStr: NOOP 500 ; 0.5秒待つ 待たない場合はTHROWを置く LOOP sd1: BRA STR_DEMO: ; 30回表示したら最初から STPALL ; 意味はないがプロセスの区切りを明確に ; --------------------------------------------------- ; ランダムな位置に文字列を表示 ; --------------------------------------------------- RandomStr: LOAD R2 80 RANDOM RX R2 ; 0 - 79 の乱数 LOAD R2 25 RANDOM RY R2 ; 0 - 24 の乱数 MUL RY 80 ADD RX RY ; RX = (80 * y) + x で表示位置を計算 GRCSR RX ; 表示位置を設定 GRSTR " NUMBER = " ; 文字列の表示 LOAD R2 100000 RANDOM RX R2 ; 0 - 99999 の乱数 GRNUM RX ; 数値の表示 GRCHR ' ' ; 続けて空白を1つ書き込み RETURN ; --------------------------------------------------- ; ライン表示プロセス 30本の線分を書き換え続ける ; --------------------------------------------------- LINEDEMO: LOAD RL 30 ld1: LOAD RB RL ; 1番から30番の線分を順に書きかえる CALL RandomLine: ; THROW ; ラインを1フレーム当たり1本表示する場合 LOOP ld1: THROW ; 1フレーム当たり30本表示する場合はここ ; WAIT ; ここのコメントを取ると線は書きかえられない BRA LINEDEMO: STPALL ; 意味はないがプロセスの区切りを明確に ; --------------------------------------------------- ; ランダムな位置にラインを表示 ; --------------------------------------------------- RandomLine: LOAD R2 16 RANDOM RZ R2 ; color LOAD R2 640 RANDOM RX R2 ; x0 RANDOM RH R2 ; x1 LOAD R2 480 RANDOM RY R2 ; y0 RANDOM RP R2 ; y1 GRLINE RETURN ;<-------------- ここまで
この例では,LINEDEMO: と STR_DEMO: は無限ループとなっています. ループ中に THROW, NOOP, WAIT のうちの1つは必須です.リスト中で コメントアウトされている行を変えて効果を試してみて下さい.