D + SDL2 入り口に立ってみた。

Android視野に入れるならSDL1.2よりSDL2のほうが良いらしい。みたいなことを何処かで見たので。
どうせやるなら新しい方で。
つっても1.2より情報少ないから、さらに苦労しそうだ。たぶん途中で投げ出すよ宣言。

取り敢えず画像表示までやる。

準備

用意するものは、前回同様
DMDを本家から。DMDは2.064.2だとVisual Dのスケルトンでエラーが出るので、一個古い2.063.2を使用。エラー出ても動くけどね。

SDL2.dllをSDL本家のDevelopment Librariesから。

画像表示のためにSDL_Image2.dllを本家?のDevelopment Librariesから。

バインダとしてDerelict3を使います。
こちらを参考ににてDerelict3をビルドします。

今回もVisual Dを使います。前回参照。

環境設定

1.前回同様、VisualStudioの新規プロジェクトで[Windows Application]で新規ソリューションを作成

2.プロジェクトのプロパティで[構成プロパティ]→[Compiler]のAdditional Importsに、Derelict3のimportフォルダのパスを設定

3.プロジェクトのプロパティの[Linker]のLibrary Search PathにDerelict3の中のlib\dmdフォルダのパスを設定。

4.[Linker]のLibrary Filesに、使用するlibを追加する。今回はDerelictSDL2.libとDerelictUtil.lib。

5.ソースのフォルダにSDL2.dll、SDL_Image2.dll、libpng16-16.dll、zlib1.dllを置く。
SDL_Image2.dll、libpng16-16.dll、zlib1.dllはSDL2_imageのlibフォルダに入ってる。
exe単体で実行する場合はexeと同じ場所に置く。

コードを書く

Derelict3に入ってるsample.dや、ググって出てくる色々を参考になんとか画像表示できた。

module winmain;

import core.runtime;
import core.sys.windows.windows;
import derelict.sdl2.sdl;
import derelict.sdl2.image;

extern (Windows)
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    int result;

    void exceptionHandler(Throwable e)
    {
        throw e;
    }

    try
    {
        Runtime.initialize(&exceptionHandler);

        result = myWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);

        Runtime.terminate(&exceptionHandler);
    }
    catch (Throwable o)		// catch any uncaught exceptions
    {
        MessageBoxA(null, cast(char *)o.toString(), "Error", MB_OK | MB_ICONEXCLAMATION);
        result = 0;		// failed
    }

    return result;
}

int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    /+
	Derelict3でSDL2を初期化する。
    +/
    DerelictSDL2.load();
	DerelictSDL2Image.load();

	// SDL初期化 スコープアウト時に終了処理
    SDL_Init(SDL_INIT_VIDEO);
	scope(exit) SDL_Quit();


    // デスクトップ中央にウィンドウを作成
    auto window = SDL_CreateWindow("Test", SDL_WINDOWPOS_CENTERED,
                                          SDL_WINDOWPOS_CENTERED, 800, 600,
                                          SDL_WINDOW_SHOWN);
	//スコープアウト時に破棄
	scope(exit)    SDL_DestroyWindow(window);


	// レンダラー取得
	// レンダリングドライバ自動判別(-1)
	// ハードウェアアクセラレーション(SDL_RENDERER_ACCELERATED)
	auto renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
	scope(exit) SDL_DestroyRenderer(renderer); //スコープアウト時に破棄

	//適当な画像読み込み
	auto image = IMG_Load("img.png");
	scope (exit) SDL_FreeSurface(image);//スコープアウト時に破棄
	//画像からテクスチャ作成
	auto sdlTexture = SDL_CreateTextureFromSurface(renderer, image);

	//60fpsは16.66..ミリ秒
	immutable MILLS_PER_FRAME = 1000/60;

    // イベントが来るのを待つだけの単純なループ
    bool running = true;

    while (running)
    {
		// フレーム開始時刻
		immutable startTicks = SDL_GetTicks();

		//イベント処理
        SDL_Event e;
        while (SDL_PollEvent(&e))
        {
			if(processEvent(e))
			{
				running = false;
			}
        }

		//画面クリア
		SDL_SetRenderDrawColor(renderer, Uint8.max, Uint8.max, Uint8.max, Uint8.max);
		SDL_RenderClear(renderer);

		//テクスチャをレンダラにコピー
		SDL_RenderCopy(renderer, sdlTexture, null, null);

		//画面に反映
		SDL_RenderPresent(renderer);

		//次のフレームまで待つ
		immutable elapse = SDL_GetTicks() - startTicks;
		SDL_Delay(elapse < MILLS_PER_FRAME ? MILLS_PER_FRAME - elapse : 0);
    }


    return 0;
}

/**
	イベント処理
**/
bool processEvent(const ref SDL_Event e)
{
	switch (e.type)
	{
		//終了
		case SDL_QUIT:
			return true;

		//キーダウン
		case SDL_KEYDOWN:
			return true;

		//マウスクリック
		case SDL_MOUSEBUTTONDOWN:
			return true;

		//その他
		default:
			return false;
	}
}

画面いっぱいに拡大されて画像が表示される。
多分普通はSDL_RenderCopyじゃなくて別の方法使うんだろうなぁ。


DLLが多くてちょっとヤな感じだけど、SDL2からzlibライセンスになったので、DLLをlibに変換してDLL減らしたりできる・・・のかしらん。

さて、次はポリゴン板一枚ぺらっと表示したりしながらOpenGL覚えるかなぁ。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

認証のために問題を解いて下さい * Time limit is exhausted. Please reload CAPTCHA.