プチコン3号入門講座

VSYNCとWAITでタイミングを取れ


垂直同期とのタイミングを取るVSYNC



 プチコン3号の動作は非常に高速です。そこで簡単な処理をしようとすれば一瞬で終わってしまいます。

@LOOP
FOR X=1 TO 42
 CLS
 GCLS RGB(0,255,255)
 LOCATE X,0
 PRINT "プチコン3ごう"
 GFILL X*8-4,116,X*8+60,132,RGB(255,0,0)
NEXT I
GOTO @LOOP

 これは画面の一番中央付近を水色の背景の上に赤で塗りつぶされた四角形とともにプチコン3号という文字が移動するプログラムですが動作が速すぎて何も見えません。
 では、GFILL命令の後にFOR I=1 TO 1000:NEXTという空ループを入れて時間稼ぎをしてみましょう。

@LOOP
FOR X=1 TO 42
 CLS
 GCLS RGB(0,255,255)
 LOCATE X,0
 PRINT "プチコン3ごう"
 GFILL X*8-4,116,X*8+60,132,RGB(255,0,0)
 FOR I=1 TO 1000:NEXT
NEXT I
GOTO @LOOP

 これで辛うじて何か表示している文字が見えていると思います。(※New 3DSで動作時)
 表示が速いだけではなく表示そのものがちらついて見えるし、スムーズな移動が出来ているようには見えません。
 これは実はプチコン3号は1秒間に60回しか画面表示の更新が行われないためです。この表示更新を行うための垂直同期信号のことをV-SYNC(ブイシンク)と言います。(垂直同期を示す英語Vertical Synchronizationの略)

 つまり、高速移動をさせても1秒間に秒60回を大きく超える表示は無意味になるだけではなく1/60秒の間に10回表示してしまうと10キャラ分動いてしまうためスムーズな移動ができないのです。
 また表示が薄いのはCLSで文字表示を消去させているためにその文字が表示されてないときに画面の表示更新のタイミングがやってくれば画面には何も表示されないため表示が薄く見えているわけです。(表示更新のタイミングで表示されたり表示されなかったりするのはちらつく原因になる)

 では、これはFORNEXTで上手く時間調整をして合わせてV-SYNCのタイミングに合わせれば解決できそうですが、何か処理を追加するごとにタイミングを微調整する必要があるため大変だし何より旧3DSとNew 3DSでは実行速度が3〜4倍程度New 3DSの方が高速であるためそれに旧3DSに合わせたらNew 3DSでは速すぎるという事態を招いてしまいます。

 それを簡単に改善するのがVSYNCという命令です。



 垂直同期信号の1回分の間隔をここでは「1フレーム」としています。つまり、ここでの1フレームは1/60秒となるわけです。(「フレーム」という単位には他にも意味を持つのですが、詳しくは下記のコラムを参照)

 VSYNCという命令は、前回VSYNCを実行してからの経過時間を指定した分だけ待つことができるのですが、プログラムの最初に記述したVSYNCにおいては下記のような注意点があります。

 プログラムの中にこのVSYNCという命令を入れておくだけで表示の更新のタイミングに合わせた処理が可能になるのです。(表示の更新は旧3DSでもNew 3DSでも1/60秒ごとに行っているため)
 FORNEXTの空ループループによる時間稼ぎを入れる前の最初のプログラムにこのVSYNCを入れてみたのが次のプログラムです。

@LOOP
FOR X=1 TO 42
 CLS
 GCLS RGB(0,255,255)
 LOCATE X,0
 PRINT "プチコン3ごう"
 GFILL X*8-4,116,X*8+60,132,RGB(255,0,0)
 VSYNC
NEXT I
GOTO @LOOP

 画面のちらつきも無くなり、移動もスムーズになりました。このVSYNCを入れることで速度が異なる旧3DSとNew 3DSで同じ速度になるようにプログラムを作ることができます。もちろん、旧3DSでNew 3DSと同じだけ速くなるというわけではなくNew 3DSでは表示更新のタイミングまで処理を待つことで旧3DSと同じ速度にしているというだけです。
 また、「移動する」という処理は「座標を変えて表示しなおす」ということがこれで分かると思います。

 何だかよく分からない人は難しいことを考えず、ゲームを作るときにはVSYNCは入れるものとして考えておけばいいでしょう。

 ゲームを作る場合には速度が遅ければちらついて見えるというのは分かりますが、60fps以上の速さのプログラムであれば表示がちらつくことはないと考えている人もいるかもしれません。しかし、上記のサンプルのように60fpsより速くてもちょうど消えているタイミングでV-SYNC(垂直同期)のタイミングがやってきたらそこでは消えた状態となっているため表示のちらつきが発生してしまうわけです。

