OPASによるプログラミング!

BASICでアニメーション処理をしよう

 前回、OPASの根本的な原理とスクロールの使用法について書きましたが、今回はいよいよアニメーション処理の方法について書きます。とはいうもののそんな大袈裟に考える必要はありません。

 前回は1ドット単位で横60ドットの画面をスクロールさせましたが、これが2ドット単位だとどうでしょうか?
 実に簡単ですね。「FOR I=1 TO 960」の後に「STEP2」を追加するだけです。
 では、これが、60ドット単位のスクロールだとどうなるでしょう。「STEP60」を追加すればよいというのは分かると思いますが、横60ドットしかない画面で一気に60ドットもスクロールしてしまったら全然違う画面が表示されて「スクロール」ではなくなってしまいます
そうなんです。これがアニメーションの原理なのです。あまりに簡単すぎてびっくりした人もいるかも知れません。でも、前回も書いたように簡単だから誰でも使えるのです。
 アニメーションさせるのに縦8ドット(1ライン)では物足りないと思いますので、縦32ドット(4ライン)分、つまり、60×32ドットをアニメーションさせる方法を書いておきます。
 今度は、1画面当たり60×4ラインで240バイト分のデータになりますので、「STEP240」にすればよいというのは分かりますね。  ということで、まず、データ記憶用にマシン語エリアを確保します。例えば、4Kバイト確保するには次のようにしてください。

 POKE &BFE03,&1A,&FD,&B,0,60,0 [RETURN]  CALL &FFFD8 [RETURN]

そして、60×32のグラフィックを確保したデータ記憶用のエリアに書き込んで下さい。4Kバイト確保している場合、17枚まで記録できます。「何のことやら分からない」とか「面倒臭い」という人は「RUN*SET」としてください。

 次がそのプログラムです。80行以降はデータ作成部分で、OPASのメインは50〜70行です。

リスト1
10 CLS :N=4:Z=&BFC00-N*&400:P=15:OPEN "SCRN:"FOR OUTPUT AS #1
20 FOR X=Z-102 TO Z+P*240-102 SETP 240
30 GOSUB *OPAS
40 NEXT :END
50 *OPAS FOR J=0 TO 3:P=X+J*60:C=INT (P/65536):Y=P-C*65536:B=INT (Y/256):A=Y-B*256
60 POKE &BFC93,A,B,C:LOCATE 10,J:PRINT #1,"アイウエオカキクケコ"
70 NEXT :RETURN
80 *SET GOSUB *MAKE
90 FOR I=0 TO 15:CLS :LOCATE 35,0:PRINT I
100 GOSUB *GRAPH
110 FOR Y=0 TO 24 STEP 8:Q=&BEC00+I*240+Y*7.5:FOR X=0 TO 60:V=1:P=0:FOR Z=0 TO 7
120 P=P+POINT (X,Y+Z)*V:V=V+V:NEXT :LOCATE 33,1:PRINT HEX$ Q:POKE Q,P:Q=Q+1
130 NEXT :NEXT :NEXT :END
140 *MAKE DIM V(19),W(19),X(19),Y(19):A=RND -1:FOR I=0 TO 19:X(I)=RND 60:Y(I)=RND 32:V(I)=RND 0*8-4:W(I)=RND 0*8-4:NEXT :RETURN
150 *GRAPH FOR J=0 TO 19:GCURSOR (X(J),Y(J)):GPRINT "3C7ED39F9FD3FFFF7E3C":X(J)=X(J)+V(J):Y(J)=Y(J)+W(J):NEXT :RETURN

主な変数の意味
N・・・マシン語エリアの大きさ(Kバイト)
Z・・・書き込み開始アドレス
P・・・グラフィックの枚数(から1を引いたもの)

 サンプルデータを使用する場合はあらかじめマシン語エリアを4Kバイト確保した後に「RUN*SET」としてデータ作成してください。このリストでは、データ作成に約12分(画面右上の数字が15で終了)かかります。要は100行で何かグラフィックパターン(この例では無数の謎の物体が散らばっていくアニメーション)を表示してそれを取り込んでいるのです。オリジナルのアニメーションも適当なグラフィックエディタで絵をかき、取り込めばできます。

 実行させれば気が付きますが、何だか、ぎくしゃくしたアニメーション(4コマ/秒)になっていますね。それもそのはず、一番上のラインと下のラインでは約0.2秒も時間差があるのです。やっぱり、一度にパッと表示させたいですね。時間差があるのは、1回の表示につきPRINT文を4回使用しているためで、しかも1つのPRINT文ごとにOPAS用のアドレス計算をしているので輪をかけて表示が遅くなっているからなのです。
 なぜならば、通常PRINT文では1ライン分しか指定通りに表示出来ないからなのです。

 しかし、実は2ライン以上同時に表示することも可能なのです。ただ、その場合ちょっとしたテクニックが必要になります。
 そのテクニックとは制御文字の使用です。例えば「A」という文字の下に「B」という文字を表示する場合、通常ならば次のようになります。

 10 LOCATE 9,0:PRINT "A"
 20 LOCATE 9,1:PRINT "B"

