レス数が1スレッドの最大レス数(1000件)を超えています。残念ながら投稿することができません。
おちゃめくらぶ掲示板
-
プチコンで高速化重視のプログラムを作る意味はあるのか?
プログラミングにおけるコード(プログラムリスト)の書き方にはいろいろなものがあるにょ。
大きく分けると次のような3つになると思われるにょ。
(1)実行速度をできるだけ速くする
(2)コード(プログラムリスト)をできるだけ短くする
(3)コードの可読性をできるだけ良くする
(1)30〜40年前はマシン性能が極めて低く速いプログラムを書ける人はそれだけでも重宝
されたにょ。
イメージ的には80年代初頭のZ80(3.58MHz)搭載機種におけるマシン語ゲーム実行速度が
プチコンmkIIにおけるBASICの実行速度くらいだったにょ。(プチコンの表示は当時の機種の
マシン語プログラムによるものよりも速いけど加減算はZ80のマシン語プログラムの方が
速かったので必ずしも同程度の速度とは言い難い部分もあるけど)
それにBASICというのはほとんどがインタープリタ型であったためそのマシンで動作する
ためにはリアルタイムで構文解析しながら実行する必要があり、当時のBASICはプチコンと
比べると100倍くらい遅いものであったにょ。
もちろん、それよりも古い世代や遅い機種(ポケコンなど)ではさらに厳しいものが
あったにょ。
ちなみにポケコンにおいては80年代前半における入門機のPC-1245はFOR〜NEXTの1000回
ループ(1万回の書き間違えではない)が42秒だったにょ。
これでゲームを作るというのは高速化だけでは無理があり、やはりまともな速度(5fps
以上)のアクションゲームを作るにはマシン語が必須だったにょ。
(2)黎明期のマイコン(70年代の機種)や初期のポケコン(80年代初頭の機種)はメモリを
数百バイト〜数KBしか搭載しておらず高級言語のBASICを搭載して誰でも簡単にプログラミング
可能になった(70年代のマイコンは7セグメントLEDを見ながら0〜Fの16進数キーボードで
マシン語プログラムを入力していたというのは知っている人も多いと思う)とはいえやはり
かなり厳しいのは確かにょ。
私が初めて買ったポケコンはPC-1245だったけどこの機種のユーザー使用可能メモリは
1486バイト(メモリ増設はハードの改造をしない限りは不可)だったにょ。(この機種の
ライバルだったPB-100は標準で544バイト、1KBの拡張メモリを装着時に1568バイト)
90年代以降の機種しか触ったことがない人は数字を見ただけで「こんな少ないメモリ」では
ゲームなんてできるわけがないと思うかもしれないけどそれは工夫次第でいくらでも何とか
なるにょ。(RPGとかもこのメモリで作れていたし)
むしろ、短くプログラムを書くということの重要性は当時のマシンを使っていれば実感が
沸くのではないかと思うにょ。
今ならばプチコンにおいて1画面プログラムや1行プログラムを作ることで短く書くという
ことを楽しむことができるにょ。
こちらはあえて制限を付けることでそういうのを楽しんでいるけどそれは環境が固定である
ということがメリットになっているにょ。
「1画面プログラム」という言葉がメジャーになったのは雑誌「MSX fan」の1画面プログラム
コーナーだと思われるにょ。
MSXは標準で16〜64KBのメモリを搭載しているため40文字x24行(960文字)の1画面で作る
というのはプチコン同様に短く書くという制約を楽しむためのものにょ。
(3)昔のマシンは遅かったり、メモリが少なかったりしたため速くなるように書く、短く書く
というのはそれ相応の理由があったため許されていた部分もある(上記のようにそれ自体を
楽しんでいる場合もある)けれどやはり可読性は非常に重要な要素といえるにょ。
といっても、私は昔から(1)や(2)を重視したプログラムばかり作ってきたためこの可読性を
良くして書くというのは意識しないとできないにょ(笑)
つまり、可読性の良いプログラムを作れなくはないけどそれだと作っていて楽しくないから
やらない(講座などの第三者の初心者に見てもらうことが前提のものは別)ということにょ。
これは普段可読性を重視している人が速度重視や短さ重視のプログラムを作ろうとしても
楽しいものにならないのと同じだと思うにょ。
可読性を良くするには様々な方法があるにょ。
ループなどでは適切な字下げを行ったり、命令や引数には適切なスペースを入れたり、
変数名やラベル名には分かりやすい法則性を持たせたり、適切なコメントを入れたり、
むやみにGOTOで飛びまくったりしないということを考えれば可読性は良くなるにょ。
つまり、逆に言えば、字下げを行わなかったり、可能な限りコロンやスペースを削ったり
1文字変数や無意味な名前の変数を付けたり、コメントを全く入れなかったり、GOTOで
あちこちに飛びまくっているプログラムは可読性が低いといえるにょ。
これを見ると1画面プログラムは可読性が極めて低いにょ。
まぁ基本的にGOTOを使わないので「GOTOを使わなければ可読性が上がる」というのならば
1画面プログラムの可読性は高くなってしまうけどね。(BASICの場合は必要な場面で
GOTOを使うのは可読性を良くするのには重要になり「GOTO禁止」は可読性の面では逆効果に
なるというのは1画面プログラムを見れば良く分かると思う)
端的に言えばそのプログラムの仕組みを知らない第三者が見ても分かりやすいものが可読性が
高いといえるにょ。
さて、仕事でプログラミングを行っている人ならば間違いなく(3)を重視すべきだけど趣味
ならば(1)(2)(3)どれでも各自の自由で問題ないにょ。
昨今はマシン性能が高くなっていてDSiで動作するBASICのプチコンでさえかつての8bit
マシンのマシン語プログラムに匹敵する実行速度を得られるのだから速度をそこまで重視
したりとかはあまり必要ないとか、メモリも1MBあり個人で作るゲームであれば足りなく
なる方が少ない(データが足りなくてもプログラムリストを短くしてメモリの空きを確保
しなくてはならない場面はほぼない)ということでプログラムをできるだけ短くするという
機会はあまりないため可読性を重視という人が大半ではないかと思われるにょ。
とはいえ、実際は30fpsさえ難しいゲームを作っている人もいるわけであって速度は重視
する必要はないといってもそれなりには速度を要求される場面はあると思うにょ。
ということで、前置きはこれくらいにしておいて、プチコンで高速化を行うための方法を
書いていくにょ。
まずは、その前に高速化とは何かというと例えば10fpsしか出ないようなゲームを30fpsで
動作するような感じにょ。
こういうことを書くと「そんなことが本当に可能なのか?」と思う人がいるかもしれない
けれど私は昔はポケコンにおいて雑誌掲載のゲームを高速化改造するのを趣味にしていた
けれどベーマガなどに掲載のゲームがその改造で平均3倍くらい速くなった(最高では
9倍速くなった)ということで高速化改造というのはそれなりに効果があると言えるにょ。
http://ochameclub.web.fc2.com/E500/TECH/basic1.htm
もちろん、マシン語が使える機種ならばマシン語を使えば3倍どころではなく数10倍〜
100倍くらい速くなるため3倍しか速くならないBASICの高速化なんてあまり意味がないと
考える人はいるかもしれないけどプチコンならばBASICしか使えないためその恩恵は十分に
あると思うにょ。
高速化を行うために必要な事柄
(A)ボトルネックになっている部分を知る
(B)アルゴリズムの改良などで高速化を行う
(C)余分なものは省略、命令や演算子などを駆使して高速化を行う
(A)効率的な高速化を行う場合にはどの処理にどの程度の時間がかかっているのかを知る
ことがまず必要不可欠となるにょ。
http://ochameclub.web.fc2.com/E500/TECH/basic2.htm
これを知らずに盲目的に高速化を行おうとすると「高速化しているつもりなのに全然速く
ならないので高速化なんて無意味」と感じるようになってしまうにょ。
これは昔、雑誌「ポケコンジャーナル」誌上で行われた討論だけどPC-E500ではFOR〜NEXTに
おいてNEXTのあとの変数を省略すると1万回あたり7秒の高速化が可能だけどこれは逆に
いえば1回当たり0.07m秒しか速くならないためこんな省略化は無意味というものにょ。
確かにそれ1つだけだとほとんど無意味だし、そのプログラムにおいてNEXTの後に変数を
付けることがボトルネックになっているということはほぼあり得ないにょ。
これはどういうことかというと上記(C)で挙げているものは他に高速化できる余地がないか
十分に考えた後に行い「塵も積もれば山となる」で高速化を行うものでありそれ1つの
高速化効果を論じるようなものではないということにょ。(お金に例えると買い物をする
度に発生する1円単位の端数は単体で見ると小さいけど長い目でみればかなりの金額に
なってくるというのと同じで5円は捨てても惜しくないけど5000円は惜しいという人は
多いと思うので5000円を得るためには5円の積みかさねが必要になる)
まず、目に見える高速化効果を得るためには時間がかかっている処理から高速化を考える
必要があるわけにょ。(アクションやシューティングならば画面表示、コンピュータ対戦の
思考ゲームならばコンピュータの思考ルーチンなど)
0.1フレームで実行している処理を5倍速くしても0.08フレーム分の高速化でしかないけど
5フレームかかっている処理を5倍速くすれば4フレームも速くなるから前者と後者は同じ
割合で高速化できた場合にどちらがより有用かが分かると思うにょ。(限界まで高速化を
行うならば後者だけではなく前者の高速化も行う必要があるけど)
(B)アルゴリズムとは端的に言えば処理の手順を記したものにょ。
これはポケコン(PC-E500)用だけど概ねプチコンでも当てはまるにょ。
http://ochameclub.web.fc2.com/E500/TECH/basic5.htm
アルゴリズムの改良は高速化においては非常に大きく影響することが多いにょ。
数倍〜10倍程度の高速化も十分に可能になってくるにょ。
基本的には演算数を減らす、ループ回数を減らすというのが高速化に繋がってくるにょ。
プチコンにおいては代入数を減らすというのも高速化には有用にょ。
具体例を挙げるとじゃんけんの勝敗判定アルゴリズムにおいて最も分かりやすいのは
プレイヤーの出す手(グー、チョキ、パー)とコンピュータの出す手(グー、チョキ、
パー)のすべての組み合わせである9通りのIF文を羅列するというものにょ。
それは少し考えれば引き分けは3通りではなく1通りで済むためIF文は7通りで済むという
ことも分かると思うけど実際はそんなことをする必要はなくて (Y-X)%3 で勝敗判定が
可能になっているにょ。
http://ochameclub.web.fc2.com/petitcom/tips/mod.htm#janken
またアルゴリズムとは少しずれてくるけど複雑な処理や判定を行う場合には配列変数などを
使ったテーブル化を行うという方法があるにょ。
あらかじめ行う内容のパターンが決まっていたらそれを常に演算する必要はなくあらかじめ
演算しておいたものを読み出すだけの方が高速処理できるのは言うまでもないにょ。
同様の考えとしてメインルーチン内で常時演算や判定をする必要はないものはメインルーチン
内には置かないというのも高速化としては有用にょ。
http://ochameclub.web.fc2.com/E500/TECH/basic6.htm
(C)プチコンがインタープリタ型である以上はリストにある余分なものは可能な限り削除して
おいた方が高速化に繋がるにょ。
例えばコロンやスペースやカッコは省略できるものは省略した方が高速化になるし、
変数名やラベル名もできるだけ短い方が高速化に繋がるにょ。(定数も桁が少ない方が速く
なるけど定数の場合は小数か否かが最も速度に影響するため桁数の多い小数はあらかじめ
1文字変数に入れておいてメインルーチン内ではそれを参照するのが最も高速)
改行コードもできるだけ省略する(マルチステートメントで記述する)のが高速化には有用
だけど改行コードよりもコロンの方が重いためコロンを付けずにマルチステートメント化
可能な場合のみマルチステートメントで記述するのが最も高速になるにょ。
FOR〜NEXTにおいてはNEXTの後の変数を省略することが高速化に繋がるけどTOの後の終了値が
速度に最も大きな影響を与えているにょ。
例えば「FOR I=0TO A」を「FOR I=1TO A+1」にしてしまうと(A=0の時、つまりループ回数
1回の時)でさえ10万回あたり48フレームも遅くなってしまうにょ。(1回のループであっても
ここまでの差が生じてしまいループ回数が多ければ多いほどさらに差は大きくなる)
上記のコロンの省略を行っても10万回あたり9フレーム程度しか速くならないためこれが
いかに致命的な遅さに繋がるかが分かると思うにょ。
これはプチコンの場合はループを実行中に終了値のチェックを行っているためにょ。
そのため終了値を論理式にすればブロックIFやREPEAT〜UNTILのようなこともFOR〜NEXTで
可能になるにょ。(ただし、速度面では少し不利になる)
http://ochameclub.web.fc2.com/petitcom/tips/list.htm#for
これはプチコンに限ったことではなくほとんどのBASICにおいて当てはまるけどIF文は
単数、複数の条件式に関わらずその式の値が「0か」「0以外か」でTHEN以下が実行するかが
決まるにょ。
http://ochameclub.web.fc2.com/petitcom/tips/list.htm#if
また、式の値が0の時にTHEN以下を実行させたい場合は論理否定を使うのが最も高速にょ。
http://ochameclub.web.fc2.com/petitcom/tips/list.htm#hitei
昔はIFを使うよりも論理式の方が高速と言われていたけどプチコンの場合はIFがそこそこ
速いため多くの場合でIF文の方が速くなるにょ。
ただし、これもIF文が成立する割合とTHEN以下に記述する内容によって変わってくるにょ。
http://ochameclub.web.fc2.com/E500/TECH/if3.htm
(これはポケコン用だけどプチコンでも概ね同じことが言える)
また、C言語などとは異なりプチコンを始めとする多くのBASICではIF文では複数の条件式が
記述された場合にはすべてをチェックしてからTHEN以下を実行するかどうかが決まるにょ。
そのため条件式を記述する順番はどうでも良さそうに思えるけどIF 条件式A AND 条件式B THEN
というのはIF 条件式A THEN IF 条件式Bとすることで高速化が可能になる場合があるにょ。
http://ochameclub.web.fc2.com/E500/TECH/if4.htm
ただし、この場合はIFを2つ実行する必要があるため条件式Aが成立する可能性が低い場合に
限って高速化が可能になるにょ。(AもBもかなりの高確率で成立するならば普通に記述した
方が高速になる)
また、画面表示においてはプチコンではコンソール、スプライト、BG、GRPがあるけど速度面
においては同じ面積ではBGが最も高速で次にスプライトにょ。(BGは画面一杯の大きな
キャラを表示しても速度ロスがないけどスプライトの場合は大きなキャラを表示すれば
するほど少しだけ遅くなる)
プチコンにおいてコンソールとGRPはかなり重い描画命令にょ。(同一面積ならばGRPの方が
重いけどGCOPYを使えばそれは逆転する場合もある)
GRP上でキャラを表示する場合にはGPUTCHRを使うのが最も簡単だけどこれは非常に重い
命令となっているにょ。
ある程度表示させるキャラが決まっているならば別のGRP面にあらかじめ描画しておいて
GCOPYを使って表示した方が高速になるにょ。
ただし、GPUTCHRを使って描画したキャラをGCOPYで別の面に表示する場合にはパレットの
問題があるため注意する必要があるにょ。
http://ochameclub.web.fc2.com/petitcom/p007_2.htm#column
BGやスプライトが比較的高速といっても多数表示する場合にはそれなりに重くなってしまう
ため一定量ずつ移動する場合には補間処理を行うのがベストにょ。
補間処理による移動はハードウェアの機能を使うためCPUの処理はゼロで移動が可能になり
多数のスプライトを移動させる必要がある場合には高速化には必要不可欠といってもいいにょ。
ただし、あくまで終点までの直線的な移動しかできないためすべてのスプライトを補間処理で
表示というのは難しいにょ。(補間処理を有効活用したければ実質15fpsで4フレームに1回の
表示処理だけど4フレーム分の移動を補間にすれば見た目を60fpsにするなどによって可能)
あと使用画面が上画面のみであってもPNLTYPE"OFF"(もしくはPNLTYPE"PNL")を実行して
おけばすべての処理が5〜8%程度高速化されるにょ。
割合そのものは小さいけどすべてにおいて有用なのでギリギリ処理落ちしていたゲームが
処理落ちしなくなるくらいの高速化は望めるにょ。
しかも、コロンやスペースやカッコの省略を全部行ったりするのと違って特別な知識も
手間も要らず1つ追加するだけで済むのでこれは速度重視ならば必要不可欠といっても過言
ではないにょ。
主なものをざっと羅列していけばこんな感じにょ。
これ以外にもまだ様々な高速化要素はあるけど今回はとりあえず思いついたものをざっと
書いてみただけなのでより詳しく分かりやすくまとめたものは別の機会に書くつもりにょ。
高速化というのは多くの場合において可読性とは相反するものにょ。
したがって、可読性を重視する限りは高速化は難しいことが多いにょ。
逆に言えば高速化を重視するならば可読性は妥協しなくてはならないにょ。
また、高速化というのは汎用性を犠牲にして行うことが多いにょ。
それ専用のアルゴリズム、その変数の取りうる範囲内でしか成立しない条件式などによって
高速化が可能になる場合が多いということにょ。
私がポケコンで限界までの高速化を行っていた時にはどの変数がどのような値をどのような
割合になっているかを元にしていたにょ。
したがって、仕様変更などがあった場合には高速化をまた見直す必要があるため限界までの
高速化を行っていると仕様変更には対応が難しくなるにょ。
逆に言えば汎用性を高めれば高めるほど高速化とは無縁になっていくということにょ。
それについてはこのポケコン用の高速化講座でまとめている通りにょ。
http://ochameclub.web.fc2.com/E500/TECH/basic9.htm
ポケコンでは高速化に拘り続けてきた私だけどプチコンではサイト上ではリスト短縮関係
ばかりなのは高速化がリニアに影響を与えるポケコンとは異なり、プチコンはポケコンと
比べて演算速度で100倍程度、画面表示速度は数千倍程度高速であるため私が作っている
ようなシンプルなゲームならばほとんどの場合において60fpsが余裕であり、GRPでスクロール
という重いゲームのみ30fpsになっている程度にょ。(GRPによる二重スクロールを用いて
いるプチコン100m走mkIIは60fpsになっている)
何せポケコンは普通に作ればシンプルなゲームであっても3〜5fpsしか出ないからね。
3倍速になれば非常に大きな影響があるけどプチコン上ですでに100fpsで動作している
ゲームが3倍の300fpsで動作しても全くの無意味にょ。
表示の更新も1/60単位でしか行えないし、入力もBUTTON関数では1/60単位でないと取得が
できないからね。
20fpsで動作しているゲームが60fpsになるならばそれなりに有用だけどすでに60fpsで
動作しているゲームならばそこから何倍になろうと全く無意味ということにょ。
私が作ったものの中で30fpsさえ難しいものといえば公開済みのゲームでは存在せず
ツールとしては「ポリゴン表示プログラム」と「GRP2軸回転プログラム」のみがそれに
該当するにょ。
プチコン用 ポリゴン表示プログラム
http://ochameclub.web.fc2.com/petitcom/polygon.htm
プチコン用 GRP 2軸回転プログラム
http://ochameclub.web.fc2.com/petitcom/2rotate.htm
ポリゴン表示プログラムは私以外に動画で公開している人が2名、QRコードを公開している
人が1名いることは確認済みだけどプチコンでポリゴン表示というのはすごく重い処理であり
汎用性の高い書き方をしていたら速度が全然出ないため私はルーチンとしての再利用性や
可読性は無視して速度重視の設計となっているにょ。
しかし、これが限界かといえばそうではなくリストが長くなってもいいならばもう少し
速くすることが可能にょ。(短い方が速くなるというイメージを持っている人もいるかも
しれないけど実際はより汎用性を無視して少しでも速いプログラム書く場合にはリストは
逆に長くなってしまうことも多々ある)
真の限界に挑戦しなかったのは単にリストの長さとの割に合わないためにょ。
またZソートは簡易化すれば大幅に高速化できるけどそれだと空洞化したトライフォースの
ようなものは正しく表示ができないためやめたにょ。
表示を立方体のみにして限界まで高速化すればまったく同一機能を維持したままでここから
さらに1〜2割の高速化は可能にょ。(光源の位置変更やオブジェクトの拡大縮小を無くせば
さらに高速化は可能)
GRP2軸回転プログラムは1軸を固定(つまりカメラは地面に対して平行)にすればさらに速く
できるけどそれだと「2軸回転」にはならないためこのような手法を取っているにょ。
また限界まで高速化されているかというと実際はそうではなく見ての通りまだ速度面において
無駄が多いものになっているにょ。
これをさらに限界まで高速化すれば2軸回転を維持したままここからさらに2倍の速度にする
ことが可能にょ。(ただし、拡大率は8倍固定)
それを搭載したポリゴンキャラによるレースゲームも作ったもののコースのグラフィックが
粗すぎてスピード感が全然出ないため試作品の段階でボツにしたにょ。
(プチコン)3Dレースゲーム試作品
https://www.youtube.com/watch?v=hLr5VEevY9I
というわけで、私はポケコンと違って限界まで高速化したゲームを1作品も発表してない
ため高速化講座を書いても絵に描いた餅になりそうな感じにょ。
講座を書くならばポケコン用の「VS」が最終的に4.6倍速の「VSスーパーターボ」になった
ようにこのプログラムが講座に書いていることを実行すればこれだけ速くなるという例を
提示する必要があるからね。
しかも、上記のように60fpsを超えた部分は無意味になるので普通に書いて20fps以下くらいの
重いゲームが必要になってくるにょ。
そんな都合のいいゲームを作るのは難しいにょ(スプライトを大量に表示して重くするだけ
ならば補間処理だけで軽くなるため例としてはあまり良くないし)
まぁTipsコーナーとして高速化に役立つものを羅列するだけならば簡単なんだけどね。
その辺は需要に応じて考えようと思うにょ。
需要がほとんど無ければ今回を書いた内容で終わりになるかもしれないにょ(気が向いた
時に上記とほぼ同一内容をサイト上にまとめる程度)
|
|
|
掲示板管理者へ連絡
無料レンタル掲示板