System4.0 とGDI の共存
はじめに
System4.0とGDIを共存させる方法を説明します。しかし、この方法は、くれぐれもサンプル程度にとどめておいてください。
拡大縮小、半透明、加算合成、回転などは、SACT標準関数(CG加工関数を含む)で提供されているため、そちらを用いて描画してください。このサンプルの考え方を進めると、DirectXとの共存も可能になります。DirectXの使用については、System4ひそひそ話で述べられています。
GetRenderTargetDataを用いるので、グラフィックボードがDirectX9対応でなければ、相当低速になってしまいます。
高速に動作するかどうかのテストには、Rance6の動作デモをDirect3Dモードで動かしてみるという方法があります。あと、Akt.は、C++プログラマじゃないですし、GDI操作は苦手なので、間違いがあっても責めちゃ駄目です。
System4.0のMainSurface
System4.0は内部でMainSurfaceを保持し、この画像データを画面に表示しています。このMainSurfaceの中身を変更してやれば、画面に表示されるものを変更することが可能となります。逆に、MainSurfaceを変更せずに画面の上から重ねても、すぐにSystem4.0がMainSurfaceを上書きするので、うまくいきません。
MainSurfaceは、24bitのDIBです。そのため、普通にDIBを用いて画像処理を行うことは可能です。(注:経験上、DLLからSystem4.0のCGデコード機能を呼び出して作成したSurfaceは普通のDIBで無いようです)
そして、DIBとDDBは(めんどくさいけど)変換可能であるので、GDIを用いての描画が可能になります。注:MainSurfaceではなく、SACTの単一のSurfaceに描画する場合は、DrawPluginとして作成し、DrawPluginManagerからIChangeNumToISurfaceを取得し、引数で渡されたスプライトからSurfaceを作成することができます。経験上、こちらもDIBです。
MainSurfaceの取得は、MainSystemに対して、GetInterfaceを呼び出すことで行います。MainSystemは、引数で取得するか、DLLのインターフェイスを取ってくるかどちからで取得します。サンプルでは後者を使用しています。
引数での取得は、マニュアル[ Sys42SDK_20041224\熟練者向けセット\マニュアル\Sys42\html\hll\format.html ] を参照しつつ、SACT内部を調べてみてください。また、毎回毎回更新するような場合では、DrawPluginで作成し、MainSurafaceに書き込んだ方が良いと思われます。詳しくは、マニュアル[ Sys42SDK_20041224\熟練者向けセット\マニュアル\Develop\DrawPlugin.html ] を参照してください。
DIBとDDBの変換
DIBとDDBの変換処理については、説明を省略します。
サンプル自体が、他所さんのサンプルを改変したものですので、適切な説明が出来ないためです。
このサンプルでは、2つの異なる方法で実装しています。
サンプル
DLLサンプル
・不要なものとかあるけど、気にしない方針で。
・きたないけど、気にしない方針で。
・サンプルのくせに、コメント少ないけど、気にしない方針で。
呼び出すためのHLL定義は省略します。
1.
void game_main(void) { int nsp=SP_GET_UNUSE_NUM(); SP_CREATE(nsp,50,50,255,0,0,255,true); SACT_UPDATE(); while(true){ gdidraw.GdiDraw1(); system.Peek(); if(KEY_IS_DOWN(VK_RETURN) || KEY_IS_DOWN(VK_LBUTTON)){ break; } } R;R;R;'終わり'A; } |
DIB Sectionでの表示です。
この方式では、SACTのグラフィック命令との互換が取れません。
そのため、SACTが作成した後ろの赤い四角は消えてしまいます。
2.
void game_main(void) { int nsp=SP_GET_UNUSE_NUM(); SP_CREATE(nsp,50,50,255,0,0,255,true); SACT_UPDATE(); while(true){ gdidraw.GdiDraw2(); system.Peek(); if(KEY_IS_DOWN(VK_RETURN) || KEY_IS_DOWN(VK_LBUTTON)){ break; } } R;R;R;'終わり'A; } |
DIBをDDBに変換して、さらにDIBに変換した方式です。
こちらでは、SACTの表示したMainSurfaceの内容を持ったままDDBに変換できるのが特徴です。
そのため、後ろの赤い四角は消えません。
しかし、画面クリアをどうするかという問題があるため、いろいろと問題があります。
後ろの四角を横移動させてみると、ちらつくのが分かると思います。
また、どちらの方法も、終わった後にDLLで書いた部分を消す必要があります。
最も簡単なのは、背景をもう一度設定する方法です。
3.
void game_main(void) { int nsp=SP_GET_UNUSE_NUM(); SP_CREATE(nsp,50,50,255,0,0,255,true); SACT_UPDATE(); while(true){ gdidraw.GdiDraw2(); system.Peek(); if(KEY_IS_DOWN(VK_RETURN) || KEY_IS_DOWN(VK_LBUTTON)){ break; } } WP_SET_COLOR(0,0,0); R;R;R;'終わり'A; } |
と一行追加すれば、GDIで表示した部分は綺麗に無くなります。
結論
大変なだけ、無駄ばかり。あと、MainSurfaceを使う場合はカスタムスプライトでやるべきです。