描画の基本

■サンプル

●環境
	VisualStudio 2017

	DirectX9(June 2010)

●リンク
	サンプル

	※今回のサンプルは完全に描画をイメージするためのサンプルです。
	 統合画像を意識したつくりにはしていません。

■概要

描画はキャラクターや背景、UIを画面上に表示する処理のことで、ゲームを作る上で絶対に必要です。
描画処理が入っていないゲームは、そもそも画面上に絵を出すことができません。
※これ以降描画するモノについてはオブジェクトという単語を使います。

gmpg_0199

上の絵では「キャラクター」「敵」「背景」のオブジェクトを画面に描画しています。

■描画するオブジェクトの種類

画面に描画するオブジェクトは様々な種類があります。
2Dでは「テクスチャ」、3Dでは「3Dモデル」を主に使っており、その他、円や矩形、線などがあります。

gmpg_0200

■描画に必要な情報

オブジェクトを描画するために最低限必要な情報は「何を描画するか」「どこに描画するか」です。
その他の情報として拡縮率や回転角度や描画する内容によっては
各自で必要な情報(円なら半径等)も存在します。

●何を描画するか
	何を描画するかというのは「■描画するオブジェクトの種類」で書いてある
	テクスチャや3Dモデルなどの種類を指します。
	描画をする際に、この情報がないと意図したオブジェクトを描画をすることはできません。
	ただ、これはサンプルや後程出るプログラムの項目で紹介している
	構造体やクラスにメンバ変数として入れるのではなく、
	種類ごとに構造体を作ったり、関数を作ったりすることが多いです。
	各種類ごとに必要な情報が異なる(テクスチャは使用するテクスチャや、テクスチャ座標、
	円では半径が必要)ので種類ごとに構造体や関数を作成し、区別することが多いです。
	無理やりまとめることで、コードが読みにくくなることを回避するために分けています。

●どこに描画するか
	次に必要な情報は描画位置です。
	画面の中心や左隅などを描画したい場所を指定するのですが、
	この時に位置情報として使用するのが「座標」です。
	座標は2Dでは「X軸とY軸」3Dでは「X軸とY軸とZ軸」で構成されており、
	各軸に値して値を設定することで、細かい位置に描画をできるようになります。
	※座標については「座標」で解説しています。

●共通情報
	描画の情報で必須ではありませんが、よく使用される情報があります。
	例えば拡縮率回転角度です。
	ゲーム上では描画しているオブジェクトを拡大、縮小させたり、
	回転させたりすることが多々あるのでそれらの情報を設定できるようにしておきます。
	
●その他
	描画する内容によって必要な情報が異なります。
	例えばテクスチャの場合、どのテクスチャを使用するか、統合画像を使用していたら
	描画する絵のテクスチャ座標を指定する必要があります。
	他にも、矩形ならば矩形のサイズ、円なら半径等、描画するオブジェクトの種類によって
	独自の情報が必要となります。

■プログラム

プログラムで描画処理を実装する場合、まずは描画情報をまとめた構造体やクラスを用意した方が
多くのオブジェクトを描画するゲームでは効率的に描画ができるようになります。

●例
	以下は例になりますがコードをある程度省略しています。
	まとめてる例の完成版はサンプルをご覧ください。

	・まとめてない
		// プレイヤーオブジェクト作成
		int player_texture_id = -1;
		float player_pos_x = 200;
		float player_pos_y = 400;

		// 敵オブジェクト作成
		int enemy_texture_id[] = 
		{
			-1,
			-1,
			-1
		}; 

		float enemy_pos_x[] = 
		{
			20,
			400,
			600
		};

		float enmey_pos_y[] =
		{
			400,
			400,
			200
		};

		// 背景オブジェクト作成
		int bg_texture_id = -1;
		float bg_pos_x = 0;
		float bg_pos_y = 0;

		// 背景描画
		Draw(bg_texture_id, bg_pos_x, bg_pos_y);
		// プレイヤー描画
		Draw(player_texture_id, player_pos_x, player_pos_y);
		// 敵描画
		for (int i = 0; i < 3; i++)
		{
			Draw(enemy_texture_id[i], enemy_pos_x[i], enemy_pos_y[i]);
		}
		
	・まとめてる
		// 描画データ
		struct DrawObject
		{
			int m_TextureId;	// テクスチャID
			float m_PosX;		// 描画座標X
			float m_PosY;		// 描画座標Y
		};

		// プレイヤーオブジェクト作成
		DrawObject player =
		{
			-1, 200, 470
		};

		// 背景オブジェクト作成
		DrawObject bg =
		{
			-1, 0, 0
		};

		// 敵オブジェクト作成
		DrawObject enemy[] = 
		{
			{ -1, 20, 400 },
			{ -1, 400, 400 },
			{ -1, 600, 200 },
		};

		// 背景描画
		Draw(bg.m_TextureId, bg.m_PosX, bg.m_PosY);
		// プレイヤー描画
		Draw(player.m_TextureId, player.m_PosX, player.m_PosY);
		// 敵描画
		for (int i = 0; i < 3; i++)
		{
			Draw(enemy[i].m_TextureId, enemy[i].m_PosX, enemy[i].m_PosY);
		}

	まとめてる方が変数宣言の時にシンプルになっていると思います。
	まとめてない方では一つのオブジェクトを描画するために3つ変数を宣言しています。
	描画するオブジェクトが多くなることを考えるとどちらの方が楽になるかというのは明確です。