‘DirectX’のエントリ

Cマガを立ち読みしてて,DirectPlayが今後なくなる予定だということを知った。とりあえず原文は…ってことで以下に書かれている。DirectX 9.0 SDK Update – (December 2004)1月以上前の情報ですね。ウェザタイはどうしよう。今後のDirectXでもランタイムは使えるんだろうけど,開発用ヘッダやライブラリが付いてこないというのはもう諦めろってことですか。次回バージョンではWinSockで書き直すのか…かなりめんどい。

DirectX9を入れてみた。WeatherTypingも動くし,DirectX9を入れた状態でコンパイルしたものでもDirectX8環境で動いているようだ。で,気になるのはIDirectPlay8NATResolverというインターフェースなんだけど,ヘルプまだ読み込んでないのでなんだか分からない。

ウェザタイ。使用ポートをデフォルトでは指定しないように変更する。今まではポートを指定して,ルータの設定がポート 1 つで OK になるようにしていたが,これによって 6073(ホスト),2302-2400(ホスト・クライアント)となる。

他の DirectPlay8 ネットワークゲームに合わせる意味と,4 人対戦が安定しないのが少しはよくなるか,ということで変更したんですが,今まで動いていてこれで動かなくなった場合,今までのようにポートを固定するオプションをチェックしてください。

DirectPlay 回線シミュレータで遅延を大きくし,ウェザタイのテストをちょっとやってみたところ,つながらない現象が再現した。原因を調べると,プレイヤーダイアログ表示中にプレイヤーを追加しようとして,排他制御で止まっていた。とりあえずそこを直した版を開発版にアップ。4 人対戦については実際にテストしないと分からないが,直っているといいなあ。

DirectX8.1 がリリースされていたので試してみる。確か DX6 の時にあった DirectPlay 回線シミュレータが復活している。これでパケットロスとか遅延のテストが効率的にできそうだ。あとは VC から DirectX プロジェクトが AppWizard で選択できるようになった。

ウェザタイに関しては,掲示板に書いたとおり,TCP/IP 対戦ができなくなった。これは,恐らくセッション選択機能を省いたせいで,DX8.0 では動いたが,DX8.1 ではだめらしい。参考にした書籍のサンプルも動かなくなっていた。これはテストが完了し次第修正版アップ予定。

ILS2 以来やっていなかった 3D に再び手を出す。とりあえず 3D 関係の本を読みつつ DirectGraphics を試す。

最初 Z バッファの初期化を忘れて,実行するたびにオブジェクトが見えたり見えなかったりして困ったが,なんとか裸眼立体視 X File Viewer ができた。


そういえば書いていなかったが,IE6.0 を入れた。全体的には IE5.5 からそれ程違いはない。但し

  • ウィンドウズ終了時,エクスプローラを開いていても次回ログイン時に自動で開かない
  • エクスプローラで,フォルダ部分以外の横の列をクリックすると,フォルダをクリックしたことになる
  • IE のスムーズスクロールがデフォルトオフ(オプションで有効にできる)

という違いがあった。上 2 つはバグなのか仕様変更なのか分からないが,せめて動作を選べるようにオプションを用意して欲しかった。(実はあるのか?)

DirectPlay8 を使ってみる。DirectPlay4 とはえらく違ってていやな感じだが,なんとかセッションの作成までやってみた。で,たまたま電話回線(というかモデムか?)を使用中に立ち上げてみると,Windows 全体がフリーズした。何もできなくなる。DirectX8 SDK サンプルをやってみてもフリーズする。

どこでダメなのか調べてみると,EnumServiceProviders のところで,モデム関連を調べていて落ちている模様。そこで,レジストリエディタでモデムその他 TCP/IP 以外の設定を全削除してやってみたところ,うまくいった。なんなんでしょうか。


VC。アウトプットウィンドウにエラーが表示されているときに F4,Shift+F4 を押すと次々に該当場所へ移動できる(分かりづらい)ことを発見。

Direct3D と 2D を重ねる方法。最初 2D の上に 3D を描いてうまくいかなかったが,Direct3D の Clear を,2D 描画の前で行うようにすればよい。

Direct3D,Viewport の ForceUpdate で画面が更新されなくて困る。原因は ForceUpdate の 3,4 番目の引数が幅,高さだと思っていたこと。実際はクライアント座標。

DirectDraw カラーキーについて

DirectDraw のカラーキーは,実際のハードウェア,BPP などに対応する値を指定してやる必要がある。1 番確実な方法はサンプルのように,サーフェスに GDI で描画をし,値を読み出すこと。

