0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【DXライブラリ】Effekseerで3Dエフェクトを実装する方法

Last updated at Posted at 2024-11-20

はじめに

記事作成者は専門学校にてDXライブラリを使用しゲームを制作した者です。

誤った情報もあるかもしれませんので、この記事のみを鵜呑みにするのは勘弁してください。

今回は3Dエフェクトのみ解説します。
2Dエフェクトはエフェクシア公式様のサンプルをご確認ください。

DXライブラリの初期設定は行っているものとします。

実装イメージ

こんな爆発エフェクトを実装していきます↓

スクリーンショット 2024-11-20 152258.png

環境

  • OS: Windows11
  • 開発環境: Visual Studio 2022

Effekseer(エフェクシアについて)

DXライブラリ、Unity等で使用できるエフェクトツールです。
→ https://effekseer.github.io/jp/

DXライブラリでエフェクトを追加するなら一番簡単で効果的な方法かと思います。

今回はこちらを利用してDXライブラリでエフェクトを実装します。

お品書き

  1. Effekseerダウンロード
  2. VisualStudioにて追加のインクルードディレクトリを指定
  3. コード実装
  4. ピックアップ解説
  5. まとめ
  6. 参考サイト

1. Effekseerダウンロード

リンク→https://effekseer.github.io/jp/index.html
公式サイトからDXライブラリに対応したエフェクシアのライブラリをダウンロードしていきます。↓

スクリーンショット 2024-11-13 162030.png


Effeksser For DXライブラリをダウンロード↓

スクリーンショット 2024-11-13 162030 (1).png


ファイルを解凍します。↓解凍後

スクリーンショット 2024-11-13 162407.png


分かりやすいようファイル名を「EffekseerForDXLib」に変更しておきます↓

スクリーンショット 2024-11-17 141356.png

2. VisualStudioにて追加のインクルードディレクトリを指定

現在のプロジェクトにエフェクシアのファイル内の内容を使用できるようにする作業です。

ダウンロードしたファイルをプロジェクトファイルと同様の階層に置きます
(これは自分の好きな場所でも大丈夫です)↓

スクリーンショット 2024-11-17 141608.png


プロジェクトファイルを開き、プロジェクト名の部分で右クリックします↓

新規プロジェクト (9).png


プロパティを選択↓

新規プロジェクト (10).png


プロパティ上部分の構成(C):を「すべての構成」、プラットフォーム(P):を「すべてのプラットフォーム」に設定されていることを確認↓

新規プロジェクト (11).png


構成プロパティ > C/C++ > 全般 > 追加のインクルードディレクトリ の右側のマークをクリック↓

新規プロジェクト (12).png


編集をクリック↓

新規プロジェクト (13).png


右上のファイルマークをクリック↓

スクリーンショット 2024-11-17 132929.png


ファイルパスを入力できるようになるので、「../EffekseerForDXLib」と入力↓

スクリーンショット 2024-11-17 141954.png


同様の手順で 構成プロパティ > リンカー > 全般 > 追加のライブラリディレクトリを指定↓
C/C++の時と同様に「../EffekseerForDXLib

(右のマークを押さずに、直入力でもできます。)

スクリーンショット 2024-11-17 142147.png


「適用」をクリック後、「OK」をクリック↓

スクリーンショット 2024-11-17 142430.png


これでエフェクシア導入は完了しました。

EffekseerForDXLibファイル内にDXライブラリ使用で必要なファイルもすでに入っているので
この作業で指定するファイルはEffekseerForDXLibのみで大丈夫です。

エラーや不明点があるときは「絶対参照、相対参照ファイルパス」
などで検索して解決するとよいと思います。

3. コード実装

注意事項

  • 今回は簡略されたクラスで実装します
  • 3Dエフェクトを再生する際はカメラが実装されていなければなりません

実用的な実装にする際はエフェクト利用を行うクラスにクラス分けしたり、
すべてのエフェクトをまとめて管理するシングルトンクラスなどにすると良いかもしれません