《 処理が高速でもちらつく例 》
@LOOP
CLS
PRINT "ABC"
FOR I=1 TO 100:NEXT
GOTO @LOOP

 これが分かるとVSYNCはメインループ内のどこに入れても良いというわけではないということも分かり、まだ表示が行われていないメインループの最初か、すべての表示が終わったメインループの最後がベターとなります。
 ちなみに最初と最後のどちらでも構いません。ループ内で確実に実行できる場所ならどちらでも良いのです。

@LOOP
CLS
VSYNC
PRINT "ABC"
FOR I=1 TO 100:NEXT
GOTO @LOOP

 このようにCLSGCLSの直後にVSYNCを置くと消去した状態のものが画面に表示されてしまう(=何も表示されなってしまう)ため注意が必要です。

 ※ここでは「1フレーム=1/60秒」としていますが、下記の補足「1フレームはちょうど1/60秒ではない」に書いているように正しくは「1フレーム≒1/60秒」となります。


VSYNCでフレームレートを調整する



 VSYNCを入れると表示更新に合わせて待ってくれるためスムーズに1/60秒ごとの処理が行えることが分かりました。このように1秒間に60回の処理を別の言い方で「60fps」といいます。
 ゲームによっては60fpsでは処理が追いつかないため30fpsや20fpsにしたい場合もあるでしょう。古いゲームを移植してキャラをドット単位で動かすとスムーズになってしまうためあえてキャラ単位(8ドット単位にして速度を10fpsとか7.5fpsにしたい場合もあるでしょう。

 この場合もVSYNCを使うと簡単に調整ができます。

 VSYNC命令は VSYNC のように引数を省略して記述した場合はVSYNC 1と同じ意味になり、プログラムがちょうど1フレームごとに処理が行えるため上記のように60fpsの動作が可能でした。(ただし、処理速度が追いつかず処理落ちしている場合は60fpsにはならない)
 これがVSYNC 2ならば2フレームごとの処理になり、60÷2=30fpsになります。それが分かればVSYNC 320fpsVSYNC 415fpsというのも分かるでしょう。上記のプログラムでVSYNCの引数の値を変えて試してみましょう。

 VSYNC命令を使えばフレームレートを簡単に調整できますが、ここで問題は表示更新のタイミングに合わせてボタン入力の情報やタッチパネルを押したかどうか、どこの座標を押しているかとかジャイロセンサー、モーションセンサーの情報も更新されていきます。(表示更新から次の表示更新までの1フレームの間は同じ値を示す)
 これは60fpsで動作しているプログラムならばそれらがスムーズに読み出しされているため問題なかったのですが、30fpsもしくはそれより遅いプログラムではそうもいきません。

 60fps以外で問題が発生する例を挙げます。
 ボタン入力情報を取得するBUTTON()関数においてBUTTON(1)BUTTON(2)とすればボタンを押した瞬間に押したボタンを取得できるようになります。(詳しくは後述の「ボタンやスライドパッドでキャラを動かしてみよう」を参照)
 これは表示更新タイミングで取得されているためその値が今回の表示更新で16という値になり、前回の表示更新で0だったら本来であれば今回の表示更新のタイミングでAボタンが押されたわけですが、60fps以外で動作時ではその1フレーム前の値が取得できないため60fpsよりも遅いプログラムでは押した瞬間はBUTTON(1)BUTTON(2)では取得できないというわけです。60fpsより速ければ問題ないかというとそうではなく「ボタンやスライドパッドでキャラを動かしてみよう」で書いているようにBUTTON()関数は同一フレーム内は同じ値を返すため正常な動作はできません。



 それを改善するには前回取得したボタンの情報を別の変数に記録しておいて「前回押して無くて今回押されたボタンが何か」というのを調べれば良いです。

《 60fps以外の速度であっても押した瞬間のボタンを取得できるプログラム 》
◎例1
A=B
B=BUTTON()
C=NOT A AND B

◎例2
A=B
B=BUTTON()
C=B-(A AND B)
※変数Bが現在押しているボタン情報の値、変数Aが前回押したボタン情報の値
 変数Cが押した瞬間のボタン情報の値

 これを使えば60fpsでなくても(VSYNC 1でなくても)BUTTON(2)と同じようにボタンを押した瞬間のボタンの値を取得可能になります。
 例1も例2も同じ動作ですが、このプログラムの解説は難しくなるのでここでの説明を避けます。
 詳しい説明についてはBUTTON関数は後述の「ボタンやスライドパッドでキャラを動かしてみよう」ANDNOTはボタン入力の応用編となる後述の「ボタン入力とビット演算」を参考にしてみてください。

 BUTTON(1)BUTTON(2)以外はVSYNC 1でなくても特に問題はないですが、プチコン3号では各種センサーやボタンの入力情報の取得は表示更新のタイミングごとに行われていることは必ず忘れないようにして、判定ミスやおかしな動作を防止するためVSYNC命令を必ず入れるようにしましょうVSYNC 0としてしまうと「前回のVSYNCから0フレーム経過過ぎるまで待つ」となり、実質VSYNC命令はスルーされてしまうのと同じになるため付ける意味はほぼない)

 自分が作ったゲームでどれくらいのfpsが出ているかを表示したいという人もいることでしょう。fpsを求める最も簡単な方法は1秒間に何回メインループを実行できているかをカウントすることです。1秒を求めるにはTIME$を使っても良いのですが、プチコン3号には1フレームごとにインクリメントしているシステム変数MAINCNTがあるためそれを使うという方法もあります。?MAINCNTとすればプチコン3号を起動してから何フレーム経ったかが分かるためその数字を60で割れば何秒経ったかも概ね分かる)

