【DXライブラリ】画像を表示する

DXライブラリで画像を表示する方法について説明しています。画面にべったり貼り付ける2D空間用と3Dゲームで奥行きを考慮して貼り付ける3D空間用の両方を説明。

画像のロードと破棄

2Dゲーム・3Dゲームに関わらず画像のロード方法および破棄方法は共通。

1枚絵を読み込みたい場合は LoadGraph() を使用する。読み込める画像ファイルは BMP, JPEG(JPG), PNG, DDS, ARGB, TAGの6つ。

宣言 int LoadGraph( char *FileName )
概要 画像をメモリに読み込む
引数 char *FileName 読み込む画像ファイルのパスのポインタ
戻り値 -1以外 画像のハンドル
-1 エラー発生

複数の絵を1つにまとめた画像(マップチップなど)を扱う場合は分割読み込みができる LoadDivGraph() を使用する。

宣言 int LoadDivGraph(char *FileName, int AllNum, int XNum , int YNum, int XSize , int YSize int *HandleBuf)
概要 分割読み込みをする画像ファイルのパスのポインタ
引数 char *FileName 読み込む画像ファイルのパスのポインタ
int AllNum 画像の分割総数
int XNum 画像を横に分割する数
int YNum 画像を縦に分割する数
int Xsize 分割された画像の横の大きさ
int Ysize 分割された画像の縦の大きさ
int *HandleBuf 分割読み込みをした画像ハンドルを格納する配列へのポインタ
戻り値 0 成功
-1 エラー発生

読み込んだ画像を破棄する場合は DeleteGraph() を使用する。

宣言 int DeleteGraph( int GrHandle )
概要 メモリ上から指定の画像を削除する
引数 int GHandle 削除したい画像ハンドル
戻り値 0 成功
-1 エラー発生

画像の表示(2D版)

キャラの立ち絵やメニュー画面でのアイコンなど画像を画面にべったり貼り付けたいときは DrawGraph() を使用する。

宣言 int DrawGraph(int x,int y,int GrHandle,int TransFlag)
概要 メモリに読み込んだ画像表示
引数 int x X座標(画像左上の点になる)
int y Y座標(画像左上の点になる)
int GrHandle 描画する画像ハンドル
int TransFlag 透明度を有効にするかどうか(TRUE:有効 FALSE:無効)
戻り値 -0 成功
-1 エラー発生

2D画面上の座標だが画面左上が原点でY軸は下が正の向きなので注意。

画像の表示(3D版)

処理に軽減のために3Dモデルではなく画像を使う場合(例:スマブラシリーズの食べ物)や3D空間にいるキャラの上にアイコンを表示させたいときに。

奥行きに合わせて画像の大きさを変える場合は DrawBillboard3D() を使う。

宣言 int DrawBillboard3D(VECTOR Pos, float cx, float cy, float Size, float Angle, int GrHandle, int TransFlag)
概要 3D空間に画像を描画する
引数 VECTOR Pos 画像を描画する座標
float cx 描画する画像の中心X座標
float cy 描画する画像の中心Y座標
floar Size 描画する画像のサイズ
float Angle 描画する画像の回転角度(単位はラジアン)
int GrHandle 描画する画像ハンドル
int TransFlag 透明度を有効にするかどうか(TRUE:有効 FALSE:無効)
戻り値 0 成功
-1 エラー発生

奥行きに関わらず画像の大きさは常に一定にしたい場合は一度3D座標を2D座標に変換し、上で書いた DrawGrpah() を使って表示する。2D座標に変換するには ConvWorldPosToScreenPos() を使う。

宣言 VECTOR ConvWorldPosToScreenPos( VECTOR WorldPos )
概要 ワールド座標をスクリーン座標に変換する
引数 VECTOR WorldPos ワールド(3D)座標
戻り値 スクリーン(2D)座標

サンプルコード

