OPAS応用編2

スクロールとアニメーションの同時使用


(1) 1領域でスクロールさせながらアニメーション表示


 応用編1ではOPASは複数の領域を書き換えることで多重スクロールが可能ということと1つの領域の書き換えでも一定量の多ライン同時スクロールが可能ということを書いたのですが、今度はさらにその応用となります。OPASにおいては1領域の書き換えではアニメーションとスクロールの排他使用しかできませんでしたが、アニメーションしながらスクロールという処理も可能なのです。
 原理は単純で必要なアニメパターン数の背景をあらかじめ用意しておいて異なるパターンから取り出す部分を変更するだけです。パターン1→パターン2→パターン3と切り替えることでアニメーション表示ができなおかつドット単位で取り出す場所を変えることでドット単位のスクロールができるというだけです。
 BFB66hBFC65の256バイトがパターン1、BFC66hからの256バイトがパターン・・・という感じで8パターンのアニメーションさせながらスクロールさせる場合は下記のようになります。

《 画面幅60ドット×1ラインでアニメーションさせながらスクロールする場合  》
    ※1ターンごとにアニメーションする場合

背景パターン1
BFB66hBFB6EhBFB76h・・・・・・BFBA1hBFBA9hBFBB1h
1ターン目       
9ターン目       
17ターン目       

背景パターン2
BFC66hBFC67hBFC6FhBFC77h・・・・・・BFCA2hBFCA9hBFCB2h
2ターン目        
10ターン目        
18ターン目        

背景パターン3
BFD66hBFD67hBFD68hBFD70hBFD78h・・・・・・BFDA3hBFDAAhBFDB3h
3ターン目         
11ターン目         
19ターン目         

背景パターン4
BFE66hBFE67hBFE68hBFE69hBFE71hBFE79h・・・・・・BFEA4hBFEABhBFEB4h
4ターン目          
12ターン目          
20ターン目          

 ※背景パターン5〜8は省略

リスト1 スクロールしながらアニメーションさせるサンプルプログラム
10 CLS :OPEN "SCRN:"FOR OUTPUT AS #1:Q=0:FOR P=0TO 195
20 POKE &BFC93,P,(Q AND 7)+243,11:LOCATE 0,0:PRINT #1,"アイウエオカキクケコサシスセソ"
30 Q=Q+0.5:NEXT :END
40 *SET A=&BF366:FOR I=0TO 7:Z=RND -1:FOR J=A TO A+254STEP 2:POKE J,0,2^(RND 8-1):NEXT
50 FOR J=A TO A+253:B=RND 8+I AND 7:IF B>4THEN B=8-B
60 B=2^B:POKE J,6*B,13*B,15*B,6*B:J=J+RND 7+4:NEXT :A=A+256:NEXT :GOTO 10
 《 注意 》
 あらかじめマシン語エリアとしてBF266h以降の2202バイトを確保しておいてください。


 実行前にRUN *SETでデータ作成をしてください。データ作成には1分弱かかります。

 1ラインのみのスクロールですが、単純なスクロールではなくアニメーションしながらスクロールしているというのが分かると思います。30行のQ=Q+0.5がアニメーションの速度であり、0.5の値を変えることでスクロール速度に影響を与えることなくアニメーション速度だけを変えることができます。(つまり、スクロール処理とアニメーション処理は独立している)

 これを使ってマリオタイプの横スクロールのゲームを作ればドット単位でスクロールさせつつ画面内で空中ブランコやエレベータなどの動くオブジェクトが大量にあっても速度をほとんど落とすことなく動作させることが可能になります。

 ただし、スクロールとアニメーションを同時使用すると飛躍的にデータが膨れあがります
 上記のリストを見てのようにスクロール256バイト分のデータ×アニメーションのパターンが8通りということで2048バイト分のデータとなっています。そもそも、OPASは無圧縮のグラフィックデータをメモリ上にあらかじめ展開しておくことで高速描画を実現しているのでデータ効率があまり良くありません。したがって、パターン数が増えればそれに比例して合計データ量も増えてしまいます。

 あるキャラがパターン数4、あるキャラがパターン数6、あるキャラがパターン8でアニメーションする場合は4と6と8の最小公倍数である24パターンのアニメーションとしてデータを記録する必要があるからです。1パターンにつき256バイトであればその24倍ということで6KBになります。しかも、これは表示の横幅が60ドットの場合、スクロール範囲196ドット、1ラインのデータ量です。
 これではあまりに効率が悪いためスクロールとアニメーションの同時使用をする場合は最もパターン数が多いキャラのパターン数の約数になるようにした方が良いでしょう。パターン数が最大のキャラが6の場合においては2、3、6のパターン数でアニメーションさせるとむやみにデータ量が増えずにすみます。



