SDLやってみた

目次

はじめに

この記事は Kogakuin Univ Advent Calendar 2019 - Adventar12日目です。

 いやーなんと三個目のアドベントカレンダー登録になりました!何個も投稿させていただけて嬉しい限りです!誰もやらないから仕方ないね。政治経済の話、小説とイロモノ枠として投稿していたわけですが、今度こそは情報学部らしく、KogCoderらしく、ライブラリを使ってみたよという話をしていきたいと思います。

そもそもSDLとは

 そもそも、SDLをご存じでない?方もいらっしゃるのかなと思うのでSDLについてまずは説明していきたいと思います。うっせーー知ってるに決まってるだろバーカという方は目次から次に飛んで下さい(じゃあ、そもそも読むなよ)

 SDLの正式名称はSimple Dynamic Libraryと言って主にゲーム制作に使われるライブラリーです。C言語で書かれていて、SDL内で使われているAPIDirectXOpenGL、Vulkanと多岐にわたっており、それを内部で自動的に切り替えてくれたり自分で切り替えられるのでいろいろなプラットフォームで動くのが特徴です。

すばらしい

 SDL自身でも十二分にゲームプログラミングをすることが可能なのですが、なんとコイツにはSDL_imageSDL_mixerSDL_netSDL_ttfSDL_rtfSDL_gfxと素晴らしい補助ライブラリの数々がありこいつ等をインクルードすると更に楽にゲームを作ることが可能です。

 昨今ゲーム開発でよく使われているDirectXとWindowsAPIの組み合わせと、SDLとその補助ライブラリで実際にゲームを作るうえで必要な動作をさせるコードを書いて比べてみましょう。

実際比べてみる

Windowの作成
DirectX11&Windows

HRESULT DirectX11Manager::Init(HINSTANCE hInstance, int cCmdShow)
{
    WNDCLASSEX wcex = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, hInstance, NULL, NULL, NULL, NULL, "DirectX11 Template", NULL };
    if (!RegisterClassEx(&wcex)) {
        return E_FAIL;
    }

    RECT rc = { 0, 0, 1270, 760 };

    hWnd = CreateWindow(wcex.lpszClassName, "DeferredRenderer", WS_DLGFRAME,
        CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top,
        NULL, NULL, hInstance, NULL);
    if (!hWnd) {
        return E_FAIL;
    }

    ShowWindow(hWnd, cCmdShow);
    UpdateWindow(hWnd);

SDL

SDL_Window* window = NULL;

window = SDL_CreateWindow("Draw Text Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);

画像の表示
Directx11&Windows

#include <windows.h>
#include <tchar.h>
#include <d3d11.h>
#include <d3dx11.h>	//追加

#pragma once
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "d3dx11.lib")	
	//ポリゴン頂点構造体
	struct Vertex3D {
		float pos[3];	//x-y-z
		float col[4];	//r-g-b-a
		float tex[2];	//x-y
	};
	const int TYOUTEN = 4;	//ポリゴンの頂点数

	//頂点データ(四角ポリゴン1枚)
	Vertex3D hVectorData[TYOUTEN] = {
		//500x811
		{ { -0.27f, +0.75f, +0.5f }, { 1.0f, 1.0f, 1.0f, 1.0f }, {0.0f, 0.0f} },
		{ { +0.27f, +0.75f, +0.5f }, { 1.0f, 1.0f, 1.0f, 1.0f }, {1.0f, 0.0f} },
		{ { -0.27f, -0.75f, +0.5f }, { 1.0f, 1.0f, 1.0f, 1.0f }, {0.0f, 1.0f} },
		{ { +0.27f, -0.75f, +0.5f }, { 1.0f, 1.0f, 1.0f, 1.0f }, {1.0f, 1.0f} }
	};
	D3D11_INPUT_ELEMENT_DESC hInElementDesc[] = {
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 4*3, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 4*3 + 4*4, D3D11_INPUT_PER_VERTEX_DATA, 0 }
	};
	//テクスチャー読み込み
	ID3D11ShaderResourceView* hpShaderResourceView = NULL;
	if(FAILED(D3DX11CreateShaderResourceViewFromFile(hpDevice, _T("picture.png"), NULL, NULL, &hpShaderResourceView, NULL))){
		MessageBox(hWnd, _T("D3DX11CreateShaderResourceViewFromFile"), _T("Err"), MB_ICONSTOP);
		goto End;
	}

	//そのテクスチャーをコンテキストに設定
	ID3D11ShaderResourceView* hpShaderResourceViews[] = { hpShaderResourceView };
    hpDeviceContext->PSSetShaderResources(0, 1, hpShaderResourceViews);

SDL

#include <SDL.h>

int main(int argc, char* argv[]){
	SDL_Surface* image;
	SDL_Rect rect, scr_rect;

	SDL_Init(SDL_INIT_EVERYTHING);

	SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE);

	/* 画像読み込み */
	image = SDL_LoadBMP("picture.bmp");

	/* 画像の矩形情報設定 */
	rect.x = 0;
	rect.y = 0;
	rect.w = image->w;
	rect.h = image->h;

	/* 画像配置位置情報の設定 */
	scr_rect.x = 0;
	scr_rect.y = 0;

	/* サーフェスの複写 */
	SDL_BlitSurface(image, &rect, SDL_GetVideoSurface(), &scr_rect);

	/* サーフェスフリップ */
	SDL_Flip(SDL_GetVideoSurface());


	SDL_FreeSurface(image);

	SDL_Quit();

	return 0;
}

まあ、見ての通り圧倒的にSDLの方が楽です。素晴らしいね!

感想やまとめ

DirectXの動作はうまく書ければ軽快に動作しますが、SDLは安定して軽快に動作する上どのプラットフォームでも動くので非常に良かったです。しかも、書く量が少なくて済む上、Directに弄れました。Dxlibから一歩進みたい人にもオススメです。以上、SDLやってみたでした。