DXライブラリミニテクニック


 ここではDXライブラリに関するちょっとしたテクニックや、 DXライブラリとはあんまり関係ないちょっとしたテクニックなどを紹介します。


 ウインドウモードで起動する

 ソフトのタイトルを変更する

 アーカイブ機能を使ってファイルを一つに纏める

 数値をグラフィックで表示する

 使えるC言語標準関数集

 ソフトが完成したらDebugビルドではなくReleaseビルドを行い処理速度の向上を図る

 自作ソフトにオリジナルアイコンを付ける

 BMPやWAVファイルだとデータが読まれてしまうので…

 裏画面のすすめ

 ゲームの進行速度とリフレッシュレート

 『前処理』のすすめ

 データ圧縮プログラムについてざっくり学ぶ

 乗算済みαのすすめ


 ウインドウモードで起動する

 DXライブラリは標準ではフルスクリーンモードで起動しますが、開発中では ウインドウモードで起動したい時があります。何故ならフルスクリーンモードでは デバッグ機能が全く使えないからです。


 とりあえず、ウインドウモードで起動するには DxLib_Init を呼んでいる行の前に

ChangeWindowMode( TRUE ) ;

 という記述を一行増やしてやるだけウインドウモードで起動する事が出来ます。


 ところで『デバッグ機能って何?』という方の為にちょっと説明しますと、例えば プログラムの実行を指定の個所で止めたり止めた時点での各変数の状態が見れたりと、 そんな感じの機能です。
 まだデバッグ機能を使った事が無い方は、とりあえず上記の様に DxLib_Init を呼んでいる 行の前に ChangeWindowMode( TRUE ) ; と記述して、Visual C++をお使いの方は、 何処か適当な行でキーボードのF9を押してからF5でソフトを起動してみてください、恐らくF9を 押した行でプログラムが止まるはずです。( Borland C++ での方法はちょっと下のほうに書いてあります)
 止まった時に Visual C++ 上にそれらしいウインドウが出現していれば問題あり ませんが、もし普段となにも変わらないウインドウしか表示されていなかったらメニューの 『デバッグ』→『ウインドウ』の中の『ローカル』『呼び出し履歴』辺りを表示させて みて下さい( VisualC++ 6.0 では『表示』→『デバッグウインドウ』の中の『変数』『コールスタック』)恐らく停止した関数内で宣言されている変数の値や、 止まった行に来るまでにどの関数を辿ってきたかを確認できると思います。

 この機能は非常に便利ですので、使った事がない方は是非使ってみてください。


 Borland C++ では、デバッグ機能が Borland C++ とは別のソフトとして存在しています。

 まず Borland のサイトで Turbo Debugger 5.5 という Borland C++ と同じく無償 配布されているソフトを以下のページの手順に従ってダウンロードします。(ユーザー登録が必要です)

http://www.borland.co.jp/cppbuilder/freecompiler/turbodebugger.html

 ダウンロードしたファイルを展開しようとするとパスワードを訊かれる以外に 展開するフォルダを聞いてきますので、Borland C++ Compiler 5.5 をインストール したフォルダを指定して下さい。

 問題なく展開された場合は Borland C++ Compiler 5.5 をインストールしたフォルダの 中の『bin』というフォルダの中に TD32.exe, TD32INST.exe, TD32HELP.TDH という ファイルが追加されます。

 次に BCC Developer のメニューから『ツール』→『環境設定』を開き 『コンパイラ設定』タグ『デバッガ』の項目に先ほどインストールした Turbo Debugger 5.5 を指定します、Borland C++ も Turbo Debugger も標準どおりの設定でインストール していたら C:\borland\bcc55\Bin\TD32.EXE 辺りになるはずです。
 選択が終了したら『設定』ボタンを押して環境設定ウインドウを閉じます。

 次に適当にデバッグしたいプロジェクトを開き、メニューから 『実行』→『デバッグ』を選んでデバッグモードで起動します。

 すると、Turbo Debugger が起動します。

 なお、Windows2000WindowsXP ではもしかしたら Turbo Debugger 上でのマウスの操作 が出来ないかもしれません。その場合は以下のことを試してください。

〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
 Turbo Debugger 5.5 のシステムバーで右クリックをして、メニューから 『プロパティ』を選んでプロパティダイアログを表示してください。
 開いたら『オプション』タグを選び、その中の『編集オプション』の中の『簡易 編集モード』にチェックが入っていたらチェックを外して『OK』を押して下さい。
 『OK』を押したときに『現在のウインドウだけに適応する』のか『同じタイトルの ウインドウに適応する』のか聞いてきますが、これは『同じタイトルのウインドウに適応する』 を選択して『OK』を押してください。

 これでマウスが効くようになると思います。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜

 さて、使い方です。
 私も殆ど知らないので最低限の使い方だけをご説明します。

 まず起動すると、初っ端からプログラムが止まっています。

 メニューの『Run』→『Run』を指定すると(又はF9キーを押すと)普通に実行が始まります。
 メニューの『Run』→『Step over』(又はF8)で一行だけ実行します、実行する一行の中で関数が 呼ばれていても関数の中はトレースせずに、次の行に移ります。
 メニューの『Run』→『Trace into』(又はF7)で同じく一行だけ実行しますが、実行する一行 の中で関数が呼ばれている場合は関数の中の最初の行に移ります。

 止まっている関数で宣言されているローカル変数を表示したい場合はメニューの『View』→『Valiables』を 選びます。するとプログラム中の全関数名が上部に、関数内で使用している変数の一覧が 下部に表示されたウインドウが開きます。
 グローバル変数(又は配列・構造体)を表示したい場合はメニューの『Data』→『Add watch...』 を選び、グローバル変数名を入力して『OK』を選びます。すると Turbo Debugger 画面の下部に ある『Watches』というウインドウの中に入力した変数の状態が表示されます。表示する行を 増やしたい場合は、ウインドウ枠の上部を左クリックで掴んで上に移動した後、右下の矢印以外の 部分を引っ張ります。『Watches』ウインドウが見当たらない時はメニューの『View』→『Watches』 を選びます。

 ブレイクポイント(何処でプログラムを止めるか、の指定)を設定するにはメニューの 『Breakpoints』→『Toggle』(又はF2)を選びます。(無効にしたい時も無効にしたい ブレイクポイントが設定されている行で『Breakpoints』→『Toggle』(又はF2)を選びます) (尚、残念ながら Visual C++ のようにプログラムの編集画面からブレイクポイントを設定する事は出来ません)
 設定したブレイクポイントを全て無効化したい場合は『Breakpoints』→『Delete all』を選びます。
 ブレイクポイントを設定したい行が別のファイルである場合はメニューの『View』→ 『Module...』(又はF3)を選んでブレイクポイントを設定したい行があるファイルを開きます。

 ブレイクしたところまでどの関数を辿ってきたかを知りたいときはメニューから『View』→ 『Stack』を選び、辿ってきた関数の一覧が表示されているコールスタックウインドウを開きます。
 どの行でその関数が呼ばれたのかを知りたい場合は、コールスタックウインドウ からその関数を選び、Enter キーを押します。するとその関数が呼ばれた行まで飛ぶ事が 出来ます。(別ファイルだった場合はそのファイルを自動的に開きます)

 BCC Developer のアウトプットウインドウに相当するウインドウはメニューの『View』→『Log』 を選ぶと開く事が出来ます。

 デバッグを終了したい場合はメニューの『File』→『Quit』を選びます。

 私が知っている事は大体この位です。
 残りの機能は皆さんが見つけてください。(^^;



 ソフトのタイトルを変更する

DXライブラリのソフトを起動すると、標準ではウインドウのシステムバーに表示される タイトルは『DxLib』になっています。これを変更するには関数リファレンスの『マイナー関数』 に分類されている SetWindowText という関数を使用します。  同じくソフトを起動すると必ず作成される AppLog.txt を作成しないようにするには SetOutApplicationLogValidFlag という関数を使用します。



 アーカイブ機能を使ってファイルを一つに纏める

 ゲーム中で使う画像は、出来ればゲーム画面以外では見れないようにしたいものですよね。
あと、ゲームで使うファイルも出来れば少なく済ませたいものです。

 そんな時に思いつくのが LzhZip 等の、ファイルを圧縮すると共に複数のファイルを一つに纏めてしまうアーカイバですが、 DXライブラリでは Lzh や Zip は使えません。

 ですが、DXライブラリには圧縮する機能が無いだけの似たようなアーカイブファイル『DXアーカイブ』 (そのまんまだ)を簡単に使うための機能がついています。

 以下はDXライブラリの圧縮ファイルの中にある、『Tool\DXArchive\readme.txt』の内容をそのまま貼り付けたものです。

--------------------------------
-
- DXアーカイブ説明書
-
- Version 1.01
-
--------------------------------

・概要

   lzhファイル や zipファイルのように、複数のファイルを
  一つのファイルに纏めるソフトです。(ただ纏めるだけなので
  lzh や zip の様に容量は小さくなりませんが)

   作成したアーカイブファイルはDXライブラリでも読み込めます。


・ファイル説明

  DxaEncode.exe   アーカイブファイルを作成するソフトです
  DxaDecode.exe   アーカイブファイルを元に戻すソフトです(多分あんまり使いません)

  Source
    DxaEncode.exeDxaDecode.exe のプログラムソースが入っています。
    (整理していないので汚いです・・・)


・使い方


 ・アーカイブファイルの作成方法と使用方法

   1.中身を一つに纏めたいフォルダDxaEncode.exeドラッグ&ドロップします
   2.フォルダ名と同じ名前のDXアーカイブファイルが、拡張子 dxa で作成されます
   3.DXライブラリはDXアーカイブファイルをフォルダとみなすので、例えば

   Image というフォルダから画像を読み込んでいたとします。

    <ファイル構成>
    実行ファイル
    Imageフォルダ(中にGraph1.bmpがある)

    GraphHandle = LoadGraph( "Image\\Graph1.bmp" ) ;


   この Image フォルダDxaEncode.exeドラッグ&ドロップして Image.dxa を
  作成し、Image.dxaImage フォルダ代わりに使うことが出来ます。

    <ファイル構成>
    実行ファイル
    Image.dxa

    GraphHandle = LoadGraph( "Image\\Graph1.bmp" ) ;


   因みに、DXアーカイブファイル名前を変更すると指定すべきフォルダ名も変わります。

    <ファイル構成>
    実行ファイル
    ImageGraphics.dxa

    GraphHandle = LoadGraph( "ImageGraphics\\Graph1.bmp" ) ;



 ・アーカイブファイルの展開方法

   1.DXアーカイブファイルを DxaDecode.exe にドラッグ&ドロップします
   2.DXアーカイブファイルがある位置と同じフォルダにDXアーカイブファイルの中身が展開されます


 デコーダがあるので暗号化の意味はちょっと薄いかもしれませんが、何もしないよりはずっとマシな筈です。

 尚、『拡張子が dxa のままは嫌』という方や、『常に dxa ファイルをフォルダに見なされると都合が悪い』 という方は、SetUseDXArchiveFlag関数SetDXArchiveExtension関数 をお使いください。

 また、このDXアーカイブに含まれた、DXライブラリの機能以外で使用するファイルにアクセスする場合は以下の関数をお使いください。 (DXアーカイブ無かった場合は勝手に通常のファイルを開くので、DXアーカイブ使う場合使わない場合で関数を使い分ける必要はありません)

  FileRead_open ファイルを開く
  FileRead_size ファイルのサイズを得る
  FileRead_close ファイルを閉じる
  FileRead_tell ファイルポインタの位置を得る
  FileRead_seek ファイルポインタの位置を変更する
  FileRead_read ファイルからデータを読み込む
  FileRead_eof ファイルの終端かどうかを調べる
  FileRead_gets ファイルから一行読み出す
  FileRead_getc ファイルから一文字読み出す




 数値をグラフィックで表示する

 数値表示や文字列表示は 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++のヘルプから検索して 見てください。


プロセス管理関係

( stdlib.h )
 exit ソフトを終了する


文字列操作

( string.h )
 strcpy 文字列のコピー
 strcat 文字列の追加
 strcmp 文字列の比較
 strchr 文字の検索
 sprintf 書式付き文字列出力を行う


ファイル操作

 ( stdio.h )
 fopen ファイルを開く
 fclose ファイルを閉じる
 fwrite ファイルにデータを書き出す
 fread ファイルのデータを読み出す
 fseek ファイルのデータ操作位置を変更する

 ( direct.h )
 _chdir カレントディレクトリ(フォルダ)を変更する
 _getcwd 現在のカレント ディレクトリ(フォルダ)を取得する。
 _mkdir ディレクトリを新規作成する。
 _rmdir ディレクトリを削除する。
 _searchenv 指定されたパスで指定されたファイルを検索する。

※…関数の前に『_』がついているのは使用を推奨されていない関数ですが、 推奨されていないだけで問題なく使えるので使いましょう。
例( _getcwd は WindowsAPIの GetCurrentDirectoryの使用を進められている)


メモリ関係

 ( malloc.h と stdlib.h )
 malloc メモリを確保する
 free 確保したメモリを解放する

 ( string.h )
 memcpy メモリをコピーする
 memset 1バイトの値で指定メモリ領域を埋める
 memmove 指定領域のメモリを別のアドレスへ移動する


数学

 ( math.h )
 abs 絶対値を得る
 fabs double型などの絶対値を得る
 fmod double型での商の余りを得る
 pow べき乗する(2乗、3乗など)
 sqrt 平方根を得る

 sin サインを計算する
 cos コサインを計算する
 tan タンジェントを計算する
 asin アークサインを計算する
 acos アークコサインを計算する
 atan アークタンジェントを計算する

 ( stdlib.h )
 rand 乱数を得る
 srand 乱数ジェネレータを初期化する



 標準関数を使うことはすなわちOSに依存する部分を全く考慮しないことになるので、特にファイル関係の 標準関数の使用は望ましくないとされるのが一般ですが、ゲーム中のデータのセーブなどの単純で一時的な ファイルの操作では全く問題にはなりません。



 ソフトが完成したらDebugビルドではなくReleaseビルドを行い処理速度の向上を図る

 ソフトの開発中はおそらくデバッグスタート(F5で実行)をしていると思いますが、いえ デバッグ機能を使っていなくてもデバッグスタートが出来る実行可能ファイルとしてビルドされますが、 こうして出来る実行可能ファイルはデバッグ用の情報を多く含むのでその情報をいれない時に比べて 200KBほどファイルの容量が増えてしまいます。(処理速度も落ちます)
 そこで、ソフトが完成したらリリースビルドという、デバッグ情報を含まない実行可能ファイルを ビルドすることで容量の縮小及び処理速度の向上をすることが出来ます。
 方法はまずメニューの『ビルド』→『アクティブな構成の設定』を開きます、すると『〜〜Debug』『〜〜Release』がリストの中に表示されていて、おそらく『〜〜Debug』のほうが選択されていると 思いますので、ここでもう一つの『〜〜Release』の方を選択してOKボタンを押します。これでもう一度 ビルドするとリリースビルドされた実行可能ファイルが出来ます。



 自作ソフトにオリジナルアイコンを付ける

 自作ソフトの実行可能ファイルのアイコンを独自で作ったアイコンにしたい、という場合の方法です。 完全に私が導き出した方法ですのでもっと良い方法があると思うのですが、調べるのが面倒ですし私は この方法で満足しているので、もし『これの方が楽じゃん』というご意見のある方はどうかご一報下さい。


BorlandC++ Compiler 5.5  の場合

 まず縦横32ドット、256色(8ビット)のアイコンファイル(拡張子『ico』)を作成し、BCC Developer のプロジェクトファイル(拡張子『bdp』)が あるフォルダに保存します。(『アイコン用ユーティリティ』等でWEB検索するとアイコンを作成するためのソフトが色々見つかります)
 次に同様にプロジェクトファイルがあるフォルダに『Resource.rc』というファイルを作成し、 (エクスプローラのフォルダオプションで『登録されている拡張子は表示しない』のチェックを外しておいてください) そのファイルをメモ帳等のテキストエディタで中身に次のように入力して保存して下さい。

MAINICON ICON "ここにアイコンファイルのファイル名"

 次に プロジェクトを BCC Developer で開き、『プロジェクト』→『プロジェクトの設定』で プロジェクトの設定ダイアログを表示し、その中の『リソーススクリプト』タグの中の 『リソーススクリプトファイル名』の欄に Resource.rc と 記述した上で『設定』ボタンを押してダイアログを閉じて下さい。
 これで、次にビルドした時には作成される実行可能ファイルのアイコンがオリジナルのアイコンになります。


VisualC++ 2005 Express Edition の場合

 VisualC++ 2005 Express Edition(以後VisualC++2005EE)でアイコンを付ける方法は、 まず縦横32ドット、256色(8ビット)のアイコンファイル(拡張子『ico』)を作成し、VisualC++2005EE のプロジェクトファイル(拡張子『sln』)が あるフォルダに保存します。(『アイコン用ユーティリティ』等でWEB検索するとアイコンを作成するためのソフトが色々見つかります)
 次に同様にプロジェクトファイルがあるフォルダに『Resource.rc』というファイルを作成し、 (エクスプローラのフォルダオプションで『登録されている拡張子は表示しない』のチェックを外しておいてください) そのファイルをメモ帳等のテキストエディタで中身に次のように入力して保存して下さい。

MAINICON ICON "ここにアイコンファイルのファイル名"

 次に プロジェクトを VisualC++2005EE で開き、『プロジェクト』→『既存項目の追加』で 追加ファイル選択ダイアログを表示して、先ほど作成した『Resource.rc』をプロジェクトに追加します。
 これで、次にビルドした時には作成される実行可能ファイルのアイコンがオリジナルのアイコンになります。


VisualC++.NET の場合

 まず縦横32ドット、256色(8ビット)のアイコン用ビットマップを作成します。(どんな グラフィック作成ツールでも大丈夫です)このとき真っ白の色が透過色(透き通る色)になりますので 覚えておいてください。
 次にVisualC++.NETのメニューの『開く』→『ファイル』を選び、『ファイルの種類』『すべてのファイル』に変更し、 アイコン用ビットマップファイルを開きます。
 開いたら次にメニューの『イメージ』→『パレットの保存』で適当な場所にパレットファイルを保存します。
 更にそのまま次にメニューの『編集』→『コピー』を選びグラフィックデータをクリップボードに退避します。
ここまでの作業が終了したらビットマップファイルは閉じてしまって結構です。
 次にメニューの『プロジェクト』→『リソースの追加』を開き、その中の『Icon』をダブルクリックし、 アイコンリソースを追加します。
 次にメニューから『イメージ』→『パレットの読みこみ』で先程保存したパレットファイルを読みこみます。
 次にメニューの『編集』→『貼りつけ』でクリップボードに先ほど退避したアイコン用 グラフィックを貼りつけます。  最後に『ファイル』→『すべて保存』を実行してアイコンの追加作業は完了です。
 これで再びビルドすれば実効可能ファイルのアイコンがオリジナルのアイコンになります。


VisualC++6.0 の場合

 まず縦横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進数で 424D 、10進数でいう 6677 になっています。この数値を 別の数値、例えばどちらも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』という文字列があります、こちらも 同様の方法で開けるのを防ぐことが出来ます。



 裏画面のすすめ

 DXライブラリを含め、ゲームでは主にグラフィックの描画は裏画面に施し(普通裏画面とは言いませんが…) すべての描画処理が終った後に表画面に裏画面の内容をコピー、又は交換することによって描画結果を反映させます。


 何故このようなことをするのかといいますと、もし表画面、つまりプレイヤーが常に目にしている画面に直接描画処理を 施した場合、画面が出来あがってゆく過程がプレイヤーの目に写ることになります。そしてゲームの画面は一般的に 1秒間に60回ほど画面の内容を更新するのでそれは結果的に『画面がちらついて見苦しい』ことに繋がります。
 ですので描画処理自体はプレイヤーの見えないところで行い、画面の更新処理が終った後にプレイヤーの見ている 表画面に写すことによってそのちらつきを無くしているのです。


 さてその裏画面ですがDXライブラリでは SetDrawScreen 関数と 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回更新されるまでの時間がかかることになります。つまりこれを利用して画面表示内容が一回更新される までに経過している時間を取得する、というわけです。

 具体的には一定時間( 以下のサンプルでは0.5秒 )ScreenFlip を実行し続け、時間内に実行できた ScreenFlip の回数と、 計測時間から一回画面が更新されるに当たりどれだけ時間が経過しているかを計測します。
 プログラムとしては以下のようになります。

	int FrameTime, ScreenFlipCount, StartTime ;

	// ScreenFlip を実行した回数を数えるカウンタを初期化
	ScreenFlipCount = 0 ;

	// 画面が1回更新されるまで待つ
	ScreenFlip() ;

	// 計測開始時刻を保存
	StartTime = GetNowCount() ;

	// 0.5秒間に実行できる ScreenFlip の回数を計測
	for(;;)
	{
		// 画面が1回更新されるまで待つ
		ScreenFlip() ;

		// 計測開始から0.5秒経過していたらループから抜ける
		if( GetNowCount() - StartTime >= 500 )
			break ;

		// ScreenFlip を実行した回数をインクリメント
		ScreenFlipCount ++ ;
	}

	// ScreenFlip を実行した回数と計測時間から画面一回更新辺りの時間を算出する
	FrameTime = 500 / ScreenFlipCount ;


 GetNowCount 関数は1000分の1ミリ単位のカウントを返すので、このプログラムで得られる1リフレッシュ当たりの 時間もミリ秒単位の値となります。更に精度を求める場合は GetNowHiPerformanceCount 関数を使用します。
 では得られた1リフレッシュ当たりの時間を使用してキャラクターの移動処理を行うにはどうすればよいか、ですが この当たりは説明されてもピンとこないと思いますのでサンプルプログラムコーナーの例を参照して下さい。



 『前処理』のすすめ

 DXライブラリでは DxLib_Init 関数の前に行える処理が幾つかあります。

 ChangeWindowMode , SetGraphMode , SetScreenMemToVramFlag ,
SetOutApplicationLogValidFlag , SetWindowText

 上記の関数は DxLib_Init 関数を使用する前に呼び出すことでそれぞれ、最初からウインドウモードとして
起動
したり、最初から指定の画面モードで起動したり、 最初から3Dグラフィックアクセラレータを使わない設定にしたり、 AppLog.txt を作らない設定にしたり、 ウインドウのシステムバーに書かれるタイトルを『DxLib』以外に変更したり することが出来ます。


 仕様例(最初からウインドウモードで起動)
// DxLib_Init 呼び出し前にウインドウモードに設定
ChangeWindowMode( TRUE ) ;

// その後 DxLib_Init を呼び出す
if( DxLib_Init() == -1 )
{
	// エラー発生時の処理
	return -1 ;
}



 データ圧縮プログラムについてざっくり学ぶ

 圧縮という言葉は聞いたことがあると思います。というかDXライブラリ自体圧縮されて 配布されていますし、そもそも『プログラムをしよう』と思い立った方が『圧縮』をしらない 可能性は低いと思うので、圧縮についての説明は割愛します。

 ともあれ、その『圧縮』をするプログラムについてざっくり学んでみたいという方向けの 説明ページを作ってみましたので、興味のある方は

   こちらをどうぞ

 内容は主に

・BMPやWAVなどの生データを晒したくないが晒さない手段を知らない
・晒さない手段としてヘッダの一部を書き換えたり拡張子を変えるといった方法は使いたくない
・圧縮プログラムを組んだことは無いが興味はある
・組んだことはあるがランレングス圧縮くらいしかない

 という方向けです。


戻る