(2) スクロールの制限を無くす


 OPAS基本の復習で書いたようにOPASにおけるスクロールとアニメーションの違いは全く違うものを表示するのか否か(言い換えれば少しずつ位置をずらしているように見えればスクロールでそうでないならばアニメーション)ということなのでしたがそれをシームレスに行うことで上記のように同時に行うことが可能ということが分かったと思います。

 応用編1-(3)では1領域書き換えるだけで多ライン同時スクロールをさせる方法を書きました。カナにおいては64文字(384バイト)制限によって表示枠が横60ドット×2ラインの場合は264ドット分しか最大でスクロールさせることができませんでしたが、このアニメーションと同時使用によってそれは無制限になります。
 要は264バイト単位で別パターン扱いにするわけです。
 パターン1、パターン2、パターン3・・・とリアルタイムで切り替えていけばスクロールしながらアニメーションが実現できるというのは分かったと思うのですがその背景のデータにおいてパターン1のスクロール終了画面、パターン2のスクロール開始画面を一致させることでシームレスにパターン1とパターン2を繋ぐことが可能になります。

《 画面幅60ドット×2ラインでスクロールする場合  》
1ライン目
BF600hBF601h・・・BF63BhBF63Ch・・・BF708h・・・BF743h・・・BF900h・・・BF93Bh
1ターン目背景パターン1            
2ターン目             
(中略)             
265ターン目             
266ターン目          背景パターン2  

2ライン目
BF744hBF745h・・・BF77FhBF780h・・・BF84Ch・・・BF887h・・・BFA44h・・・BFA7Fh
1ターン目背景パターン1            
2ターン目             
(中略)             
265ターン目             
266ターン目          背景パターン2  

《 メモリマップ 》
BF000h〜BF5FFh グラフィックデータ作成用ワークエリア
60(表示枠)+264(パターン1スクロール用)+264(パターン2スクロール用)の588バイト
その2ライン分(1176バイト)+空き領域
背景パターン1
BF600h〜BF63Bh 1ライン目の開始時のグラフィックデータ格納場所
BF63Ch〜BF743h 1ライン目のスクロール用のグラフィックデータ
BF744h〜BF77Fh 2ライン目の開始時のグラフィックデータ格納場所
BF780h〜BF887h 2ライン目のスクロール用のグラフィックデータ
背景パターン2
BF900h〜BF93Bh 1ライン目の開始時のグラフィックデータ格納場所
BF93Ch〜BFA43h 1ライン目のスクロール用のグラフィックデータ
BFA44h〜BFA7Fh 2ライン目の開始時のグラフィックデータ格納場所
BFA80h〜BFB87h 2ライン目のスクロール用のグラフィックデータ
 
リスト2 64文字(384バイト)制限を超えるスクロール
10 CLS :CLEAR :OPEN "SCRN:"FOR OUTPUT AS #1:A$=A$+31:FOR I=0TO 9:A$=A$+CHR$ 29:B$=B$+CHR$ (160+I):C$=C$+CHR$ (214+I):NEXT :Z$=B$+A$+C$
20 A=&7900:FORJ=0TO 1:FOR I=A TO A+264
30 POKE &BFC93,I AND 255,I/256+128,11:LOCATE 0,0:PRINT #1,Z$:NEXT :A=A+769:NEXT:END
40 *SET FOR J=0TO 1:Z=&BF000+J*600:FOR I=Z TO Z+588:POKE I,0:NEXT :FOR I=Z TO Z+588:I=I+RND 9+4:Y=2^(RND 5-1):POKE I,6*Y,13*Y,15*Y,6*Y:NEXT
50 FOR I=0TO 580STEP 20:POKE Z+I,255:NEXT :X=&BF600+J*324:FOR I=0TO 1:FOR H=0TO 324:POKE X+H,PEEK (Z+H):NEXT:X=X+768Z=Z+264:NEXT :NEXT:GOTO 10
 《 注意 》
 あらかじめマシン語エリアとしてBF000h以降の3072バイトを確保しておいてください。


 実行前にRUN *SETでデータ作成をしてください。データ作成には約30秒かかります。

 このサンプルでは264ドット×2528ドット分スクロール可能になっていますがその場合1ラインあたり588バイト、2ラインの合計では1176バイトのデータ量になります。その2ライン分のデータを最初にBF000hからのワークエリアに作成していてそれを元に324バイト×2に分解しています。このように重なりあう部分を持つデータを複数パターン用意しておけば64文字(384バイト)の制限があってもメモリの許す限り横スクロールが可能になります。

 またカナだけの書き換えにおいて3ライン同時スクロールでは102ドットしかスクロールできませんでしたが、この方法を使えばそれも緩和できます。ただし、102ドットあたり162バイトのデータが必要になります。3ライン同時なので必要データ量はその3倍となります。
 同様にカナだけで4ライン同時スクロールも無理ではありません。しかし、48ドットあたり108バイトのデータが必要になってきます。4ライン同時であるため必要なデータはその4倍となります。カナの書き換えだけで288ドット分の4ライン同時スクロールを行うためには108×(288÷48)×4=1732バイトのデータが必要になってくるわけです。

 この方法を使えば64文字(384バイト)制限があっても1領域(カナ)の書き換えだけで多ライン同時スクロールを制限なしに行うことが可能になるとはいえ、上記のように同時スクロールのライン数が増えるにしたがってメモリ効率は悪くなります。メモリ効率を重視して384バイト制限を超える4ライン同時スクロールを行う場合は20h〜7Fhを除いた3領域を書き換え、カナ(A0h〜DFh)は2ライン分を賄うという方法を取るのがベターかもしれません。