◎FPSを計測するプログラム
TIME$使用バージョン
INC FPS:IF TIME$!=TM$ THEN LOCATE 0,0:?"FPS";FPS,:FPS=0:TM$=TIME$
MAINCNT使用バージョン
INC FPS:IF MAINCNT-CNT>59 THEN LOCATE 0,0:?"FPS";FPS,:FPS=0:CNT=MAINCNT

 前回FPSを表示した時のMAINCNTの値(変数CNTの値)と現在のMAINCNTの値を比較してその差分が59を超えた場合(MAINCNTは整数値なので前回からの差分が60以上になった場合)は1秒なのでその間に実行できた回数を表示しているというシンプルなプログラムです。あとTIME$の値が変わるのは1秒ごとであり、前回FPSを表示した時から変化していればFPSを表示というの説明しなくても分かると思います。
 これをメインループ中の適当な場所におけば1秒ごとに画面左上に現在のFPSを表示します。最初の1回目の表示は正しくなく2回目以降(プログラムをスタートして2秒以降)が正しい表示になります。なお、このプログラムを改造すれば1秒未満でFPSを求めたいとか0.1fps単位で求めたりもできるので改造してみてください。
 メインループにVSYNC 1が入っている場合は基本的にFPS60のまま固定になるのですが、これが60より小さな値になる場合はいわゆる処理落ち状態となります。
 なぜ、MAINCNT-CNT==60という条件にせずMAINCNT-CNT>59にしているかというとMAINCNT-CNT==60とした場合には処理落ち時には正常動作ができなくなるためです。MAINCNT-CNT>59とすることでどれだけ処理落ちしても正常に計測することが可能になっています。


単純に待つ命令WAIT



 上記VSYNC命令は前回のVSYNC命令が実行されてから次のVSYNCまでの間の表示更新のタイミング分だけ実行します。例えば、60fpsではなく少し処理落ちして58fpsとかになっているゲームの場合はVSYNC 1を実行してもすでに前回のVSYNCからは1フレーム以上経過しているためVSYNC 1はスルーされてしまいます。
 これは出来る限りVSYNC 1(60fps)で動作するためには当然の動作ですが、単純にウェイト(待ち時間)が欲しい場合はこれでは都合の悪い場合があります。
 そこで用意されているのがWAIT命令です。



 WAIT命令は前回実行されてからのフレーム数は関係なく表示更新のフレーム数分だけ待ちます。WAIT 10ならば10フレーム分のウェイトとなります。ただし、プチコン3号で扱える最小単位が「フレーム」なのでぴったり10フレームとは限らず多少の誤差が生じてしまいますが、それでもVSYNCの直後に実行した場合は誤差はほぼありません。

 さて、フレーム単位で待つ命令が「VSYNC」「WAIT」と2つあってどちらを使ったらいいのか迷う人もいることでしょう。それは以上の説明を読めば表示更新やボタン入力などのタイミングを取る場合はVSYNC、単にウェイトが欲しい場合にはWAITを使うのがベターであることが分かるでしょう。

