• SDL_mixerを追加しました

    2011年04月10日 00時32分
    時代はSDLなんでしょうか。
    最近SDLの話をよく見かける気がします。



    乗るしかない このビッグウェーブに



    SDLは音声再生にSDL_mixerを使うものらしいので追加してみました。


    SDL for D version 1.2.14.2


    次の様な単純に再生するコードのみ動作を確認しています。

    1import core.runtime;
    2import std.c.windows.windows;
    3import org.libsdl.sdl;
    4import org.libsdl.mixer;
    5
    6//--------------------------------------------------------------
    7// D言語でWindowsアプリを作るときの基本処理
    8
    9extern (Windows)
    10int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    11{
    12    void exceptionHandler(Throwable e)
    13    {
    14        throw e;
    15    }
    16
    17    int result;
    18    try
    19    {
    20        Runtime.initialize(&exceptionHandler);
    21        scope (exit) Runtime.terminate(&exceptionHandler);
    22
    23        dmain();
    24    }
    25    catch (Throwable o)
    26    {
    27        MessageBoxA(nullcast(char*)o.toString(), "Error", MB_OK | MB_ICONEXCLAMATION);
    28        result = 1;
    29    }
    30
    31    return result;
    32}
    33
    34// 画面サイズ
    35immutable int SCREEN_WIDTH = 640;
    36immutable int SCREEN_HEIGHT = 480;
    37
    38void dmain()
    39{
    40    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
    41        throw new Error("SDL_Init failed.");
    42    scope(exit) SDL_Quit();
    43
    44
    45    // SDL_Mixerの初期化と終了
    46    Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 4096);
    47    scope(exit) Mix_CloseAudio();
    48
    49    // ファイルの読み込みと解放
    50    Mix_Music* music = Mix_LoadMUS("hoge.ogg");
    51    scope(exit) Mix_FreeMusic(music);
    52
    53    // 再生と停止
    54    Mix_PlayMusic(music, 0);
    55    scope(exit) Mix_HaltMusic();
    56
    57
    58    SDL_Surface* screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32, SDL_HWSURFACE);
    59    if (screen is null)
    60        throw new Error("SDL_SetVideoMode failed.");
    61
    62    
    63    for (;;)
    64    {
    65        SDL_Event event;
    66        while (SDL_PollEvent(&event))
    67        {
    68            if (event.type == SDL_QUIT)
    69                return;
    70        }
    71    }
    72}



    SDL_mixer.libが例によってcoff形式でありますが、
    omf形式の物を所持していなかたので変換する必要がありました。

    そこで探してみたのですが、変換するプログラムがきちんとありました。
    digitalmars.D.announce - coffimplib tool
    COFFIMPLIB - Digital Mars

    ダウンロードはこちら (Digital Mars FTP)

    coff2omfとの違いがはっきりとはわからないのですが、
    coffimplibはインポートライブラリ専用の簡易版のようです。

    とりあえずSDL_mixer.libについては無事変換出来ました。

    みんなLinuxだからこの辺り困ってないのかな?
  • SDLモジュール更新

    2011年04月06日 22時45分
    情報をいただいた点を修正しました。

    SDL for D version 1.2.14.1

    構造体のalign

    ubuntu 64bitでは構造体のalign(4)を消したら動いたそうなので、消しました。

    versionで切って対応しようかとも思ったのですが、
    Windows 32bitでもalign(4)を削除して動いたので、とりあえず単純に削除としました。
    (alignイマイチよくわかって無いのですが、Windows版dmdは元々align(4)な気がします)


    モジュールのpublic import

    org.libsdl.sdlモジュールで、OpenGL以外のモジュールをpublic importするようにしました。
    あと、org.libsdl.openglモジュールで、org.opengl.*のモジュールをpublic importするようにしました。
    これでCのヘッダのように扱えるかと思います。

    一応Dっぽく個別import出来るよう、version(DisablePublicImport)として切っておきました。

    コーディングの好みに合わせて使い分けてください。
  • D言語とDirectInputとゲームコントローラと

    2011年04月06日 00時43分
    アクションゲームですとキーボードでの操作は厳しいかと思います。
    なので、DirectInputでゲームコントローラの処理を書きました。

    基本的にC++と同様にやれば動くので
    例によって詳細はどこか他サイトを参照してください。


    ここではDから使うときのポイントだけ書いておこうと思います。


    DirectInputは複数のゲームコントローラを認識出来ますので、
    最初にデバイスを列挙することになります。

    このとき、IDirectInput8.EnumDevicesを使いますが、
    引数の関数ポインタで指定する関数は当然DirectInputから呼ばれますので、定義時に注意が必要です。

    具体的にはextern(Windows)を指定します。
    1extern (Windows)
    2static
    3BOOL enumerateDeviceCallback(const(DIDEVICEINSTANCE)* device, VOID* context)
    4{
    5    // なにがしかの処理
    6}


    軸の列挙に使用するIDirectInputDevice8.EnumObjectsに指定する関数も同様です。


    ちなみに、キーボードいっぱい刺さってたらどうなるんだろう?と思い調べたところ、
    全部のキーボードを1つのキーボードとして認識するそうです。(マウスも)
    DirectInput の使用方法(MSDN)
  • D言語でDirectX 補足情報

    2011年03月20日 12時21分
    前回のD言語用DirectXモジュールについての補足です。

    このモジュールを使用する場合の開発環境ですが、必要なものはdmdのみです。

    DirectXのSDKは特に必要ありません。
    サンプルやリファレンスが欲しい時にインストールすれば良いです。

    libファイルも用意してませんので、リンクする必要はありません。


    DirectXをD言語から使用する方法ですが、基本的にC++から使用する場合と同じです。

    何か調べる時にはC++からの使用を解説しているサイトなどを探してください。
    APIは同一となっています。(なっていなかったら私の作成ミスです。)


    基本的にCOMのオブジェクトはC++と同様に取れますが、
    ルートとなるオブジェクトの取得には注意が必要です。

    インポートライブラリを同梱していませんので、
    例えば「DirectSoundCreate8」のような関数ではなく、CoCreateInstanceを使うことをお勧めします。

    つまり、IDirectSound8やIDirectInput8等は次の様にCOM標準の方法で取得します。
    1IDirectSound8 directSound;
    2CoCreateInstance(&CLSID_DirectSound8, null, CLSCTX.CLSCTX_INPROC_SERVER, &IID_IDirectSound8, cast(void**)&directSound);


    1IDirectInput8 directInput;
    2CoCreateInstance(&CLSID_DirectInput8, null, CLSCTX.CLSCTX_INPROC_SERVER, &IID_IDirectInput8, cast(VOID**)&directInput);



    同じようにしてDirect3Dのオブジェクトも取りたいところですが、
    Direct3Dに限ってはCoCreateInstanceでは取れません。
    「Direct3DCreate9」のような専用関数を使用する必要があります。

    この関数の実体はDLLに含まれています。
    「Direct3DCreate9」ならば「d3d9.dll」です。

    よって、次の様にDLLから関数を取得して使用します。
    1HMODULE d3d9Dll = LoadLibrary("d3d9.dll\0".ptr);
    2
    3Direct3DCreate9Function Direct3DCreate9 = cast(Direct3DCreate9Function)GetProcAddress(d3d9Dll, "Direct3DCreate9\0".ptr);
    4
    5IDirect3D9 direct3D = Direct3DCreate9(D3D_SDK_VERSION);



    Direct3D 11の場合はこうです。
    1HMODULE d3d11Dll = LoadLibrary("d3d11.dll\0".ptr);
    2
    3PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN D3D11CreateDeviceAndSwapChain = cast(PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN)GetProcAddress(d3d11Dll, "D3D11CreateDeviceAndSwapChain\0".ptr);
    4
    5IDXGISwapChain swapChain;
    6ID3D11Device device;
    7ID3D11DeviceContext immediateContext;
    8D3D_FEATURE_LEVEL featureLevel;
    9DXGI_SWAP_CHAIN_DESC swapChainDesc; // 設定略
    10D3D11CreateDeviceAndSwapChain(null, D3D_DRIVER_TYPE.D3D_DRIVER_TYPE_HARDWARE, null, 0, null, 0, D3D11_SDK_VERSION, &swapChainDesc, &swapChain, &device, &featureLevel, &immediateContext);

  • D言語でDirectX

    2011年03月17日 22時38分
    いつものように手持ちのソースの再アップです。


    D言語からはCOMが扱えるようになっているので、
    DirectXのヘッダ情報さえD言語モジュールとして作ってしまえば割と簡単にDirectXが扱えます。

    ただ、そのD言語モジュールを作るのが激しく面倒です。
    使う人がそれぞれでこんな作業をしていたら宇宙のエントロピーが増大してしまうと思うのです。
    そうすると魔法少女的なところにも影響があると思うのでよろしくありません。


    なので私がせっせと作ったモジュールを置いておきます。
    D言語(D2)用 DirectX モジュール


    例によって手作業でやっている部分が多いので
    何かおかしなところがあればこのモジュールが原因の可能性が高いです。

    可能な限り正しく動く状態にしたいと思いますので、
    そういった場合には情報をいただければと思います。


    また、上記モジュールの使用例として
    簡単なプログラムを作成しました。

    サンプルプログラム

    2011年3月21日 追記

    上記のサンプルプログラムがdmd2.052でビルド出来なかったため、修正版を置いておきます。
    winmain.dで一箇所Objectをcatchしている箇所があったので、そこをThrowableに直しただけです。
    サンプルプログラム