lucane’s blog

新人プログラマーの仕事だったり趣味で詰まった事や解決方法をメモするブログでございます。

そうだ、DirectXで遊ぼう

ブログの方針について


こんばんは、Lucaneです。

前の記事を書いて以来、ブログのメインにする題材について考えてました。
考え付いたのは、

1:Unityで簡単なゲームを沢山作って経験を積む
2:DirectXでがっつり高度なプログラミングをする
3:java等の別言語に手を出す

の三つでした。

それぞれにメリット・デメリットあって

Unity

【メリット】
・面倒な設定が無いのでモチベが下がりにくい
・一番見栄えが良いゲームが作れそう
【デメリット】
ゲームエンジン頼りな部分があり、高度な技術は身に付きにくそう
・転職等などではC++の方が圧倒的に有利

DirectX

【メリット】
・細部まで自分でプログラムするため技術力が付く
・転職等で有利
【デメリット】
・基本的に難しいのでモチベが下がりやすい
・英語との闘い(英語圏のサイト見ないとバグ潰せなかったり…)

別言語

【メリット】
・幅広く言語を扱えれば職に困らない
・違う分野の知識が身に付きそう(DBとかwebサイト)
【デメリット】
・実際のお仕事で役に立つかいまいち不明
・乗り気がしない

考え抜いた結果、自分のやる気が続く事を信じてDirectXを進めて行く事にしました。
難しかったらUnityに切り替えればいいし

ひな形プロジェクトの準備をしよう!


と言うわけで、まずはひな形のプロジェクトを準備しましょう。
参考にしたサイトはlemonkobo様の下記記事です。
https://qiita.com/lemonkobo/items/83b2c75b7a8b70253186

記事通り進めた所、ビルドの時にWindows SDK 10.0.16299.0がないと怒られたので
windows公式サイト(Windows 10 SDKWindows アプリ開発
からSDKをダウンロードして解決。

そしてコードをコピペ→ビルドでまたエラー。
f:id:lucane:20180312001342p:plain

どうやら渡したdeviceがnullの様子。


エラーを吐いたコードがこちら

// These are the resources that depend on the device.
void Game::CreateDevice()
{
UINT creationFlags = 0;

 //追加したコード ここから
m_spriteBatch = std::make_unique<SpriteBatch>(m_d3dContext.Get());
ComPtr<ID3D11Resource> resource;
DX::ThrowIfFailed(
CreateWICTextureFromFile(m_d3dDevice.Get(), L"kawaii.png", resource.GetAddressOf(), m_texture.ReleaseAndGetAddressOf())
);

ComPtr<ID3D11Texture2D> texture;
DX::ThrowIfFailed(resource.As(&texture));

CD3D11_TEXTURE2D_DESC textureDesc;
texture->GetDesc(&textureDesc);

//追加したコード ここまで

#ifdef _DEBUG
creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

static const D3D_FEATURE_LEVEL featureLevels [] =
{
// TODO: Modify for supported Direct3D feature levels
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_1,
};

// Create the DX11 API device object, and get a corresponding context.
ComPtr<ID3D11Device> device;
ComPtr<ID3D11DeviceContext> context;
DX::ThrowIfFailed(D3D11CreateDevice(
nullptr, // specify nullptr to use the default adapter
D3D_DRIVER_TYPE_HARDWARE,
nullptr,
creationFlags,
featureLevels,
_countof(featureLevels),
D3D11_SDK_VERSION,
device.ReleaseAndGetAddressOf(), // returns the Direct3D device created
&m_featureLevel, // returns feature level of device created
context.ReleaseAndGetAddressOf() // returns the device immediate context
));

//中略

DX::ThrowIfFailed(device.As(&m_d3dDevice));
DX::ThrowIfFailed(context.As(&m_d3dContext));

// TODO: Initialize device dependent objects here (independent of window size).


}

 


原因としては簡単な事で追加したコードの位置が悪かったようです。
CreateDevice()の終了部分に丁寧に、
「デバイスに依存するオブジェクトはここで初期化」ってコメントまで書いてあるのに…
ちゃんとコメントを読まないといけませんね。

と言う訳で修正

//中略

DX::ThrowIfFailed(device.As(&m_d3dDevice));
DX::ThrowIfFailed(context.As(&m_d3dContext));

// TODO: Initialize device dependent objects here (independent of window size).
 //追加したコード ここから

m_spriteBatch = std::make_unique<SpriteBatch>(m_d3dContext.Get());
ComPtr<ID3D11Resource> resource;
DX::ThrowIfFailed(
CreateWICTextureFromFile(m_d3dDevice.Get(), L"kawaii.png", resource.GetAddressOf(), m_texture.ReleaseAndGetAddressOf())
);

ComPtr<ID3D11Texture2D> texture;
DX::ThrowIfFailed(resource.As(&texture));

CD3D11_TEXTURE2D_DESC textureDesc;
texture->GetDesc(&textureDesc);

//追加したコード ここまで

これで無事に動くぞ!と思いきやまたエラー。

f:id:lucane:20180312002106p:plain

流石にこれはすぐに分かりました。
下に指定された画像が見つかりませんでしたって教えてくれてますもんね。

画像の置かれている位置が悪かったようです。
ソリューションファイル(.sln)があるフォルダの
プロジェクトと同盟なフォルダの中に画像を張り付けて解決。
無事画面が表示されるようになりました!

f:id:lucane:20180312004238p:plain

いやー可愛いですね…
この子は我那覇響ちゃん(16)。
歌もダンスもカンペキなアイドルで、疲れた心を癒してくれる天使です。
一目ぼれした方は是非
アイドルマスターステラステージ(公式サイトリンク
を購入してプロデュースすると幸せになれます。

センターにもってきてあげよう


さて、コピペだけで記事を書き終えるのもアイドルを端に表示するのも、
よろしくないのでウィンドウの中央に表示してあげましょう。

ウィンドウの中央に表示するためには、ウィンドウサイズを知らなければいけないので
専用の関数を使いましょう。
それがGetClientRect( )関数。
これでウィンドウの中のサイズを取得できるみたいです。
また、RECT型の変数が必要なのでヘッダーファイルにでも宣言しておきましょう。

本当なら次は画像サイズを取得して計算云々でピッタリ中央に表示…と行きたいのですが
眠いので諸事情でここはマジックナンバーを使って適当に調節したいと思います。

void Game::Render()
{
    // Don't try to render anything before the first Update.
    if (m_timer.GetFrameCount() == 0)
    {
        return;
    }


    Clear();

    // TODO: Add your rendering code here.
	m_spriteBatch->Begin();

	//クライアント領域取得
	GetClientRect(m_window, &windowSizeBuf);

	//マジックナンバーでサイズを調整
	m_pos.x = windowSizeBuf.right * 0.25f;
	m_pos.y = windowSizeBuf.bottom * 0.10f;

	m_spriteBatch->Draw(m_texture.Get(), m_pos);
	m_spriteBatch->End();


    Present();


}

調節した画像がこちら
f:id:lucane:20180312010934p:plain

しっかりセンターに表示できました。
真ん中に立ってこそのアイドルですからね。これでよしよし。

正直、画面サイズ引っ張って来るのにも手こずると思ってたので
何事も起こらずに進められてよかった、よかった。


では、今日はプロジェクトのひな形を準備できたので
次からはこれを基に色々と遊べたらという感じです、また何かできたら更新しますね。

それではおやすみなさい。