以下サンプルコード。下の画像を分割読み込みして1つは画面左上に、1つは DrawBillboard3D() を使って、1つは3D座標を2D座標に変換をして表示するコード。

分割読み込みする画像例

画像を扱うソースファイル Image.cpp/h を作成してそこに処理を書き込んでいく。

Image.h

#ifndef DEF_IMAGE_H

#define DEF_IMAGE_H

void Image_Initialize(); //画像の初期化
bool Image_CalculatePos(VECTOR* pos); //3D座標の計算
void Image_Update(); //画像の情報更新
void Image_Draw(); //画像の描画
void Image_Finalize(); //画像の終了処理

#endif

Image.cpp

#include "DxLib.h"
#include "Image.h"
#include "Input.h"
#include "Camera.h"
#include "Define.h"

const static int MAX_IMG_NUM = 4;

static int ImgHandle[MAX_IMG_NUM];

//画像の初期化
void Image_Initialize() {
	//画像の分割読み込み
	LoadDivGraph("(読み込みたい画像のパス)", MAX_IMG_NUM, 2, 2, 128, 128, ImgHandle);
}

//3D空間で画像を表示する座標を計算
bool Image_CalculatePos(VECTOR *pos) {
	VECTOR tmp1, tmp2;
	float dot;

	//カメラの座標を取得
	tmp1 = Camera_GetEye();

	//カメラの注視点を取得
	tmp2 = Camera_GetTarget();

	//カメラ→注視点のベクトルを作成
	tmp2 = VSub(tmp2, tmp1);

	//カメラ→任意の座標のベクトルを作成
	tmp1 = VSub(*pos, tmp1);

	//tmp1とtmp2の内積を求める
	dot = VDot(tmp1, tmp2);

	//内積dotが0より大きい(=カメラの画面内にある)場合のみ座標を計算
	if (dot > 0) {
		*pos = ConvWorldPosToScreenPos(*pos);
		return true;
	}
	
	return false;
}

//画像の情報更新
void Image_Update() {

}

//画像の描画
void Image_Draw() {
	VECTOR Pos;

	//ImgHandle[0]を画面左上に描画
	DrawGraph(0, 0, ImgHandle[0], TRUE);

	Pos = VGet(10.0f, 2.0f, 10.0f);

	//ImgHandle[1]を特定の3D空間の場所に描画
	DrawBillboard3D(Pos, 0.5f, 0.5f, 1.0f, 0.0f, ImgHandle[1], TRUE);

	Pos = VGet(-10.0f, 2.0f, -10.0f);

	if (Image_CalculatePos(&Pos)) {
		//ImgHandle[2]を特定の3D空間の場所に描画
		DrawGraph((int)Pos.x, (int)Pos.y, ImgHandle[2], TRUE);
	}
}

//画像の終了処理
void Image_Finalize() {
	for (int i = 0; i < MAX_IMG_NUM; i++) {
		DeleteGraph(ImgHandle[i]);
	}
}

3D座標を2D座標に変換して表示する場合、そのまま描画させるとカメラの視野外に座標があっても描画されることがある。なのでカメラの視野内に座標があるかどうか調べる処理を入れている。カメラ→注視点のベクトルとカメラ→画像を描画したい3D座標のベクトルのなす角(内積)で判断している。

あとは Game.cpp に画像処理関連を呼ぶ。

Game.cpp

//以下のヘッダーファイルを追加でインクルードする
#include "Image.h"

//初期化関数に以下の処理を追加
void Game_Initialize() {
    //略

    //画像の情報初期化
    Image_Initialize();
}

//更新関数に以下の処理を追加
void Game_Update() {
    //略

    //画像の情報更新
    Image_Update();

    //略
}

//描画関数に以下の処理を追加
void Game_Draw() {
    //略

    //画像の描画
    Image_Draw();
}

//終了処理関数に以下の処理を追加
void Game_Finalize() {
    //略

    Image_Finalize();
}

コメント

タイトルとURLをコピーしました