(3) 縦スクロール


 OPASが本来対応していない縦スクロールも工夫次第では可能になります。縦スクロールはアニメーション機能を応用すれば良いというだけですからね。ただし、1ドットずつずらしたデータ(1ドット分シフトしたデータ)をあらかじめ用意しておく必要があるためデータ量が非常に多くなります。

 例えば、表示エリアが60ドット×4ライン(60×32ドット)でスクロール全体画面が60×63 ドットの場合は縦方向に31ドットスクロール可能になりますが、その場合において60×32の表示エリア(240バイト)の32倍(7680バイト)のデータが必要になります。(下記の(a)の方法)。しかし、それとは別の方法もあります。
 それは、PRINT+フォント書き換えで1ドット単位のキャラ移動をする場合と似たような方法です。要は縦に1ドットずつずらしたデータを8種用意し、8ドットスクロールさせるごとに表示位置を変えることで断続的な縦スクロールが可能になるのです。(下記の(b)の方法)
 この方法は上記(2)の方法の応用ともいえるかもしれません。

《 画面幅60ドット×4ラインで縦スクロールする場合  》

(a)縦スクロールさせるドット数分の全パターンを用意した場合
 ※使用メモリ 1パターン240バイト×32パターン=7680バイト

メモリマップ
BDE00h〜BDEEFh1ターン目の表示データ
 ※1つあたり240バイト
BDEF0h〜BDFDFh2ターン目の表示データ
(略)
BFB10h〜BFBFFh32ターン目の表示データ

(b)1ドットずつずらした全体データを8パターン用意した場合
 ※使用メモリ 1パターン420バイト×8パターン=3360バイト
   64-8=56ドット(=7ライン) 60バイト×7ライン=420バイト

メモリマップ1
BEEE0h〜BF083hパターン1のグラフィックデータ
 ※1つあたり420バイト
BF084h〜BF227hパターン2のグラフィックデータ
BF228h〜BF3CBhパターン3のグラフィックデータ
BF3CCh〜BF56Fhパターン4のグラフィックデータ
BF570h〜BF713hパターン5のグラフィックデータ
BF714h〜BF8B7hパターン6のグラフィックデータ
BF8B8h〜BFA5Bhパターン7のグラフィックデータ
BFA5Ch〜BFBFFhパターン8のグラフィックデータ

メモリマップ2
BEEE0h〜BEFCFh1ターン目の表示データ
BF084h〜BF173h2ターン目の表示データ
BF228h〜BF317h3ターン目の表示データ
BF3CCh〜BF4BBh4ターン目の表示データ
BF570h〜BF65Fh5ターン目の表示データ
BF714h〜BF803h6ターン目の表示データ
BF8B8h〜BF9A7h7ターン目の表示データ
BFA5Ch〜BF69Bh8ターン目の表示データ
BEF1Ch〜BF00Bh9ターン目の表示データ
BF0C0h〜BF1AFh10ターン目の表示データ
(略)
BEF58h〜BF047h17ターン目の表示データ
(略)
BEF94h〜BF083h25ターン目の表示データ
(略)
BFB10h〜BFBFFh32ターン目の表示データ

メモリマップ2の解説
1ターン〜8ターングラフィックパターンを1つずつ変えていく ※アドレスに420(1A4h)プラスする
9ターン1ターン目より1ライン分だけ変える ※アドレスに60(3Ch)プラスする
10ターン〜16ターングラフィックパターンを1つずつ変えていく ※アドレスに420(1A4h)プラスする
17ターン9ターン目より1ライン分だけ変える ※アドレスに60(3Ch)プラスする
18ターン〜24ターングラフィックパターンを1つずつ変えていく ※アドレスに420(1A4h)プラスする
25ターン17ターン目より1ライン分だけ変える ※アドレスに60(3Ch)プラスする
26ターン〜32ターングラフィックパターンを1つずつ変えていく ※アドレスに420(1A4h)プラスする

 非常に複雑に見えますがFOR〜NEXTを使えば単純であることが分かるでしょう。
 FOR A=0 TO 3:FOR B=0 TO 7:ADD=&BEEE0+A*60+B*420:NEXT :NEXT
 変数ADD(表示データの開始アドレス)

 (a)(b)2種類の方法を用意しましたが(a)の方は単純というメリットがあり(b)の方はデータ量を少なくできるというメリットがあります。表示エリアが縦に広い場合やその広さに対してスクロール量の割合が多いほど(b)の方法はメモリが節約できますが、表示エリアが縦8ドットの場合は(a)(b)に差はないので単純な(a)を選択するメリットが大きいでしょう。
 今回は表示エリアが縦32ドットであるため(b)の方法を使ったサンプルプログラムを用意しました。(a)の方は単純なアニメーションであるため基本編を理解していれば簡単に作れると思います。