《 VSYNCではなくWAITを使うのがベターな例 》
VSYNC
INPUT "何秒待ちますか?";A
VSYNC A*60
BEEP 73

 「3秒待ちたい」という場合には3を入力するのですが、入力するまでに3秒以上かかっていたらVSYNCは無視される(2秒かかっていたらVSYNCの部分では差分の1秒しか待ってくれない)というのが分かると思います。
VSYNCのみを使ってこのプログラムを正常に動作させるためにはVSYNC A*60の直前にVSYNC 0を入れれば問題ありません。しかし、そんなことをするくらいならば素直にWAIT A*60と記述した方が良いですね。

 INPUTを使った例のようにVSYNCを含まない1フレーム以上の処理(この場合はINPUTの入力にかかる時間が1フレーム以上かかる)を行った場合にその次に実行するVSYNCは最後のVSYNCからの経過時間が大きくなるため正しく待つことはできません。VSYNCが想定通り動作するのはループ内(同じVSYNCを繰り返す場合)に限られるということです。

なお、プログラムで最初に実行されるVSYNCの起点は前回実行時のものであるため最初のVSYNCはスルーされる可能性がありますが、正確にはスルーされるわけではなく「前回VSYNCを実行してからの経過時間ほど待つ」というのは何ら変わっていません。
 上記サンプルプログラムにおいて先頭のVSYNCを省略して長目の値(5秒とか10秒とか)を入力して一旦中断して実行すれば前回中断した時の最後のVSYNCからの経過時間の待ちとなることが分かると思います。
 これを利用すれば前回実行したプログラムを中断をしてからの時間も判断が可能です。

《 VSYNCが前回実行したプログラムからも引き継がれる例 》
M=MAINCNT
VSYNC 300
IF MAINCNT-M THEN ?"あなたは、ぜんかいじっこうして5びょういないにこのプログラムをまたじっこうしましたね?" ELSE ?"ぜんかいじっこうしてから5びょういじょうたちました"

 このプログラムを実行して再実行した際に実行するまでの時間によって表示されるメッセージが変化します。
 プログラムでよく使われるのはVSYNC 1ですがプログラムを実行時には前回VSYNCを実行してから1フレーム以上の時間が確実に経過しているためプログラムの最初に記述したVSYNCはスルーされるというだけなのです。

 VSYNCはこのように前回のVSYNCを実行してから経過した時間によって動作が変化するため「確実に一定時間待って欲しい」という場合には思ったような動作をしてくれない場合も少なくないです。
 例えば、「Aボタンが押されるまで待つ」という「Aボタン入力待ちプログラム」は次のように記述できます。

《 VSYNCを使ったAボタン入力待ちプログラム 》
 REPEAT VSYNC UNTIL BUTTON(2)==#A

 この場合は何度も書いているように前回のVSYNCからの経過時間によってVSYNCの動作は変化するためループ内の最初のVSYNCの動作が保証されてないという問題があります。例えばタイトル画面でAボタン入力待ちを行っている場合に「RUN+Aボタンで開始」したり、コンソールゲームを作っていてINPUTの処理の後にAボタン入力待ちがある場合に「Aボタンで入力を確定」したり等の場合は、この「Aボタン入力待ちプログラム」に含まれるVSYNCは、最初に実行時に前回のVSYNCから1フレーム以上の時間経過しているためスルーされるのでこのAボタン入力待ちプログラムは正常に動作しません。

 したがって、これもWAITを使った方が良いです。

《 WAITを使ったAボタン入力待ちプログラム 》
 REPEAT WAIT UNTIL BUTTON(2)==#A

 WAITは前回のVSYNCWAITからの経過時間とかは関係なく指定したフレーム数ほど待ってくれるためこのWAITを使ったAボタン入力待ちのプログラムはいかなる場合であっても正常に動作します
 VSYNCを使ったAボタン入力待ちプログラムをいかなる場合も正常動作させるためにはこの「Aボタン入力待ちプログラム」の先頭にVSYNCもしくは何らかの1フレーム以上のウェイト処理(FOR I=1 TO 30000:NEXTなど)を追加する必要があるためWAITを使った方が簡単で分かりやすいと思います。

 「前回のVSYNCからの経過時間」というのが良く分からないという人は、「待たないと困る」場合はWAIT、「待ちすぎたら困る」場合はVSYNCという使い方をするのが良いかもしれません。
 とはいえ、常時60fpsで動作しているゲームのメインループに使う場合はVSYNCでもWAITでもほぼ同じ動作になるため自分の好きな方を使って良いと思います。(処理落ちせず常時60fpsで動作しているのか分からない場合は上記のFPS表示プログラムを使って常時FPS表示を行ってもいいし、「タイミングを取るのにはVSYNCを使えばいい」と考えればいいだけのことなので難しく考える必要はない)

