問題点

ここには、私が実際にDGCでプログラムを作るにあたって直面した問題点について、ちょっとしたメモ代わりに書いていこうと思います。

スプライトの透過・その2
下の方でスプライトの透過色を簡単に設定できないと書いたが、やっと方法がわかった。Image Library Editor でビットマップを開いた後、「Bitmap」-「Edit Palette」で透過色を指定することが出来るのだ。これですべてのイメージに個別に透過色を指定してやれば、実行時に明示的に指定する必要は無くなる。

リフレッシュレートと実行速度
ずーっと気になっていたことなのだが、DGC は画面の描画回数がメインの時間単位として取り入れられている。これはビデオカードやディスプレイの種類などによっても変化し、またマシンの能力不足による処理落ちのたびに実行速度が変化することを意味する。設定にもよるが、一般にハイエンドのマシンほど実行速度も速くなってしまうのである。実際に垂直同期が50の時と100の時では実行速度に2倍の差がつき、アクションゲームにおいては致命的なほどにゲームバランスが崩れてしまうことになる。しかもアニメーションのフレーム切り替え速度などには実時間(ms)が使われており、OnAnimationEnd イベントによって時間管理されている部分がある場合、違うゲームかと感じるぐらいタイミングにずれが生じてしまう。

基本的にはこれらはすべて、スプライトマネージャの実装に原因があり、DGC を使っていて感じる具合の悪さの殆どがこのコンポーネント(DGCSpriteMgr)に集中している。今のままでは作るソフトにも制限ができてしまうので、将来的にこれらの不具合が直らない場合は他の Delphi 用 DirectX コンポーネント集に乗り換えるか、自分でスプライトマネージャを作るしかない。そんな面倒な作業をする時間は無いので、私としては次のバージョンあたりで解決されることを切に期待しているのである。

スプライトのアニメーションがリセットできない
下の方にある話とは逆で、スプライトのアニメーションを途中でリセットして一からやり直す方法である。単に animation プロパティに値を代入した場合、animation の値が同じなら何も起こらない事になっている。これは、いったん別の値を animation に入れてやることで解決できた。
    //アニメーションを先頭に戻して再開する。
    //現在の animation が 2 の場合。
    animation := 1;
    animation := 2;
スプライトの透過
DGCSpriteMgr は、デフォルトでパレットの0番を透過色として認識する。しかしせっかくスプライトの画像の背景をパレットの0番で描いても、イメージライブラリエディタに登録する際にはパレットの0番以外の値の中から近い物を探して読み込んでしまうため、透過スプライトが使用できないのである。そんなはずはないと思っていろいろ調べてみたが、どうしても簡単に済ませる設定が見つからなかった。

仕方が無いのでプログラム上で設定することにする。TDGCSurface クラスは TransparentColor というプロパティを持っていて、ここに透過したい色のパレット番号を設定してやることで Draw などのメソッドの透過設定(最後のパラメータ)が有効になる。具体的には以下のように書けば良い。

  for i:=0 to DGCImageLib1.ImageCount -1 do
    DGCSpriteMgr1.DGCScreen.Images[i].TransparentColor := 11;
これを DGCScreen の Initialize にでも書いておくことによって、やっとスプライトを透過させることが出来た。

SpriteStopped が発生しない
またスプライトの話になるが、Sprites.AddBouncer などのスプライトタイプで AllActions に laStopOutside なんかを設定しておくと、スプライトが Limits の外に出たときに OnSpriteStopped イベントが発生する。しかし、実際にやってみると境界の上と左の端ではイベントが起こるが、右と下では起こらなかった。

これは AddBouncer のときに、スプライトの向き(4番目のパラメータ)を0にしていたときに発生する。これはスプライトが右と下の境界の判定を、スプライトの向きによってしたりしなかったりするのが原因で、「 SetAllDirections でやってるからスプライトの向きは関係ないや」などと考えていると落とし穴にはまる。つまり、右を向いていなければ右の境界判定はしないのである。したがってスプライトの向きが0以外でも、もちろん同じ現象が見られる。

この問題は、スプライトの動きを VelocityX などの値を自分で設定して制御する場合に注意が必要となるが、対策は簡単である。スプライトが上と左向きのときは無条件で境界を判定するので、スプライトが常に右下を向いていることにすれば良い。

    DGCSpriteMgr1.Sprites.AddBouncer(ID,x,y,12,velocity,anim);
これは仕様というよりバグだと思うが。。。

スプライトのアニメーションがリセットされる
カーソルキーの左か右を押すことによって、スプライトのアニメーションが先頭に戻る現象が起こっていた。これは Player8 などのスプライトではなく、Bouncer などのまったくキー入力とは関係ないスプライトで起こっていたのでとても不思議だった。途中まで原因を突き止めて、どうもスプライトの automatic プロパティが true のときに発生する事まで突き止めて、明示的に false にすることによって解決したのだが、今になってこの部分を削ってみても再現しなかった (?_?)

なのでこの問題はこれ以上追求しないことにする。もし同じ問題で悩んでいる人がいたら、詳しく調べて解決策を送ってくれるとうれしいです。

ジョイスティック入力について
DGCJoy で入力して Player8 に Velocity を設定してやると、スプライトが動いても IdleAnimation のままになってしまう。FormKeyDown でキーボードから入力して同じ事をしても正常に動くので不思議であるが、原因は分からない。ご存知の方募集。

イントロの再生
DGCIntroLib1 でイントロを再生した後、もう一度任意のタイミングで同じイントロを再生する方法が分からないでいる。実はできたこともあるが、その後さっぱり再現しない。これもご存知の方募集。



もどる