実装するクラス

  • EffectManager: エフェクトを管理するクラスです
  • Camera: カメラを管理するクラスです
  • TestObject: 動かせるプレイヤー、ステージを管理するクラスです

それでは実装コードです。

EffectManager.h
#pragma once
#include <EffekseerForDXLib.h> // 先ほど指定したエフェクシアファイルをインクルード

// エフェクト管理クラス
class EffectManager
{
public:
	EffectManager();					// コンストラクタ
	~EffectManager();					// デストラクタ
	void Initialize();					// 初期化
	void Load();						// 読み込み
	void Update(VECTOR playPosition);	// 更新
	void Draw();						// 描画
private:
	// 定数
	const int	EffectParticleLimit	= 20000;				// 画面に表示できる最大パーティクル数
	const char* EffectFilePath		= "Data/Flame.efk";		// エフェクトのファイルパ
	const float EffectSize			= 1.0f;					// エフェクトのサイズ
	const int	EffectPlayInterval	= 300;					// エフェクトを再生する周期
	const float	EffectMoveSpeed		= 0.2f;					// エフェクトが移動する速度

	// 変数
	int effectResourceHandle;	// エフェクトのリソース用
	int playingEffectHandle;	// 再生中のエフェクトハンドル
	
	// 今回の動作でにみ必要な変数
	int		playCount;			// 周期敵に再生するためのカウント
};


EffectManager.cpp
#include "DxLib.h"
#include "EffectManager.h"

// コンストラクタ
EffectManager::EffectManager()
    : effectResourceHandle  (-1)
    , playingEffectHandle   (-1)
    , playCount             (0)
{
    // 初期化
    Initialize();

    // 読み込み
    Load();
}

// デストラクタ
EffectManager::~EffectManager()
{
    // エフェクトリソースの開放
    // (Effekseer終了時に破棄されるので削除しなくてもいい)
    DeleteEffekseerEffect(effectResourceHandle);
}

// 初期化
void EffectManager::Initialize()
{
    // DirectX11を使用するようにする。(DirectX9も可、一部機能不可)
    // Effekseerを使用するには必ず設定する。
    SetUseDirect3DVersion(DX_DIRECT3D_11);

    // 引数には画面に表示する最大パーティクル数を設定する。
    if (Effkseer_Init(EffectParticleLimit) == -1) { DxLib_End(); }

    // フルスクリーンウインドウの切り替えでリソースが消えるのを防ぐ。
    // Effekseerを使用する場合は必ず設定する。
    SetChangeScreenModeGraphicsSystemResetFlag(FALSE);

    // DXライブラリのデバイスロストした時のコールバックを設定する。
    // ウインドウとフルスクリーンの切り替えが発生する場合は必ず実行する。
    Effekseer_SetGraphicsDeviceLostCallbackFunctions();

    // Zバッファを有効にする。
    // Effekseerを使用する場合、2DゲームでもZバッファを使用する。
    SetUseZBuffer3D(TRUE);

    // Zバッファへの書き込みを有効にする。
    // Effekseerを使用する場合、2DゲームでもZバッファを使用する。
    SetWriteZBuffer3D(TRUE);
}

// 読み込み
void EffectManager::Load()
{
    // エフェクトのリソースを読み込む
    effectResourceHandle = LoadEffekseerEffect(EffectFilePath, EffectSize);
}

/// <summary>
/// 更新
/// </summary>
/// <param name="playPosition">再生座標</param>
void EffectManager::Update(VECTOR playPosition)
{
    // 定期的にエフェクトを再生する
    if (!(playCount % EffectPlayInterval))
    {
        // エフェクトを再生する。
        playingEffectHandle = PlayEffekseer3DEffect(effectResourceHandle);
    }

    // 再生カウントを進める
    playCount++;

    // 再生中のエフェクトを移動する。
    SetPosPlayingEffekseer3DEffect(playingEffectHandle, playPosition.x, playPosition.y, playPosition.z);

    // Effekseerにより再生中のエフェクトを更新する。
    UpdateEffekseer3D();
}