《 WAITを使った簡易的なストップウォッチ 》
REPEAT
 WAIT
UNTIL BUTTON(2)==#A
REPEAT
 T=T+1
 LOCATE 21,14
 PRINT FORMAT$("%5.2F",T/60)
 WAIT
UNTIL BUTTON(2)==#A
BEEP 3

 これは、最初のREPEATUNTILAボタンを押してスタートするまでを待つループで次のREPEATUNTILがメインループでAボタンを押すことで計測を終了します。VSYNCではなくWAITにしているのは何度も書いているようにVSYNCが確実な待ちには使えないためです。WAITVSYNCに変えてRUN Aボタンでこのプログラムを実行してみればそれがどういうことなのかが一目瞭然になります。
 BUTTON()関数については後述の「ボタンやスライドパッドでキャラを動かしてみよう」を参照、REPEATUNTILについては「ループ命令で条件判断」を参照してください。


《 補足 》1フレームはちょうど1/60秒ではない

 厳密に言えばプチコン3号において垂直同期のタイミングはちょうど1/60秒ごとではなく少しずれがあるのです。したがって、VSYNCWAITもそれに合わせているのです。私の実測では1/59.833秒くらいでしたが、その細かい時間を覚える必要はなく「(ぴったり1/60秒ではないけど)概ね1/60秒」と覚えておいてほぼ問題はないと思います。
 時間表示をするプログラムを作っていてこのずれが気になるという人は ver.3.3.0から加わったシステム変数 MILLISEC を使うと良いでしょう。これを使えばプチコン3号を起動してからの時間がミリ秒(1/1000秒)単位で分かるのでMILLISEC/1000で何秒かが分かります。細かいことは気にしないならばMAINCNT/60で秒数としても問題はないです。

 MAINCNTがプチコン3号を起動してからのフレーム数、MILLISECがプチコン3号を起動してからのミリ秒であり、両者は似ているシステム変数なのですが根本的に異なるのはMAINCNTがスリープ中は増加しないのに対して、MILLISECはスリープ中も増加するということです。これを上手く活用すればスリープしている時間を求めることも可能です。
 ちなみにプチコン3号には内蔵時計の時間を取得するTIME$というシステム変数があります。MILLISECがプチコン3号を起動している状態でスリープになってもカウントしているのですが、TIME$は内蔵時計なのでプチコン3号を起動していなくても電源を切っていてもカウントしているというメリットがあります。ただし、内蔵時計との情報のやりとりは1フレームごとではなく15フレームごとに行われるという点に注意が必要です。1秒間に4回情報が更新されるというわけですが、「15フレーム」がぴったり1/4秒ではないためその誤差の蓄積によって、89秒に1回は1秒に3回しか情報更新されないということがあります。時計表示のプログラムを作っていて「若干短く感じる1秒」があったらそれが原因です。

 上記の「VSYNCでフレームレートを調整する」において、FPS(1秒間の処理回数)を表示するプログラムを記述していますが、このプログラムでは60フレームを1秒としてカウントしています。これはMAINCNTを使うよりTIME$MILLISECを使ったりした方が正確な1秒を計測できるのですが、「VSYNC 1で処理落ち無しのプログラムを60fpsとする」と考えた場合にはTIME$MILLISECを使った場合にはぴったり60fpsにはならないのでMAINCNTの方が都合が良いのです。TIME$を使った場合には89秒間に1回は「1秒≒45フレーム」になる)