DWORD CDirectDraw::DDColorMatch(LPDIRECTDRAWSURFACE pSurface, COLORREF rgb)
{
    DWORD result;
    COLORREF oldrgb;

    HDC hdc;

    // GDI を使って色を置く
    if(rgb != CLR_INVALID && pSurface->GetDC(&hdc) != DD_OK)
    {
        return 0;
    }

    // 前の値を保持
    oldrgb = ::GetPixel(hdc, 0, 0);

    // 色を置いてみる
    ::SetPixel(hdc, 0, 0, rgb);

    pSurface->ReleaseDC(hdc);

    // ハードウェア依存の値を読み込む
    DDSURFACEDESC ddsd;
    ddsd.dwSize = sizeof(DDSURFACEDESC);

    HRESULT hres;
    while((hres = pSurface->Lock(NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING)
    {
        ;
    }

    if(hres == DD_OK)
    {
        result = *(DWORD *)ddsd.lpSurface;

        // BPP に対する修正
        if(ddsd.ddpfPixelFormat.dwRGBBitCount < 32)
        {
            result &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount) - 1;
        }

        pSurface->Unlock(NULL);
    }

    // 書き込んだ値を元に戻す
    if(rgb != CLR_INVALID && pSurface->GetDC(&hdc) != DD_OK)
    {
        return 0;
    }

    // 色を置いてみる
    ::SetPixel(hdc, 0, 0, oldrgb);

    pSurface->ReleaseDC(hdc);

    return result;
}

Direct3D,メッシュを見えなくするには,Frame.DeleteVisual すればよいが,メッシュの参照がなくなり,メッシュが削除され,もう 1 度表示するときに困る。これを防ぐには先に Mesh->AddRef() をしてやればよい。

DirectSound で音が鳴り終わったことを検出する為に IDirectSoundNotify を使う。DIRECTSOUNDBUFFER 作成時のフラグに DSBCAPS_CTRLPOSITIONNOTIFY を指定するのを最初忘れた。

DirectSound,弾を撃つバッファを static で作ったが,複数の音が鳴らない。これは別々にバッファを用意するしかないようだ。

DirectInput。GetDeviceData が Release フルスクリーンでうまくいかなかった。原因は第 3 引数が入出力両用ということに気付かず,初期化しないまま渡していたからだ。

SendChatMessage を使うために DirectPlay インターフェースを IDirectPlay3 に。しかしインターフェースがかなり変わっていて戸惑う。

結局 SendChatMessage はロビーを使わないとだめなので使わなかった。

DirectSound が初期化できなかった。原因はサスペンドした時にサウンドカードが使えなくなってたため。もう一度差し直すことで解決。

DirectX の簡易ライブラリを作ろうと思う。使いたい DirectX ラッパークラスを継承するというものにしようと思う。


スタティックライブラリの作り方。何度かやってるがいつも迷うのでここに書いておく。新規ワークスペースで Win32 Static Library を選び,プリコンパイル済みヘッダ,MFC サポートを on にする。


DirectSound。DSound.h をインクルードする前に MMSystem.h をインクルードする必要がある。ちなみにライブラリは DSound.lib と WinMM.lib。


Information の r が抜けていた。全部直す。

Direct3D,テクスチャは 2 の n 乗でないと SetTexture でエラーが出るようだ。ていうかそんな制限どっか書いてあったっけ?

テクスチャがどうやってもできないと思ってふと裏から見るとちゃんと見られる。でも何故裏にできる?

ということでよく調べると座標系を勘違いしていた。ヘルプを見てやっと座標系を理解できた。しかしカメラ,ライトは z 方向を向くとかはどこにも書いてないような。試行錯誤でやっと分かってきた。

念のため。SetPosition は自分のフレームの位置をベース座標で指定する。SetOrientation は自分のフレームの向きをベース座標で指定する。その際,第 2 ~ 4 引数は自分の z 軸をベース座標で表した値,第 5 ~ 7 引数は自分の y 軸をベース座標で表した値である。

Direct3D の初期化をする。ぷぅさんからテストデータがあがったので試してみたいのだ。しばらくやってると妙に動作が重い。ふと時計を見ると他の時計より 30 分ばかり遅れている。おや? と思って修正しようとすると,明らかに時間が進むのが遅い! ていうか何だコリャ。熱くなりすぎておかしくなったのか? ともあれ時間が遅れるとはビックリ。ちなみに再起動したら直った。

ILS2 を進める。

クライアントウィンドウに対するメインウィンドウの合わせ方

AdjustWindowRectEx を使う。これはあるウィンドウサイズ,あるメニューに対してメインウィンドウをどのくらいにすればよいかを返す関数で,例えば CMainFrame::PreCreateWindow で

CRect rectClient(WINDOW_BASE, WINDOW_BASE, WINDOW_BASE + WINDOW_WIDTH, WINDOW_BASE + WINDOW_HEIGHT);
::AdjustWindowRectEx(&rectClient, cs.style, NULL, cs.dwExStyle);
cs.x = rectClient.left;
cs.y = rectClient.top;
cs.cx = rectClient.Width();
cs.cy = rectClient.Height();

のように使う。


で,ウィンドウモードだが,なかなかうまくいかなかった。原因を調査していると,Primary Surface に BltFast しているのがいけないらしい。Blt ならうまくいく。何故だろう。