では、次のプログラムを入力してください。
10 CLS 20 LOCATE 0,0:PRINT "* *" 30 LOCATE 0,0:PRINT "** " 40 GOTO 20 |
このように2つのグラフィック画面を用意して、2つを交互に表示してやることで中間調の表示が(疑似的に)実現できるのです。2つのグラフィック画面をそれぞれ画面A、画面Bとすると次のようになります。
画面A、画面Bともに点灯しているドット ・・・・ 黒 画面A、画面Bともに点灯していないドット・・・・ 白 画面A、画面Bどちらか点灯しているドット・・・・ 灰色 |
35 FOR I=1 TO 7:NEXT |
画面A のみ点灯しているドット ・・・ 薄い灰色 画面B のみ点灯しているドット ・・・ 濃い灰色 |
これにより4階調を実現するための原理はお分かりでしょうか?
同様に画面Bの2倍の時間表示する画面Cを用意すれば8階調表示ができ、さらに、その2倍の時間を表示する画面Dを用意すれば16階調も実現できるのです!
ところが、これには問題があるのです。それは「高速に表示しなければならない」ということです。
では、どの程度の速度にすればよいかということですが、60コマ/秒(1秒間に60回表示を切り替える)を実現できれば言うことはありません。60コマ/秒というのは最近のアーケードゲームでよく使われていますが、ゲームをやらない人のために別のものに例えると蛍光灯と同じ(ただし中部以東は1秒あたり50回)なのです。蛍光灯はちらついて見えませんよね。
はっきり言って60コマ/秒を実現するためには画面Aを1秒あたり180回表示するだけの速度が要求されるのです。これは言い換えれば1回あたりの表示時間が約5.5m秒なのですが、これは理論上不可能です。PRINT文の実行速度は「PRINT文の高速化」にも掲載していますが、あの数値にLOCATEの2.3m秒をプラスしなくてはいけないのです。となると、やはり、適当なところで妥協するしかありません。幸いポケコンのLCDは反応があまりよくありません(笑)ので、20コマ/秒なら十分、10コマ/秒程度でもそれほどちらつきを感じずに済むと思います(たぶんね・・・)。そうなると、画面Aは1秒あたり30回の表示速度(33m秒)で済むために何とか実現できそうです。
では、きちんと多階調表示ができるのか実際のプログラムで見てみましょう。まず、RUN*AREAとしてデータ用のエリア確保をしてください。とりあえず、24×24ドットのグラフィックで4階調表示を行いますが、データを作るのが面倒な人はRUN*SETとしてください。自分でデータを作りたい人はBFAE6hから72バイト(24ドット×3ライン)が、画面Aで、その続きから72バイトが画面Bとなりますので適当なグラフィックをPOKE文で書き込んでください。
リスト1
10 CLS 20 *MAIN 30 POKE &BFC93,&80,&FA,&B 40 GOSUB *SUB 50 END 100 *SUB 110 LOCATE 0,0:PRINT "アイウエ" 120 LOCATE 0,0:PRINT "オカキク" 130 LOCATE 0,0:PRINT "ケコサシ" 140 LOCATE 0,0:PRINT "スセソタ" 150 LOCATE 0,0:PRINT "チツテト" 160 LOCATE 0,0:PRINT "ナニヌネ" 170 FOR I=1 TO 25:NEXT 180 IF INKEY$=" " RETURN 190 GOTO *SUB 200 *SET A=255:FOR I=0 TO 11:B=-(I>5)*A:C=A-B:POKE &BFAE6+I*12,A,A,A,B,B,B,C,C,C,0,0,0:NEXT:GOTO 10 210 *AREA POKE &BFE03,&1A,&FD,&B,&80,1,0:CALL &FFFD8 |
このプログラムは速度よりも原理の分かり易さを優先して作られています。110〜130行が画面A、140〜160行が画面Bに相当します。1070行のFOR文で画面Bが画面Aの2倍の時間表示するように調節しています(実は計算したあときちんと4階調表示に見えるようウエイトは微調整している)。
コラム FOR〜NEXTの謎
実は、FOR〜NEXTの厳密な実行時間を計算で求めるのはほぼ不可能なのである。なぜなら、同じループ数でも開始値が変われば実行時間がわずかに変わるのである。しかし、もっと厄介な問題もあるのだ。 |
|
10 CLS :OPEN "SCRN:" FOR OUTPUT AS #1 20 *MAIN 30 POKE &BFC93,&80,&FA,&B 40 GOSUB *SUB 50 END 100 *SUB 110 LOCATE 0,0:PRINT #1,"アイウエ↓←←←←オカキク↓←←←←ケコサシ↑↑←←←←スセソタ↓←←←←チツテト↓←←←←ナニヌネ" 120 IF INKEY$=" " RETURN ELSE *SUB |
ここまで読んで分かるようにこの多階調表示(もどき?)はOPASを使用しなくてもフォント書き換え(+PRINT文高速化&制御文字使用)で実現できます。なぜ、仕様上OPASに入っているかというと、64文字制限のためです。グラフィックを複数枚用意しなくてはいけないのでデータ量が多くなりますからね。
でも、私が言うのも何ですが、はっきり言ってこのルーチンは使い勝手がよくありません(笑)。というのも、表示するリスト1、リスト2を比べてみて分かるように表示速度によってウエイトを調節しなくてはいけないからです。画面Aを表示するのにかかっている時間を実測で求めるなり、計算で出すなりしなくてはいけません。さらに見た目で微調整も必要です。これは、非常に大変なことです。
でも、それほどこのルーチンを使用しない(同じ表示エリアのグラフィックしか表示しない)のであれば、それほど問題にはならないとは思います。ちらつきを許容できる最大サイズは4階調で48×32ドット、8階調で24×24ドットです。正直言って、タイトル画面かイベントのグラフィック程度にしか使用するのは難しい(濃さを保つため常に一定のウエイトを加えないといけないため)常にですが、ぜひ一度使ってみてください。とはいうものの私は使ったことがありませんが(笑)
さらにOPASを活用したい人へ→OPAS応用編