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覚えるかなぁ。