《 コラム 「フレーム」という言葉の意味 》

 WAIT 3ならば「3フレーム待つ」というのは分かると思います。しかし、メインループにWAIT 3VSYNC 3を用いて20fpsのゲームを作った場合には「フレーム」という言葉は別の意味合いを持ちます。
 それは、60fpsのゲームでない限りはゲーム内の時間(ソフトウェア面の時間)とハードウェア面の時間にギャップが生じるためです。

 WAITVSYNCは上記のようにあくまで垂直同期の更新の時間を基準に動作しています。それはプチコン3号(正しく言うならば3DS本体)の場合は約1/60秒となるため「WAIT 3で3フレーム待つ」という書き方そのものは間違っていません。
 とはいえ、20fpsのゲームの場合は実際は垂直同期3回分で1回の描画を行っています。これは動画で例えると分かりやすいのですが、撮影コマがあってその次のコマが1/20秒後となるわけです。つまり、その動画の1フレームごとの時間は1/20秒となります。これは動画に限らずゲームにおいても同じです。
 したがって、WAIT 3は3フレーム待つと書いた場合にはソフトウェア面から見た場合には正しくありません。十分に高速処理が可能なプログラムでWAIT 3をメインループに記述した場合にはあくまで「垂直同期3回分が1フレーム」となるからです。

 このようにハードウェアとしての垂直同期の間隔は20fpsのゲームだろうと10fpsの動画だろうと約1/60秒から変化しない(20fpsのゲームだからといって1/20秒単位で表示更新が行われるわけではない)のは上記のVSYNCの解説を見ても明らかでハードウェア面から見た1フレームは「約1/60秒」で正しいのですが、ソフトウェア面ではそのソフトの処理速度に依存する形になります。
 ただし、VSYNCWAITMAINCNTについて説明する場合は垂直同期というハードウェア面での動作時間が基準になっているというのは何度も書いているように「それが分かっていて1フレームが約1/60秒と考えること」はは何ら問題はありません。あくまでハードウェアとしての表示更新はどんな速度のゲームであろうと垂直同期の信号ごと(約1/60秒ごと)に行われているためです。

 プチコン3号は処理速度が速いので画像は一瞬で表示されますが、「一瞬」は0秒ではありません。分かりやすく説明するためプチコン3号で動画再生を行う際に静止画像を1枚表示するのに1/20秒の時間がかかると仮定します。その場合においては垂直同期信号ごとに画面更新が行われるため最初の1/60秒でその動画の中の静止画1枚のうちの上の1/3が描画され次の1/60秒で中央の1/3が描画されそして次の1/60秒で下の1/3が描画され「トータルでは1/20秒で1枚の静止画が表示されているように見えているだけ」です。
 その1/3ごとの描画単位(垂直同期ごとの描画単位)がハードウェア面から見た1フレームです。わざわざ実際に表示される1枚から分割して「ハードウェア面から見た1フレーム」なんて考える必要はないと思う人もいるかもしれませんが、プチコン3号では例えばスプライトでアニメーション表示した場合には垂直同期ごとに動作しているし、各種センサーやボタン入力も垂直同期ごとの動作となっているためプチコン3号でゲーム等を制作する場合には「垂直同期単位」で考えることは非常に大きな意味を持つわけです。上記のようにVSYNC 3を入れれば1/20秒単位で動作しているように見えるけど実際は1/60秒単位の3つ分として動作している)
 逆にいえばゲーム等を作るのではなく純粋に動画として考えるならばほぼ無意味でしょう。端的に言えば、プチコン3号においても作る立場に立つか見るだけの立場に立つかで「フレーム」という言葉の意味合いが変わってくると言えるかもしれません。

 とはいえ、「フレーム」は垂直同期信号ごとの時間の単位であると言い切るのは正しくないでしょう。
 例えば「1km」なのか「1kg」のことなのかが分からない場面で「1キロ」と書くのは正しいとは言えないですが、明らかに1kmのことを示していると判断される場面で「1kgと間違えるから1『キロ』と表記するのは正しくない」ということはなくちゃんと分かって使うならば問題ないというのは分かると思います。(「フレーム」は「重さ」と「長さ」という異なる次元のものではなく両方とも同じ「時間」という次元で使うため間違いやすいというのはあるけど)
 「キロ」というのは接頭辞であり長さや重さを示すような単位ではないのと同じく「フレーム」も時間を示す単位でく静止画像を示すものですが、時間を示すような場面で「3フレーム」と記述されていたらそれは「3フレーム分の時間」というのを意味します。(「フレーム」が時間の単位ではないと指摘するのは「キロ」が長さや重さの単位ではないと指摘するくらい野暮なこと)
 あと垂直同期何回分の時間かを「フレーム」という単位で記述すること自体に抵抗があるのである人も中にはいるかもしれませんが、これはプチコン3号のマニュアルでも書かれているものなので「プチコン用語」として考えれば問題ないと思います。どうしても気になる人は3フレームを3vsyncと置き換えて考えれば良いでしょう。(あえて小文字で「vsync」を書いたのはこれはオリジナル単位でありVSYNC命令との混同を防ぐためであり、3vsyncVSYNC 3は意味合いが違うという厄介な問題があるため)


RETURN (プチコン3号講座のページにもどる) RETURN *MAIN (トップページにもどる)

inserted by FC2 system