久しぶりにDXライブラリ触ってて、オブジェクトの制御をLuaでやろうと思って少し躓いたのでメモ。
以前Seleneでやったことだけど。
前提として、
・LuaJITを使う(ゲームのつもりなので速度優先のため)
・DLLじゃなくexeに組み込み(なのでstaticなlib)
・開発環境はVC++2010 Express
LuaJITのビルド
まずはLuaJITのソースをダウンロードしてくる。
The LuaJIT Project の左メニューのDownloadから、好きなバージョンを選ぶ。
Windowsでの開発なのでzipのほうが楽だと思われ。
バージョンは現時点で2.0.0-beta8まであるけど、まぁβって書いてあるとおりなので安定性とかお察し。
今のところ妙な不具合は無さそうだけど。
安定性を求めるなら1.1.7のがいいんじゃね?
速度は2.0.0のが早いみたいだけどね。比較ページ参照
とりあえず今回は2.0.0-beta7で進めます。beta8はhotfix当てるのメンドイので。
1.1.7でも違いは無いと思われ。1.x.xだとバッチファイルじゃなくてmakefileしかないからメンドクサイことに。
ソースをDLしたら解凍する。
どこに解凍してもいいけど、なるべく浅くて日本語じゃないフォルダが安全。
ここでは仮にCドライブ直下にしようか。
解凍したら、解凍フォルダのsrcフォルダを開く。
ここで注意。DXライブラリ用に少しだけ手を加えます。
srcフォルダ内のmsvcbuild.batをテキストエディタで開いて、17行目辺りにあるコンパイルオプション少しだけ書き換えます。
@set LJCOMPILE=cl /nologo /c /MD /O2 /W3 /D_CRT_SECURE_NO_DEPRECATE
↓
@set LJCOMPILE=cl /nologo /c /MT /O2 /W3 /D_CRT_SECURE_NO_DEPRECATE
/MDだとDLL用のコンパイルになってしまって、このままだと
error LNK2005: _exit は既に LIBCMTD.lib(crt0dat.obj) で定義されています。
みたいなリンクエラーが出てしまうので、作成するexeのほうのプロジェクトに合わせて/MTにします。
msvcbuild.batの書き換えが終わったら、VisualStudioコマンドプロンプトを起動してsrcフォルダまで移動し、
C:LuaJIT-2.0.0-beta7src>msvcbuild static
を実行すれば、ビルドが行われてsrcフォルダに
lua51.lib
luajit.lib
luajit.exe
その他幾つかのファイル
が出来上がる。staticオプションを忘れないように。
static忘れるとDLLが出来ちゃうので。
exeに結合するlibはlua51.libのほうで、luajit.libやluajit.exeは今回使わない。
プロジェクトの設定
プロジェクトの設定で、
「C/C++→全般→追加のインクルードディレクトリ」にLuaJITのsrcフォルダを設定。
「リンカー→入力→追加の依存ファイル」にlua51.libを設定。
コードの組み込み
実際のコードの組み込み方は本家Luaと同じだけど、ひとつだけ注意点があります。
通常、Luaの開始コードとして
lua_State* _L = lua_open();
// luaの標準ライブラリ読み込み
luaL_openlibs(_L);
とかするんだけど、このコードをDxLib_Init()より後に行うと、luaL_openlibs()のタイミングで強制終了されます。
DxLib_Init()より前に呼べばとりあえずluaL_openlibs()は通過するかもしれないけど(試してない)、その後で異常が出そうな気が。
理由はLuaJIT公式のFAQに載ってるんだけど、ざっくり書くとDirect3D(バージョン9以前)のデバイスの初期化時にD3DCREATE_FPU_PRESERVEをつけないとダメよ、と。
で、DXライブラリはその辺全部内部でやってくれてるので、D3DCREATE_FPU_PRESERVEを直接指定することはできません。
で、どうするかっていうと、DXライブラリ掲示板より
DxLib_Init を呼び出す前に SetUseFPUPreserveFlag( TRUE ) ; という記述を追加すると
Direct3D の初期化時に D3DCREATE_FPU_PRESERVE を使用するようになりますので
よろしければお試しになってみてください m(_ _)m
とあります。
というわけで、DxLib_Init()の手前でSetUseFPUPreserveFlag( TRUE ) ;を呼んであげましょう。
ただし、D3DCREATE_FPU_PRESERVEを使うと、DirectXの浮動小数点演算が遅くなります。
D3DCREATE_FPU_PRESERVEはDirectXで使用する浮動小数点を倍精度(double)に指定します。
Direct3Dは単精度浮動小数点(float)に最適化されてるので、D3DCREATE_FPU_PRESERVEを指定してない時に比べて遅くなる訳です。たぶん。
Direct3Dって大量の浮動小数点演算するから、コレって結構影響大きいんじゃ・・・?
精度は上がるけどね。
ちなみに本家LuaでもD3DCREATE_FPU_PRESERVEを指定しないと、32bitの整数のやり取りがうまくいかないらしいです(2006年時点での情報。今はどうかわからない)
DirectXとLuaの組み合わせってあんましよくないのかもしれませんね・・・。
Luaの仕様が変わって、なんでもかんでも浮動小数点変数に格納するのではなく、整数の場合は整数型変数に格納してくれるような仕様になってくれれば、Luaが普段使う浮動小数点変数をfloatにしてD3DCREATE_FPU_PRESERVEをつけなくても良くなるんじゃないかなー。
以前はそんなパッチが在ったそうだけど、今は無いらしい。公式にやってくれよぅ。
もしくは非公式でもLuaJITがやってくれれば・・・
ここから先は本家Luaと同じなので、別のサイトや書籍を見たほうが詳しいので省きます。
書籍なら
スクリプト言語による効率的ゲーム開発 C/C++へのLua組込み実践 (GAME DEVELOPER)
がお勧め。
Tipsを一つだけ。
C++からLuaへ、また逆をやりたいときに、C++で定義した構造体を渡したくなることがあるけど、なぜかひたすら処理が遅くなるのでオススメしない。
なるべくメンバ変数ごとにgetter/setter的な関数作ってやり取りしたほうが早い気がするよ。
私のやり方が不味いだけかもしれんけど。