// 描画
void EffectManager::Draw()
{
    // Effekseerにより再生中のエフェクトを描画する。
    DrawEffekseer3D();
}

Camera.h
#pragma once
#include <EffekseerForDXLib.h>
class Camera
{
public:
	Camera();			// コンストラクタ
	~Camera();			// デストラクタ
	void Initialize();	// 初期化
	void Update();		// 更新
private:
	// 定数
	const float	 CameraNearClip				= 0.1f;			// カメラから見て最も近い描画距離の設定
	const float	 CameraFarClip				= 600.0f;		// カメラから見て最も遠い描画距離の設定
	const VECTOR InitializePosition			= { 0,10,-50 };	// 初期化時の座標
	const VECTOR InitializeTargetPosition	= { 0,0,0 };	// 初期化時の視点座標
	const float  FovDegrees = 60.0f * DX_PI_F / 180.0f;		// カメラの視野角(度数)
	// 変数
	VECTOR	position;			// 座標(どこから見るのか)
	VECTOR	targetPosition;		// 視点座標(自分が見ている位置)
};
Camera.cpp
#include "Camera.h"
// コンストラクタ
Camera::Camera()
    : position          (InitializePosition)
    , targetPosition    (InitializeTargetPosition)
{
    // 初期化
    Initialize();
}

// デストラクタ
Camera::~Camera()
{
    // 処理なし
}

// 初期化
void Camera::Initialize()
{
    // 描画範囲の設定
    SetCameraNearFar(CameraNearClip, CameraFarClip);

    // カメラを設定
    SetCameraPositionAndTarget_UpVecY(position, targetPosition);

    // 視野角設定
    SetupCamera_Perspective(FovDegrees);
}

// 更新
void Camera::Update()
{
    // DXライブラリのカメラとEffekseerのカメラを同期する。
    Effekseer_Sync3DSetting();

    // カメラの更新
    SetCameraPositionAndTarget_UpVecY(position, targetPosition);
}
TestObject.h
#pragma once
#include <EffekseerForDXLib.h>

// とりあえずオブジェクト実装
// テスト用オブジェクト
class TestObject
{
public:
	TestObject();
	~TestObject();
	void Update();
	void Draw();
	VECTOR GetPlayerPosition() { return playerPosition; }
private:
	VECTOR playerPosition;	// プレイヤー座標
	VECTOR stagePosition;	// ステージ座標
	int playerModelHandle;	// プレイヤーモデルハンドル
	int stageModelHandle;	// ステージモデルハンドル
};
TestObject.cpp
#include "TestObject.h"

TestObject::TestObject()
    : playerPosition    (VGet(0,0,0))
    , stagePosition     (VGet(0,-10,0))
{
    // モデル読み込み
    playerModelHandle = MV1LoadModel("Data/PlayerModel.mv1");
    stageModelHandle = MV1LoadModel("Data/StageModel.mv1");

    // スケール調整
    MV1SetScale(playerModelHandle, VGet(0.01f, 0.01f, 0.01f));
    MV1SetScale(stageModelHandle, VGet(0.1f,0.1f, 0.1f));
}

TestObject::~TestObject()
{
    // モデル削除
    MV1DeleteModel(playerModelHandle);
    MV1DeleteModel(stageModelHandle);
}

void TestObject::Update()
{
    // プレイヤーの移動
    if (CheckHitKey(KEY_INPUT_LEFT)) { playerPosition.x -= 0.25f; }
    else if (CheckHitKey(KEY_INPUT_RIGHT)) { playerPosition.x += 0.25f; }
    if (CheckHitKey(KEY_INPUT_UP)){ playerPosition.z += 0.25f; }
    else if (CheckHitKey(KEY_INPUT_DOWN)){ playerPosition.z -= 0.25f; }

    // 座標更新
    MV1SetPosition(playerModelHandle, playerPosition);
    MV1SetPosition(stageModelHandle, stagePosition);
}

