はじめに
記事作成者は専門学校にてDXライブラリを使用しゲームを制作した者です。
誤った情報もあるかもしれませんので、この記事のみを鵜呑みにするのは勘弁してください。
今回は3Dエフェクトのみ解説します。
2Dエフェクトはエフェクシア公式様のサンプルをご確認ください。
DXライブラリの初期設定は行っているものとします。
実装イメージ
こんな爆発エフェクトを実装していきます↓
環境
- OS: Windows11
- 開発環境: Visual Studio 2022
Effekseer(エフェクシアについて)
DXライブラリ、Unity等で使用できるエフェクトツールです。
→ https://effekseer.github.io/jp/
DXライブラリでエフェクトを追加するなら一番簡単で効果的な方法かと思います。
今回はこちらを利用してDXライブラリでエフェクトを実装します。
お品書き
- Effekseerダウンロード
- VisualStudioにて追加のインクルードディレクトリを指定
- コード実装
- ピックアップ解説
- まとめ
- 参考サイト
1. Effekseerダウンロード
リンク→https://effekseer.github.io/jp/index.html
公式サイトからDXライブラリに対応したエフェクシアのライブラリをダウンロードしていきます。↓
Effeksser For DXライブラリをダウンロード↓
ファイルを解凍します。↓解凍後
分かりやすいようファイル名を「EffekseerForDXLib」に変更しておきます↓
2. VisualStudioにて追加のインクルードディレクトリを指定
現在のプロジェクトにエフェクシアのファイル内の内容を使用できるようにする作業です。
ダウンロードしたファイルをプロジェクトファイルと同様の階層に置きます
(これは自分の好きな場所でも大丈夫です)↓
プロジェクトファイルを開き、プロジェクト名の部分で右クリックします↓
プロパティを選択↓
プロパティ上部分の構成(C):を「すべての構成」、プラットフォーム(P):を「すべてのプラットフォーム」に設定されていることを確認↓
構成プロパティ > C/C++ > 全般 > 追加のインクルードディレクトリ の右側のマークをクリック↓
編集をクリック↓
右上のファイルマークをクリック↓
ファイルパスを入力できるようになるので、「../EffekseerForDXLib
」と入力↓
同様の手順で 構成プロパティ > リンカー > 全般 > 追加のライブラリディレクトリを指定↓
C/C++の時と同様に「../EffekseerForDXLib
」
(右のマークを押さずに、直入力でもできます。)
「適用」をクリック後、「OK」をクリック↓
EffekseerForDXLibファイル
内にDXライブラリ使用で必要なファイルもすでに入っているので
この作業で指定するファイルはEffekseerForDXLib
のみで大丈夫です。
エラーや不明点があるときは「絶対参照、相対参照ファイルパス」
などで検索して解決するとよいと思います。
3. コード実装
注意事項
- 今回は簡略されたクラスで実装します
- 3Dエフェクトを再生する際はカメラが実装されていなければなりません
実用的な実装にする際はエフェクト利用を行うクラスにクラス分けしたり、
すべてのエフェクトをまとめて管理するシングルトンクラスなどにすると良いかもしれません
実装するクラス
-
EffectManager
: エフェクトを管理するクラスです -
Camera
: カメラを管理するクラスです -
TestObject
: 動かせるプレイヤー、ステージを管理するクラスです
それでは実装コードです。
#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; // 周期敵に再生するためのカウント
};
#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();
}
#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; // 視点座標(自分が見ている位置)
};
#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);
}
#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; // ステージモデルハンドル
};
#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);
}
#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; // ソフトの終了
}
必要ファイル
このプロジェクト内に必要なエフェクトデータをダウンロードしてください↓
このようなファイル構成位置にしてください↓
※必ずDataフォルダ
をプロジェクトファイル
と同じファイル階層においてください。
この実装で起動確認してます。
4. ピックアップ解説
// 初期化
void EffectManager::Initialize()
{
SetUseDirect3DVersion(DX_DIRECT3D_11);
if (Effkseer_Init(EffectParticleLimit) == -1) { DxLib_End(); }
SetChangeScreenModeGraphicsSystemResetFlag(FALSE);
Effekseer_SetGraphicsDeviceLostCallbackFunctions();
SetUseZBuffer3D(TRUE);
SetWriteZBuffer3D(TRUE);
}
LoadEffekseerEffect
で読み込むファイルについて
読み込むファイルは必ず.efk
ファイルでないとエラーが発生します。
リソースハンドル = LoadEffekseerEffect("Data/Flame.efk"); // としてください
.efkproj
ファイルがありますが、これはエフェクシアのツール上で使用するファイルです。
efkefc
ファイルはefk
ファイル同様に使用できるようです。
-
.efkproj
をエフェクシアツールで開く - ゲームエンジンで使用可能な形にエクスポート
-
.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