前回、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] |
次がそのプログラムです。80行以降はデータ作成部分で、OPASのメインは50〜70行です。
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を引いたもの) |
実行させれば気が付きますが、何だか、ぎくしゃくしたアニメーション(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" |
CHR$ 28 ・・・ 右(→) |
CHR$ 29 ・・・ 左(←) |
CHR$ 30 ・・・ 上(↑) |
CHR$ 31 ・・・ 下(↓) |
(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) 行番号その他を挿入する |
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と同じため省略 |
では、アドレス計算高速化について書いておきます。
この例ではグラフィック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,"アイウエオカキクケコ↓←←←←←←←←←←サシスセソタチツテト↓←←←←←←←←←←ナニヌネノハヒフヘホ↓←←←←←←←←←←マミムメモヤユヨラリ" |
さらにOPASを活用したい人へ→OPAS応用編