これを制御文字を使うと次のようになります。

 10 LOCATE 9,0:PRINT "A"+CHR$ 31+CHR$ 29+"B"

 なぜか、PRINT文1つで2ライン分同時に表示できましたね。このCHR$29とかCHR$31が制御文字になります。

CHR$ 28 ・・・ 右(→)
CHR$ 29 ・・・ 左(←)
CHR$ 30 ・・・ 上(↑)
CHR$ 31 ・・・ 下(↓)

 つまり、「"A"+CHR$ 31+CHR$ 29+"B"」というのは簡単に言えば「A」を表示した後に表示位置を下に1つ動かし左に1つ動かし(「A」を表示した後、次の表示位置は「A」の右になるため)、そこに「B」を表示するということなのです。要は「A」の真下に「B」を表示するわけですね。
 この制御文字があれば、PRINT文1つですべてが表示出来るためさきほどぎくしゃくしていた60×32ドットのアニメーションもスムーズに表示(アドレス計算が1回で済む上に一度に大量に表示するので表示自体も高速化されるため)できます。
 次のリストを見て分かると思いますがPRINT文の中にCHR$を使わずに直接制御文字を入れています(60行)。これのやり方が分からない人は次のようにしてください。

(1) RUNモードにする
(2) A$=CHR$31 [RETURN]
(3) FOR I=0 TO 9:A$=A$+CHR$29:NEXT [RETURN]
(4) A$=A$+A$+A$ [RETURN]
(5) PROGRAMモードにする
(6) A$ [RETURN] [+/-]
(7) 行番号その他を挿入する
リスト2
10 CLS :N=4:Z=&BFC00-N*&400:P=15:OPEN "SCRN:"FOR OUTPUT AS#1
20 FOR X=Z-102 TO Z+P*240-102 SETP 240
30 GOSUB *OPAS
40 NEXT :END
50 *OPAS C=INT (X/65536):Y=X-C*65536:B=INT (Y/256):A=Y-B*256
60 POKE &BFC93,A,B,C:LOCATE 10,0:PRINT #1,"アイウエオカキクケコ↓← ←←←←←←←←←サシスセソタチツテト↓←←←←←←←←←←ナニヌネノハヒフヘホ↓←←←←←←←←←←マミムメモヤユヨラリ"
70 NEXT :RETURN
80〜150 リスト1と同じため省略

 先程とは比べ物にならないほどにスムーズですね。ぱっと見てBASICとは思えないスピードかもしれません。しかし、これでも、11コマ/秒程度なのです。アドレス計算を高速化すれば、18コマ/秒まで高速化することが出来ます。

 では、アドレス計算高速化について書いておきます。
 この例ではグラフィック1枚当たり240バイト使用していますが、これを256バイトとして処理(もちろん、データも256バイト単位で書き込む必要がある→余った16バイトは未使用となる)してやるのです。こうすることにより、最下位アドレスが固定化されるので、3つのうち上位2つを計算するだけになります。
 さらに、データ量が63Kバイトよりも小さいときには最上位アドレスも「Bh」となり固定化されるので求めるのは中位アドレス1つだけになります。
 ここまでくると乗除算は必要なく加減算1つのみでOKになるので、計算速度はデフォルトの数10倍になっています。しかも、ただアニメーションさせるだけなら、単純加算(常に1ずつ加える→「インクリメント」:A=A+1に相当)で済みますのでFOR〜NEXTを使用すれば、何とアドレス計算はいらなくなってしまいます。
 つまり、POKE文で中位アドレスを書き込むだけでアニメーション処理が出来るのです。

 まず、データ作成部分である110行の「I*240」を「I*256」に変更して、再び「RUN*SET」としてデータ作成を行って下さい。そして、リスト2のプログラムを以下のように変更して下さい。

リスト3(変更部分のみ)
20 POKE &BFC93,&9A,&BE,&B:FOR X=235 TO 250
50 *OPAS
60 POKE 785556,X:LOCATE 10,0:PRINT #1,"アイウエオカキクケコ↓←←←←←←←←←←サシスセソタチツテト↓←←←←←←←←←←ナニヌネノハヒフヘホ↓←←←←←←←←←←マミムメモヤユヨラリ"

 18コマ/秒のスピードはいかがですか?マシン語で表示していると言っても分からないほどですね。ちなみに60行のPOKEは高速化のため10進数表記にしています。これが、OPASの限界速度なのですが、言い換えればBASICの限界表示速度表示エリアの変更によりさらに高速化できますが汎用性に欠けているためここでは省略)にもなります。単純に考えれば物体を1秒間に360個(20個×18)以上動かすことができます(実際に動かしているのではないのですが・・・)。
 どうでしょう。皆さんは今まで、この限界速度の何分の1で満足していましたか?まだまだBASICの奥は深いのです。ここまで理解できれば、「パネルQ」のようなゲームもいとも簡単に出来てしまいます。


さらにOPASを活用したい人へ→OPAS応用編


RETURN

inserted by FC2 system