void TestObject::Draw()
{
    // モデル描画
    MV1DrawModel(playerModelHandle);
    MV1DrawModel(stageModelHandle);
}
Main.cpp
#include <EffekseerForDXLib.h>
#include "EffectManager.h"
#include "Camera.h"
#include "TestObject.h"

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	ChangeWindowMode(true);
	SetDrawScreen(DX_SCREEN_BACK);
	if (DxLib_Init() == -1) { return -1; }

	// インスタンス化
	EffectManager	effectManager;	// エフェクト管理クラス
	Camera			camera;			// カメラ
	TestObject		testObject;		// テストオブジェクト

	// ゲームループ
	while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && !CheckHitKey(KEY_INPUT_ESCAPE))
	{
		// 更新
		testObject.Update();
		camera.Update();
		effectManager.Update(testObject.GetPlayerPosition());

		// 描画
		testObject.Draw();
		effectManager.Draw();
	}

	// Effekseerを終了する。
	Effkseer_End();

	// DXライブラリの後始末
	DxLib_End();

	return 0;				// ソフトの終了
}

必要ファイル

このプロジェクト内に必要なエフェクトデータをダウンロードしてください↓


このようなファイル構成位置にしてください↓

スクリーンショット 2024-11-20 141108.png

※必ずDataフォルダプロジェクトファイルと同じファイル階層においてください。

この実装で起動確認してます。

4. ピックアップ解説

この部分は脳死で実装しないと動作しません。↓

EffectManager.cpp
// 初期化
void EffectManager::Initialize()
{
    SetUseDirect3DVersion(DX_DIRECT3D_11);
    if (Effkseer_Init(EffectParticleLimit) == -1) { DxLib_End(); }    
    SetChangeScreenModeGraphicsSystemResetFlag(FALSE);
    Effekseer_SetGraphicsDeviceLostCallbackFunctions();
    SetUseZBuffer3D(TRUE);
    SetWriteZBuffer3D(TRUE);
}

この流れで実装したら基本いけると思います↓

  1. 読み込み        LoadEffekseerEffect
  2. 再生          PlayEffekseer3DEffect
  3. 再生座標設定      SetPosPlayingEffekseer3DEffect
  4. すべての再生座標更新  UpdateEffekseer3D
  5. すべてのエフェクト描画 DrawEffekseer3D

LoadEffekseerEffectで読み込むファイルについて

読み込むファイルは必ず.efkファイルでないとエラーが発生します。

リソースハンドル = LoadEffekseerEffect("Data/Flame.efk"); // としてください

.efkprojファイルがありますが、これはエフェクシアのツール上で使用するファイルです。
efkefcファイルはefkファイル同様に使用できるようです。

  1. .efkproj をエフェクシアツールで開く
  2. ゲームエンジンで使用可能な形にエクスポート
  3. .efk が出力される

エフェクシアは本来エフェクトを制作、編集するツールですのでそちらを利用して自分が使用したいエフェクトを作成する形になります。
(自分は公式サイト様からすでに作成されているエフェクトを利用させていただきました。)

分からなかったら.efkファイルだけ使いましょう。

5. まとめ

簡単にDXライブラリでエフェクシアを実装する方法についてまとめてみました。
実用的なものには程遠いですが、参考になれば幸いです。

最後に作成したプロジェクトファイルのリンクを置いておきます。↓
https://drive.google.com/drive/folders/1UwZ8tpZxEFtKaHM8cp2TO02twBLF3nSl?usp=sharing

6. 参考サイト

EffekseerのDXライブラリで使用可能なすべての関数↓
https://github.com/effekseer/EffekseerForDXLib/blob/master/Dev/EffekseerForDXLib/EffekseerForDXLib.h

0
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?