| DXライブラリ FAQ & ミニテク | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
ここではDXライブラリに関する質問に対するQ&A形式の回答や、ゲームプログラム 及びDXライブラリに関するミニテクを掲載します。 FAQ Q:フルスクリーンだとデバッグしにくいのでウインドウモードで開発したいのですが… A:ChangeWindowMode という関数を使えばウインドウモードでソフトを起動できます。 Q:ウインドウモードで起動するとウインドウのタイトルが『DxLib』になっているので 自分の好きなタイトルに変更したいのですが… A:SetWindowText という関数を使えばウインドウのタイトルを変更することが出来ます。 ミニテクニック 数値をグラフィックで表示する 使えるC言語標準関数集 ソフトが完成したらDebugビルドではなくReleaseビルドを行い処理速度の向上を図る 自作ソフトにオリジナルアイコンを付ける BMPやWAVファイルだとデータが読まれてしまうので… BMPのデータ容量を減らす 裏画面のすすめ ゲームの進行速度とリフレッシュレート DXライブラリ、『前処理』の進め FAQ 現在はまだ質問はありません。 ミニテクニック 数値をグラフィックで表示する 数値表示や文字列表示は DrawString で行うわけですが、ゲーム中のスコア表示などは1色の 標準フォント数字ではなく独自に用意した数字グラフィックを使いたいものです。 そこでまず数字グラフィックを用意します、数字グラフィックは左から0から9までの数字 が等間隔で描かれた横長のグラフィックです。ペイントでもなんでも良いので用意してください。 (DXライブラリについて来る『Sample実行用フォルダ』フォルダに『Num.bmp』というサンプルのグラフィックが ありますのでそちらを使って頂いてもOKです) 次にそのグラフィックを LoadDivGraph関数で分割読み込みをします。一つのBMPファイルを いくつかのグラフィックに分割してロードするときに使う関数です。 えー、あとは以下のプログラムを参考にしてください。(無責任)
#include "DxLib.h"
#define WIDTH 24 // 数字グラフィック横幅
#define HEIGHT 24 // 数字グラフィック高さ
int NumHandle[ 10 ]; // 数字グラフィックの識別番号を保存する配列
// 数値をグラフィック表示する関数
void NumDraw( int Num ) ;
// WinMain関数
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
if( DxLib_Init() == -1 ) // DXライブラリ初期化処理
{
return -1; // エラーが起きたら直ちに終了
}
// 数字グラフィックを分割読みこみ
// 分割数は全部で10こ、1列当たり10個の分割数でそれが1行だけあるので
// 以下のような記述になります。
LoadDivGraph( "Num.bmp" , 10 , 10 , 1 , WIDTH , HEIGHT , NumHandle ) ;
// 数値256をグラフィック数字で表示
NumDraw( 256 ) ;
// キー入力待ち
WaitKey() ;
DxLib_End() ; // DXライブラリ使用の終了処理
return 0 ; // ソフトの終了
}
// 数値をグラフィック表示する関数
void NumDraw( int Num )
{
int i , BeamWidth , x ;
// Numが十進数で何桁になるか調べる
BeamWidth = 0 ;
for( i = 10 ; Num >= i ; i *= 10 ) BeamWidth ++ ;
// 画面左上にグラフィックで描画
// x は数字グラフィックを描く矩形の左端の座標です
x = BeamWidth * WIDTH ;
for( i = 0 ; i <= BeamWidth ; i ++ )
{
// 数字の描画(透過色あり)
// NumHandle 配列には要素番号0には『0』のグラフィック識別番号が
// 1には『1』のグラフィック識別番号が入っているので、
// DrawGraph( 0 , 0 , NumHandle[ 0 ] , TRUE ) ; とすれば
// 『0』のグラフィックを描画できることをお忘れなく
DrawGraph( x , 0 , NumHandle[ Num % 10 ], TRUE ) ;
// 描画X座標を移動
x -= WIDTH ;
// 1番下の桁が描画し終わったので一桁下げる
Num /= 10 ;
}
}
使えるC言語標準関数集 コンソールアプリケーションではない Windows環境でのプログラムでも使えるC言語標準関数は 沢山あります、ですがそれらの関数はあまり公には広まっていません。それはおそらくVisualC++に 本の形での標準関数リファレンスがないからだと思いますが、とにかくあまりVisualC++のヘルプから 標準関数の項目をめくる人はいないと思います。 とりあえずヘルプ中のどの場所に標準関数のことが書かれているか以下にしめします。 メニュ−の『ヘルプ』→『目次』でヘルプを開く。 開いたら左の目次タグから『MSDNライブラリ Visual Studio 6.0』→『Visual C++ ドキュメント』 →『Visual C++ ユーザーズガイド』→『Visual C++ プログラマーズガイド』→『ランタイムライブラリ リファレンス』→『カテゴリ別ランタイムルーチン』を開いていきます。この『カテゴリ別ランタイムルーチン』 の項目が主にC言語標準関数の説明となります。(なんでこんなにわかりにくいところにあるんだろう…) 次にとりあえず私が使えると思うC言語標準関数を紹介します。詳しい説明はVisualC++のヘルプから検索して 見てください。
標準関数を使うことはすなわちOSに依存する部分を全く考慮しないことになるので、特にファイル関係の 標準関数の使用は望ましくないとされるのが一般ですが、ゲーム中のデータのセーブなどの単純で一時的な ファイルの操作では全く問題にはなりません。 ソフトが完成したらDebugビルドではなくReleaseビルドを行い処理速度の向上を図る ソフトの開発中はおそらくデバッグスタート(F5で実行)をしていると思いますが、いえ デバッグ機能を使っていなくてもデバッグスタートが出来る実行可能ファイルとしてビルドされますが、 こうして出来る実行可能ファイルはデバッグ用の情報を多く含むのでその情報をいれない時に比べて 200KBほどファイルの容量が増えてしまいます。(処理速度も落ちます) そこで、ソフトが完成したらリリースビルドという、デバッグ情報を含まない実行可能ファイルを ビルドすることで容量の縮小及び処理速度の向上をすることが出来ます。 方法はまずメニューの『ビルド』→『アクティブな構成の設定』を開きます、すると『〜〜Debug』と 『〜〜Release』がリストの中に表示されていて、おそらく『〜〜Debug』のほうが選択されていると 思いますので、ここでもう一つの『〜〜Release』の方を選択してOKボタンを押します。これでもう一度 ビルドするとリリースビルドされた実行可能ファイルが出来ます。 自作ソフトにオリジナルアイコンを付ける 自作ソフトの実行可能ファイルのアイコンを独自で作ったアイコンにしたい、という場合の方法です。 完全に私が導き出した方法ですのでもっと良い方法があると思うのですが、調べるのが面倒ですし私は この方法で満足しているので、もし『これの方が楽じゃん』というご意見のある方はどうかご一報下さい。 でははじめます、まず縦横32ドット、256色(8ビット)のアイコン用ビットマップを作成します。(どんな グラフィック作成ツールでも大丈夫です)このとき真っ白の色が透過色(透き通る色)になりますので 覚えておいてください。 次にVisualC++のメニューの『開く』を選び、『ファイルの種類』を『すべてのファイル』に変更し、 アイコン用ビットマップファイルを開きます。 開いたら次にメニューの『イメージ』→『パレットの保存』で適当な場所にパレットファイルを保存します。 更にそのまま次にメニューの『編集』→『コピー』を選びグラフィックデータをクリップボードに退避します。 ここまでの作業が終了したらビットマップファイルは閉じてしまって結構です。 次にメニューの『挿入』→『リソース』を開き、その中の『Icon』をダブルクリックし、リソース ウインドウを開きます。次に、開いたアイコンエディットウインドウの『標準(32x32)』とかかれている部分の すぐ右にあるボタンを押し、『アイコンイメージの新規作成』ウインドウを開き、リストの中から『32x32.256色』 を選びOKを押します。 そして今度はメニューの『編集』→『貼りつけ』でクリップボードに先ほど退避したアイコン用 グラフィックを貼りつけます。次にメニューから『イメージ』→『パレットの読みこみ』で こちらも先ほど保存したパレットファイルを読みこみアイコン作成作業は完了です。 次に『ファイル』→『すべて保存』を選択するとどこにリソーススクリプトファイルを保存するか 聞いてきますのでどこかに保存してください。 そして最後に『プロジェクト』→『プロジェクトへ追加』→『ファイル』を選択し、保存したリソーススクリプトファイル (Script.rc等)をプロジェクトに追加します。 これで再びビルドすれば実効可能ファイルのアイコンがオリジナルのアイコンになります。 BMPやWAVファイルだとデータが読まれてしまうので… 折角ソフトを作って配布しても、グラフィックデータや音楽データがBMPやWAVファイル形式だと簡単に エピローグに流そうとした音楽やグラフィックが見られてしまう。いやそれでも見てしまおうという人は少ない とは思いますが、見ようと思えば苦労せずともいつでも見れてしまうのはプレーヤーとしても張り合いがないものです。 そこでどのソフトも大抵は容易には鑑賞できないようにデータを加工するのですが、このライブラリには 独自のグラフィック形式等はなく、BMPやWAV形式しか扱うことが出来ません。(作る予定もありませんし なによりそれが私の嫌う『ライブラリ独自の規則』になるのが嫌だからです) ではどうすれば容易には見れないように出来るでしょうか? 一つ提案します、ファイルの拡張子を『bmp』や『wav』ではなく『gph』や『snd』などの拡張子に変更して 見たらどうでしょう? まず拡張子とはファイル名の後ろについている通常三文字のファイル識別文字列のことです。これはWindowsの 標準の設定ではおそらく見えなくなっていると思いますので、その場合はWindows98の場合しかわかりませんが デスクトップの『スタート』→『設定』→『フォルダオプション』を開き『表示』タグの中の『登録されている ファイルの拡張子は表示しない』のチェックを外して拡張子を見れるようにしてください。 ではとりあえずビットマップファイルの拡張子『bmp』を『gph』にしてみましょう、こんなもので平気なのか? と思われるかもしれません、実際Windows標準グラフィックエディタのペイントで開くと見れてしまいます。しかし! もしあなたがゲームをダウンロードした時、グラフィックデータが『gph』などという聞いたこともないファイル形式 だった場合「もしかしたらBMPデータかも」などと思って開いてみようと思うでしょうか?おそらくそのようには 思わないでしょう。因みに拡張子がどうであれ、ライブラリはきちんとロードできます。 この方法だけでほぼ98%の機密保持の確保はできたと思います。しかしこれでは物足りないという方はもう一つ 踏みこんだ方法をお教えします。 それは各データファイルの先頭のファイル識別文字列を変更してしまうことです。 具体的な方法はBMPファイルを例に挙げて説明します。 まずVisualC++で『ファイル』→『開く』で、『用途』を『バイナリ』にしてからビットマップファイルを開いて みましょう。すると1番左にファイルのデータ番地、真中にデータの16進数値表示、1番右にテキスト文字が 表示されると思います。そこで右のテキスト文字部分の1番左上の2文字を見てみましょう。 『BM』と書かれているはずです。これはビットマップファイル形式のファイルはファイルの先頭2バイトに『BM』という文字を あらわす数値が配置されていなければならないという決まりがありまして、その数値とは真中のデータの16進数値 表記を見ればわかると思いますが、16進数で 42 と 4D 、10進数でいう 66 と 77 になっています。この数値を 別の数値、例えばどちらも0にしてしまって上書き保存してみましょう、おそらくどのエディタでも開くことは 出来ないはずです。(そのデータを無視するエディタなら開けるでしょうが…) この方法を使ってすべてのグラフィックデータの先頭2バイトを変更してしまい、グラフィックをロードする前に 『BM』に直してやる、といった方法を使い、先ほどの方法と2段構えにすればほぼ100%の機密保持の確保を出来たと 思います(データ解析のマニアにかかればいちころですが、マニアの目に付くほどのソフトを開発できるようになった ころにはもっとよい方法を独自に見つけ出すことが出来ることでしょう) では『先頭2バイトを元に戻しロードする』という具体的なプログラムを以下にしめします。 例ではtest.gphという、実はBMPファイル形式のファイルの先頭2バイトを元に戻して読みこみ、その後再び 先頭2バイトを適当な文字で埋めます。(ファイルの扱いにはC標準ライブラリを使います)
#include <stdio.h>
#include "DxLib.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
FILE *fp ;
int GHandle ;
if( DxLib_Init() == -1 ) // DXライブラリ初期化処理
{
return -1; // エラーが起きたら直ちに終了
}
// ファイルを書きこみ専用でオープン
fp = fopen( "test.gph" , "r+b" ) ;
// ファイルの先頭2文字を変更
fwrite( "BM" , sizeof( char ) , 2 , fp ) ;
// ファイルを閉じる
fclose( fp ) ;
// グラフィックを改めて読みこむ
GHandle = LoadGraph( "test.gph" ) ;
// ファイルを書きこみ専用でオープン
fp = fopen( "test.gph" , "r+b" ) ;
// ファイルの先頭2文字を変更
fwrite( " " , sizeof( char ) , 2 , fp ) ;
// ファイルを閉じる
fclose( fp ) ;
// 読みこんだグラフィックを描画
DrawGraph( 0 , 0 , GHandle , FALSE ) ;
// キー入力待ち
WaitKey() ;
DxLib_End() ; // DXライブラリ使用の終了処理
return 0 ; // ソフトの終了
}
このプログラムを参考にして実践してみてください。 因みにWAVファイルやAVIファイルは先頭に『RIFF』という文字列があります、こちらも 同様の方法で開けるのを防ぐことが出来ます。 BMPのデータ容量を減らす インターネットなどでソフト公開を考える場合にはソフトの全データ容量は出切るだけ小さくすることを考えなければなりません。 そこで容量の大半を占めるグラフィックデータを出来るだけ減らす方法を紹介します。 まずDXライブラリ本来の力を存分に使いたい場合は16ビットカラー以上を使うことになりますが、BMPファイルは 8ビットカラー(256色)形式でも24ビットカラー(フルカラー)形式でも問題なくロードできます(16色、2色形式 のBMPファイルもある)。ということはフルカラーのBMPファイルを使うより256色、あるいはもっと少ない16色、 2色形式のBMPを使うことによってデータ容量を一気に2分の1、4分の1に減らすことが出来るということです!これは 素晴らしい! ですが綺麗なCGなどをゲーム中に載せたい場合、最近では256色、又はそれ以下の色数を使った環境でCGを製作することは ほとんどありえませんし、256色等で綺麗なCGを描くには多大な時間がかかります。 そこで登場するのが『減色』です。 減色とはそのまま、CGに使われている色の数を減らすことです。減らすのですから当然CGはもとより汚くなります。ですから 出来るだけもとの状態を保ったまま減食することが求められます。 フォトショップ等にも減色機能はありますが、あまり性能がいいとはいえないので こちらのページ の Padie という減色ソフトをダウンロードし、使って減色してみてください。無料である程度のクオリティを持っています。 さてフルカラーから256色またはそれ以下に減色したことにより容量はかなり減らすことが出来たとは思いますが、 これを更に減らす方法として、RLE圧縮という方法があります。これはBMPファイル形式の中の圧縮機構なのですが、 これを行うことによりさらに容量を減らすことが出来ます。 しかし、先ほど紹介した Padie やペインタではRLE圧縮を施したBMP保存には対応していないので、また別のソフトを 使用することになります。そこで再び先ほどのページから今度は Bmp To Bmp というソフトをダウンロードし、使ってみてください。 このソフトはBMPファイルをRLE圧縮を施して保存をするという機能を持ったソフトです。ただし注意ですがこのソフト にも減色機能はありますが、性能は Padie に比べると多少劣るので減色を Padie で行い、そのあとBmp To Bmp で RLE圧縮保存する、という形を取ってください。これによりグラフィックの容量はかなり減るはずです。 裏画面のすすめ DXライブラリを含め、ゲームでは主にグラフィックの描画は裏画面に施し(普通裏画面とは言いませんが…) すべての描画処理が終った後に表画面に裏画面の内容をコピー、又は交換することによって描画結果を反映させます。 何故このようなことをするのかといいますと、もし表画面、つまりプレイヤーが常に目にしている画面に直接描画処理を 施した場合、画面が出来あがってゆく過程がプレイヤーの目に写ることになります。そしてゲームの画面は一般的に 1秒間に60回ほど画面の内容を更新するのでそれは結果的に『画面がちらついて見苦しい』ことに繋がります。 ですので描画処理自体はプレイヤーの見えないところで行い、画面の更新処理が終った後にプレイヤーの見ている 表画面に写すことによってそのちらつきを無くしているのです。 さてその裏画面ですがDXライブラリでは SetDrawSceen 関数と ScreenFlip 関数によって裏画面処理手段を提供しています。 SetDrawScreen 関数は各種描画関数の描画先を表画面にするのか、裏画面にするのかを決めることが出来、 ScreenFlip 関数で裏画面に描画された内容を表画面に反映させることが出来るようになっています。 使用例のプログラムは各関数のサンプルプログラムを参照して下さい。 ゲームの進行速度とリフレッシュレート ゲームの進行速度 ゲームのアクションゲームなどではなぜキャラクター達が滑らかに移動しているように見えるのか、それは 直感的に説明すれば少しだけ動かしては表示し、また少しだけ動かしては表示する、というものを繰り返して いるからですが、ではひとつの『少しだけ動かす』作業のうちに現実ではどれほどの時間が経過しているの でしょうか? 当然何の処理もせず『少しだけ動かして表示』を繰り返せば、それはパソコンの性能と1フレーム(コマ)当たりに かかっている作業量に比例します。つまり性能のよいパソコンではキャラクターは速く動き、悪いパソコンでは 遅く、さらに画面上に出ているキャラクターの数でも動きの速さは変わってしまいます。 これはとてもよろしくありません。 そこで一般では『1フレーム当たりどのくらいの時間が経過するか』または『1フレーム処理する間にどの 程度時間が経過したか』などを決め、又は取得し、それに応じてゲームの進行速度を一定に保つようにする処理を 施します。 コンシューマゲーム機のゲーム(TVゲーム)の場合 家庭用テレビで稼動するTVゲームでは1フレーム当たり60分の1秒経過することを前提にゲームを設計します。 何故なら家庭用テレビでは1秒間に60回画面の表示内容が更新されるからです。(厳密には半60ですがここで の説明は割愛します)画面の秒間更新回数が60なのに対してゲームの1フレーム当たりの経過時間を60分の1 以下にしてもタイミングが合わないので色々と都合が悪いのは説明無しでわかると思います。 パソコンのゲームの場合 ではパソコンの場合は、といいますとディスプレイの1秒間あたりの更新回数(リフレッシュレートといます)は 可変で固定ではありません、つまり60の場合もあれば80や120の時もあるのです。 リフレッシュレートは皆さんも知ってのとおり設定で変更することは可能ですが『このゲームをやる時はリフレ ッシュレートを60にしてプレイしてください』というのはあまり現実的ではありません。ですのでTVゲームと は逆にこちらがリフレッシュレートに合わせてゲームの1フレーム当たりの経過時間を変更してやる必要があります。 そうするにはどうすればよいか、をこれから説明します。 まず画面が1回更新されるのに何秒、いえ何ミリ秒経過しているかを得る必要があります。それを実現するには DXライブラリの ScreenFlip 関数を使用します。関数の説明にはありませんが、実はこの関数で裏画面の 内容が表画面へ反映されるときは、ディスプレイが画面の表示内容更新を終了した後という決まりがあるので1回 ScreenFlip 関数を使用した後にすぐまた ScreenFlip 関数を使用すれば関数から処理が戻ってくるまでに 画面が1回更新されるまでの時間がかかることになります。つまりこれを利用して画面表示内容が一回更新される までに経過している時間を取得する、というわけです。 具体的には1回のサンプルでは不安定なので、30回ほど時間を計測し、その合計の平均を取ることになります。 プログラムとしては以下のようになります。
int FreamTime , OldTime , NowTime ;
// 画面が1回更新されるまで待つ
ScreenFlip() ;
// 1フレームにかかる時間を計測
FreamTime = 0 ;
OldTime = GetNowCount() ;
for( i = 0 ; i < 30 ; i ++ )
{
ScreenFlip() ; // 画面が1回更新されるまで待つ
NowTime = GetNowCount() ; // 現在の時間を得る
FreamTime += NowTime - OldTime ; // 経過時間を加算する
OldTime = NowTime ; // 今回取得した時間を保存する
}
FreamTime /= 30 ; // 30回採取した経過時間の平均を取る
GetNowCount 関数は1000分の1ミリ単位のカウントを返すので、このプログラムで得られる1リフレッシュ当たりの 時間もミリ秒単位の値となります。更に精度を求める場合は GetNowHiPerformanceCount 関数を使用します。 では得られた1リフレッシュ当たりの時間を使用してキャラクターの移動処理を行うにはどうすればよいか、ですが この当たりは説明されてもピンとこないと思いますのでサンプルプログラムコーナーの例を参照して下さい。 DXライブラリ、『前処理』の進め DXライブラリでは DxLib_Init 関数の前に行える処理が幾つかあります。 SetScreenMemToVramFlag , ChangeWindowMode , SetGraphMode , SetUse3DFlag 上記の関数は DxLib_Init 関数を使用する前に呼び出すことでそれぞれ、最初からウインドウモードとして 起動、最初から指定の画面モードで起動、最初から3Dグラフィック描画エンジン仕様の有無をセット、することが出来ます。 特にデバッグ中で初期状態でウインドウモードで起動したい場合などに重宝します。 なお SetUse3DFlag 関数の前処理により3Dグラフィック描画エンジンを使用しないよう設定した場合は 特例として後に SetUse3DFlag 関数で3Dグラフィック描画エンジンの使用を有効にすることが出来ません ので注意してください、逆にいえば、DXライブラリが2D専用として初期化されるので DxLib_Init 呼出し後 に SetUse3DFlag 関数により3D描画機能を無効にした場合よりもより安定した動作が望めますので、2D描画 機能のみを使用するゲームでは必ず3D描画機能無効設定の前処理をすることをお勧めします。 仕様例(最初からウインドウモードで起動)
// DxLib_Init 呼び出し前にウインドウモードに設定
ChangeWindowMode( TRUE ) ;
// その後 DxLib_Init を呼び出す
if( DxLib_Init() == -1 )
{
// エラー発生時の処理
return -1 ;
}
戻る | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||