リスト3 縦スクロール サンプルプログラム
10 CLS :CLEAR :OPEN "SCRN:"FOR OUTPUT AS #1
20 FOR I=0TO 3:FOR J=0TO 7:A=28282+I*60+J*420:POKE &BFC93,A AND 255,A/256+128,11
30 LOCATE 0,0:PRINT #1,"アイウエオカキクケコ↓← ←←←←←←←←←サシスセソタチツテト↓←←←←←←←←←←ナニヌネノハヒフヘホ↓←←←←←←←←←←マミムメモヤユヨラリ":NEXT :NEXT:END
40 *SET Z=&BED00:FOR I=Z TO Z+479:POKE I,0:NEXT :FOR I=Z TO Z+479:I=I+RND 9+4:Y=2^(RND 5-1):POKE I,6*Y,13*Y,15*Y,6*Y:NEXT
50 X=&BEEE0:FOR I=0TO 419:POKE X+I,PEEK (Z+I):NEXT
60 FOR I=1TO 7:Y=2^-I:FOR J=0TO 419:POKE X+I*420+J,PEEK (Z+J)*Y+PEEK (Z+J+60)*Y*256AND 255:NEXT :NEXT :GOTO 10
 《 注意 》
 あらかじめマシン語エリアとしてBED00h以降の3840バイトを確保しておいてください。


 実行前にRUN *SETでデータ作成をしてください。データ作成には2分弱かかります。

 分かりにくいと思われる部分だけ解説しておきます。
 まずは、20行の28282の意味です。
 グラフィックデータの書き込み開始アドレスであるBEEE0hの上位部分を取ったEEE0h(61152)においてANDでアドレス演算を行うため一時的に8000h(32768)マイナスし、カナ表示においてA0hからではなく「ア」(B1h)から表示しているため開始アドレスが102バイトずれるため61152-32768-102=28282となります。  あとBED00hBEEDFhの480バイトは60ドット×64ドットの全体データとなっています。これをベースに1ドットずつ縦にずらした8パターンをBEEE0hから順に書き込んでいます。

 これを実行すればスムーズに縦スクロールしていることが分かるでしょう。
 縦スクロールは横スクロールの併用さらにアニメーションの併用ができます。ただし、横スクロールのデータには60文字(384バイト)制限があるためにそれを超える場合は(2)の方法を使ったり複数領域の書き換えが必要になります。
 またアニメーションを利用する場合は縦スクロールだけで8パターンとなっているため4パターンのアニメーションを加えるだけで全体では32パターンに達してしまいます。仮に1パターン128ドット×64ドットであってもデータサイズは1KBになるため32パターンではグラフィックデータだけで32KBになります。
 したがって、縦スクロールは可能とはいえ、横スクロールほどの利便性はなくどうしても必要な場合のみ使用すると良いかもしれません。



 OPASを使用すれば工夫次第ではいくらでも凝った表現は可能になります。しかも表示速度もGPRINTよりは格段に速いのでいいことだらけとはいえ凝れば凝るほどそれに比例してメモリが必要になるため凝ったことをやろうとすればメモリはいくらあっても足りません。
 基本編はあくまでOPASの使用方法のごく一部でありこの応用編ではそれを応用することで様々なことができるようになるということだけ分かって貰えれば良いのではないかと思っています。使うか使わないかは自由ですが、OPASの基本編で書いたように選択肢が増えるということだけでも有用ですからね。
 基本編をマスターしそして今回の応用編をマスターすることで選択肢が増えるということはOPASが有効活用できるシーンも多くなりさらにOPASが便利になっていくということを意味します。


OPAS応用編1 多ライン同時スクロール
  (1) OPASの基本の復習
  (2) 多重スクロールの原理
  (3) 1領域で多ライン同時スクロール

OPAS応用編2 スクロールとアニメーションの同時使用
  (1) 1領域でスクロールさせながらアニメーション表示
  (2) スクロールの制限を無くす
  (3) 縦スクロール


RETURN

inserted by FC2 system