System4.0 Tips 

 

 

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を使う場合はカスタムスプライトでやるべきです。