Support System
開発支援・ユーティリティ構造
FlFileWatcher – ファイル監視と資産同期
FlFileWatcher は、エディタ環境におけるファイル変化の検出・自動更新・同期の中核です。
std::filesystem と std::thread を活用し、非同期にディレクトリ全体を監視します。
更新が検出されると、即座にコールバックを通じて関連システム (例:メタファイル更新・アセット再ロード) へ反映します。
// --- 抜粋: FlFileWatcher::Start ---
void FlFileWatcher::Start(Callback callback)
{
m_running = true;
m_thread = std::thread([this, callback]() {
while (m_running) {
std::this_thread::sleep_for(m_interval);
// ファイル更新・新規作成検出
for (auto& file : std::filesystem::recursive_directory_iterator(m_pathToWatch)) {
const auto pathStr = file.path().string();
const auto lastWriteTime = std::filesystem::last_write_time(file);
if (!Contains(pathStr)) {
m_paths[pathStr] = lastWriteTime;
callback(file.path(), FileStatus::Created);
}
else if (m_paths[pathStr] != lastWriteTime) {
m_paths[pathStr] = lastWriteTime;
callback(file.path(), FileStatus::Modified);
}
}
// 削除検出
for (auto it = m_paths.begin(); it != m_paths.end();) {
if (!std::filesystem::exists(it->first)) {
callback(it->first, FileStatus::Erased);
it = m_paths.erase(it);
} else ++it;
}
}
});
}
主な特徴
Created / Modified / Erasedの3状態をリアルタイム検出- 非同期監視によるUIブロッキングの回避
- フォルダ階層全体を再帰的に走査
- ファイル/ディレクトリ操作 (追加・削除・移動・リネーム・コピー) を内包
FlVisualStudioManager – Visual Studioのプロジェクト自動生成・追加
FlVisualStudioManager は、FlScriptModuleEditorで入力された名前でプロジェクトとフィルタと必要最低限のコードファイルを
テンプレートコードから作成、またはそのプロジェクトの削除を行います。
.slnにプロジェクトを追加し、プリコンパイルヘッダなどの設定を済ませます。
// --- 抜粋: FlVisualStudioProjectManager::CreateNewProject ---
auto projDir = targetDir / projectName;
// ---------------------------------------------------
// (1) ディレクトリ作成
// ---------------------------------------------------
try {
std::filesystem::create_directories(projDir);
}
catch (...) {
FlEditorAdministrator::Instance().GetLogger()->AddErrorLog("Failed to create directory: %s", projDir.string().c_str());
return false;
}
// ---------------------------------------------------
// (2) 初期コードファイル生成
// ---------------------------------------------------
if (!CreateSourceFiles(projDir, projectName)) {
return false;
}
// ---------------------------------------------------
// (3) .vcxproj と .filters を生成
// ---------------------------------------------------
if (!CreateVcxproj(projDir, projectName)) return false;
if (!CreateFilters(projDir, projectName)) return false;
// ---------------------------------------------------
// (4) .sln に Project を追加
// ---------------------------------------------------
auto projFile = projDir / (projectName + ".vcxproj");
if (!AddProjectToSolution(m_solutionPath, projFile, projectName)) {
return false;
}
FlEditorAdministrator::Instance().GetLogger()->AddLog("Project '%s' created & added to solution.", projectName.c_str());
return true;
主な特徴
- プロジェクトファイルの作成・削除
- フィルタファイルの作成・削除
- .sinへの動的追加・削除
- Script用抽象化されたコンパイル対象外のコードファイルの自動生成
FlAutomaticFileAddSystem – 自動コード生成とXMLパーサ連携
FlAutomaticFileAddSystem は、
新しいコードファイルを、.vcxproj および .filters に即時登録するためのシステムです。
内部的には tinyxml2 によるXMLパーサを利用してVisual
Studioのプロジェクト構成を解析・更新します。
// --- 抜粋: FlAutomaticFileAddSystem::AddFiles ---
if (files.empty()) return true;
auto normalizedFilterPath{ std::filesystem::path(filterPath).lexically_normal().string()};
// 出力先ディレクトリの作成
auto outputDir{ m_projectDir / normalizedFilterPath };
if (!std::filesystem::exists(outputDir))
{
try {
std::filesystem::create_directories(outputDir);
}
catch (...) {
return false;
}
}
// 1. 実ファイルの書き込み
for (const auto& file : files)
{
auto fullPath = outputDir / file.fileName;
if (!WriteFileToDisk(fullPath, file.content)) return false;
}
// 2. vcxprojの更新 (一度だけLoad/Save)
{
tinyxml2::XMLDocument doc;
if (doc.LoadFile(m_vcxprojPath.string().c_str()) != XML_SUCCESS) return false;
for (const auto& file : files)
{
auto fullPath = outputDir / file.fileName;
if (file.itemType == Def::EmptyStr) AddToVcxproj(doc, fullPath, DetectItemType(file.fileName));
else AddToVcxproj(doc, fullPath, file.itemType);
}
if (doc.SaveFile(m_vcxprojPath.string().c_str()) != XML_SUCCESS) return false;
}
// 3. filtersの更新 (一度だけLoad/Save)
{
tinyxml2::XMLDocument doc;
if (doc.LoadFile(m_filtersPath.string().c_str()) != XML_SUCCESS) return false;
// 指定されたフィルタ階層が存在しない場合は作成
EnsureFilterPathExists(doc, normalizedFilterPath);
for (const auto& file : files)
{
auto fullPath = outputDir / file.fileName;
if (file.itemType == Def::EmptyStr) AddToFilters(doc, fullPath, DetectItemType(file.fileName), normalizedFilterPath);
else AddToFilters(doc, fullPath, file.itemType, normalizedFilterPath);
}
if (doc.SaveFile(m_filtersPath.string().c_str()) != XML_SUCCESS) return false;
}
return true;
上記の関数は、指定したフィルタに複数のコードファイルを プロジェクトファイルへXML要素を追加します。 フィルタ階層の作成や一意識別子の付与も自動化されており、 Visual Studio上でのソース構成を即座に反映します。
XML操作の一例
// --- 抜粋: FlAutomaticFileAddSystem::AddToFilters ---
XMLElement* root = doc.RootElement();
if (!root) return false;
// ItemTypeに対応するItemGroupを探す
XMLElement* itemGroup = nullptr;
for (XMLElement* ig = root->FirstChildElement("ItemGroup"); ig; ig = ig->NextSiblingElement("ItemGroup"))
{
if (ig->FirstChildElement(itemType.c_str()))
{
itemGroup = ig;
break;
}
}
if (!itemGroup)
{
itemGroup = doc.NewElement("ItemGroup");
root->InsertEndChild(itemGroup);
}
auto relPath = std::filesystem::relative(filePath, m_projectDir).generic_string();
std::string filterPathWin = filterPathStr;
std::replace(filterPathWin.begin(), filterPathWin.end(), '/', '\\');
// 重複チェック
for (XMLElement* e = itemGroup->FirstChildElement(itemType.c_str()); e; e = e->NextSiblingElement(itemType.c_str()))
{
const char* inc = e->Attribute("Include");
if (inc && relPath == inc) return true;
}
XMLElement* elem = doc.NewElement(itemType.c_str());
elem->SetAttribute("Include", relPath.c_str());
XMLElement* filterElem = doc.NewElement("Filter");
filterElem->SetText(filterPathWin.c_str());
elem->InsertEndChild(filterElem);
itemGroup->InsertEndChild(elem);
return true;
主な特徴
- tinyxml2 によるXML DOM構造操作
- Visual Studioプロジェクトとの完全同期
- フィルタ階層の自動作成
FlScriptModuleEditorからのGUIファイル監視により動作
FlSolutionParser – Visual Studioソリューション構造解析
FlSolutionParser は、Visual Studio の .sln ファイルを解析し、
含まれる .vcxproj プロジェクトの構造情報を抽出するためのユーティリティです。
Editor内部では、プロジェクトのBuildに活用されています。
// --- 抜粋: FlSolutionParser::Load ---
bool FlSolutionParser::Load(const std::filesystem::path& slnPath)
{
m_projects.clear();
m_solutionPath = slnPath;
std::ifstream file(slnPath);
if (!file.is_open()) return false;
std::string line;
while (std::getline(file, line)) {
if (line.rfind("Project(", 0) == 0)) {
// ダブルクォート位置を取得
std::vector<size_t> quotes;
for (size_t pos = 0; pos < line.size(); ++pos)
if (line[pos] == '"') quotes.push_back(pos);
if (quotes.size() >= 6) {
// プロジェクト名・パス抽出
std::string name = line.substr(quotes[2] + 1, quotes[3] - quotes[2] - 1);
std::string relPath = line.substr(quotes[4] + 1, quotes[5] - quotes[4] - 1);
std::replace(relPath.begin(), relPath.end(), '\\', '/');
std::filesystem::path projectPath = m_solutionPath.parent_path() / relPath;
std::string ext = projectPath.extension().string();
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
if (ext == ".vcxproj") {
FlProjectInfo info;
info.name = name;
info.relativePath = relPath;
info.fullPath = std::filesystem::absolute(projectPath).lexically_normal();
m_projects.push_back(info);
}
}
}
}
return !m_projects.empty();
}
主な特徴
- Visual Studio ソリューション (
.sln) ファイルの構造を正確に解析 .vcxprojパス・プロジェクト名を動的に取得- 文字列解析には安全なクォート位置検出を採用
FindProjectByName()による検索機能を提供- パスの正規化と相対変換を自動で実施
利用例
FlSolutionParser parser;
if (parser.Load("FalconEngine.sln")) {
const auto* project = parser.FindProjectByName("FlComponentSystem");
if (project)
std::cout << "Found project: " << project->name
<< " at " << project->fullPath << std::endl;
}
このクラスは、MSBuildコマンドでBuildもしくはCleanを行うために、ソリューションに含まれるプロジェクトの名前とパスを検出します。
FlChronus – 時間制御と計測ユーティリティ
FlChronus は、時間管理・計測・制御の基盤を担うユーティリティクラスです。 ストップウォッチ、ラップタイマー、ティッカー、FPS計測、スコープ計測など、 開発・計測・最適化のあらゆる場面で活用できる高精度ツール群を内包しています。
// --- 抜粋: FlChronus 基本構造 ---
class FlChronus
{
public:
using Steady = std::chrono::steady_clock; // 経過時間用 (単調時計)
using System = std::chrono::system_clock; // 現実時間用 (壁時計)
FlChronus(bool startNow = true) { if (startNow) start(); }
void start() noexcept { if (!_running) { _running = true; _t0 = Steady::now(); } }
void stop() noexcept { if (_running) { _acc += Steady::now() - _t0; _running = false; } }
void reset() noexcept { _acc = Dur::zero(); _running = false; _t0 = Steady::now(); }
template
D elapsed() const noexcept {
Dur d{ _acc };
if (_running) d += (Steady::now() - _t0);
return std::chrono::duration_cast(d);
}
};
主な構成機能
- Stopwatch – スタート・ストップ・リセット・ラップ計測
- Countdown – 残り時間や期限までのカウントダウン管理
- Ticker – 一定間隔でイベントを発生させるティッカー(定期処理)
- FpsAverager – フレームレートの移動平均を算出
- Scoped – スコープ終了時に自動で時間を計測・ログ出力
便利ユースケース例
// --- 例1: FPSの計測 ---
FlChronus::FpsAverager fpsAvg;
auto [current, average] = fpsAvg.on_frame();
std::cout << "FPS: " << current << " (" << average << " avg)\n";
// --- 例2: スコープ計測 ---
{
FlChronus::Scoped measure([](auto dur){
std::cout << "処理時間: " << FlChronus::to_seconds(dur) << "秒\n";
});
RunHeavyProcess(); // 処理時間を自動計測
}
特徴
std::chronoベースの高精度な時間制御- ISO8601形式の現在時刻文字列生成
- カウントダウン・ティッカーなど周期的処理の簡易化
FlEasing – アニメーション補間関数ライブラリ
FlEasing は、アニメーションやトランジション効果に滑らかな動きを付与するための イージング関数群をまとめたユーティリティクラスです。 物理的な動きや自然な加速・減速をシンプルに表現でき、 UIエフェクト・ゲーム演出・補間計算など幅広く利用できます。
// --- 抜粋: FlEasing 基本構造 ---
class FlEasing
{
public:
static double Linear(double t) noexcept { return t; }
// 二次曲線 (Quad)
static double EaseInQuad(double t) noexcept { return t * t; }
static double EaseOutQuad(double t) noexcept { return t * (2 - t); }
// 三次曲線 (Cubic)
static double EaseInCubic(double t) noexcept { return t * t * t; }
static double EaseOutCubic(double t) noexcept { return 1 + (--t) * t * t; }
// 正弦補間 (Sine)
static double EaseInSine(double t) noexcept {
return 1 - std::cos((t * M_PI) / 2.0);
}
};
主な特徴
- Linear / Quad / Cubic / Quart / Quint など基本補間を網羅
- 物理的効果を再現する Sine / Expo / Circ / Back / Elastic / Bounce 系を収録
- EaseIn / EaseOut / EaseInOut の3種を全補間タイプで提供
- すべて
staticメソッドとして定義され即座に利用可能 noexcept指定でオーバーヘッドを最小化
使用例
// --- 例: 時間t[0,1]に応じて値を補間 ---
double t = 0.5;
double value = FlEasing::EaseInOutCubic(t);
pos.x = Math::Lerp(start.x, end.x, value);
pos.y = Math::Lerp(start.y, end.y, value);
このように、FlEasing はゲーム・UIエフェクト・スライダー挙動など あらゆる「時間変化」に直感的な表現力を与えます。 FlChronus と組み合わせることで、 時間制御と補間を高精度かつ簡潔に扱うことができます。
FlAnimator – 時間制御 × 補間の統合クラス
FlAnimator は、FlChronus と FlEasing を統合した
「時間ベース補間クラス」です。
アニメーションの経過時間を自動的に管理し、イージング関数を適用した進行度を算出します。
ゲーム内UI・トランジション・フェードなど、あらゆる時間変化処理を簡潔に実装できます。
// --- 抜粋: FlAnimator ---
class FlAnimator
{
public:
using EaseFunc = std::function<double(double)>;
FlAnimator(double durationSec, EaseFunc ease = FlEasing::Linear)
: m_duration(durationSec), m_ease(ease) {}
void start() { m_timer.start(); m_running = true; }
void reset() { m_timer.reset(); m_running = false; }
bool isRunning() const { return m_running && progress() < 1.0; }
// イージング適用済みの進行度 (0.0〜1.0)
double value() const { return m_ease(progress()); }
// 生の進行度(イージング未適用)
double progress() const {
if (!m_running) return 0.0;
double t = std::chrono::duration_cast<std::chrono::duration<double>>(
m_timer.elapsed()).count() / m_duration;
return std::clamp(t, 0.0, 1.0);
}
private:
FlChronus m_timer;
double m_duration;
EaseFunc m_ease;
bool m_running = false;
};
主な特徴
- FlChronus による高精度タイマー制御
- FlEasing 関数を動的に切替可能(ラムダ式も可)
value()は自動でイージング補正済み値を返す- アニメーションの進行状態を
isRunning()で即判定 - 任意の時間・関数・型に対応する汎用デザイン
使用例
// --- UIフェードアニメーション例 ---
FlAnimator fade(2.0, FlEasing::EaseInOutQuad);
fade.start();
while (fade.isRunning()) {
double alpha = fade.value(); // 0.0〜1.0 の補間値
DrawUI(alpha);
}
FlAnimator により、時間計測と補間を一体化した柔軟なアニメーション管理が可能です。 コード上での時間制御が明快になり、UI/演出処理を「データ駆動的」に記述できます。
FlMetaFileManager – アセットメタ情報自動生成・追従システム
FlMetaFileManager は、ゲームエンジン内で使用される全アセット(モデル・テクスチャ・サウンドなど)に対して、
一意の GUID と管理情報を付与するメタファイル (.flmeta) を自動生成・更新・追従するクラスです。
Unity の .meta 管理に類似しており、ファイルのリネーム・移動・削除にも自動対応します。
// --- 抜粋: FlMetaFileManager.h ---
class FlMetaFileManager
{
public:
void StartMonitoring(const std::string& rootPath, int intervalSeconds = 1);
void StopMonitoring();
void CreateMetaFileIfNotExist(const std::string& assetPath);
void OnAssetRenamedOrMoved(const std::filesystem::path& oldPath, const std::filesystem::path& newPath);
void IncrementLoadFlag(const std::string& assetPath);
const std::optional<std::string> FindAssetByGuid(const std::string& guid) const;
const std::optional<std::string> FindGuidByAsset(const std::filesystem::path& path) const;
private:
void CreateOrUpdateFlMetaFile(const std::filesystem::path& assetPath);
bool IsInsideFlMeta(const std::filesystem::path& path) const;
void OnFileEvent(const std::filesystem::path& path, FlFileWatcher::FileStatus status);
FlFileWatcher m_fileWatcher;
std::unordered_map<std::string, std::string> m_guidMap;
};
主な特徴
- .flmeta ファイルの自動生成・更新・削除を監視ベースで実施
- ファイル名変更やディレクトリ移動時にもメタ情報を追従
- GUID によるアセット一意識別と逆引き検索
- 親フォルダの更新や削除にも自動反映 (再帰的管理)
- アセット更新日時を
lastModified/lastUpdatedとして記録
動作概要
void FlMetaFileManager::StartMonitoring(const std::string& rootPath, int intervalSeconds)
{
m_rootPath = rootPath;
std::filesystem::create_directories(m_rootPath);
// 初回スキャンで既存アセットにメタ付与
for (const auto& entry : std::filesystem::recursive_directory_iterator(m_rootPath))
if (!IsInsideFlMeta(entry.path()))
CreateOrUpdateFlMetaFile(entry.path());
// ファイル監視開始
m_fileWatcher.SetPathAndInterval(rootPath, std::chrono::seconds(intervalSeconds));
m_fileWatcher.Start([this](const auto& path, auto status) {
OnFileEvent(path, status);
});
}
内部処理
- ファイル生成時 → 新規
.flmeta生成 - ファイル変更時 → 更新日時を比較し再シリアライズ
- ファイル削除時 → 対応するメタを削除、GUIDマップから除外
- フォルダ移動時 →
OnAssetRenamedOrMoved()が自動追従処理を実施
メタファイル例
{
"Guid": "B8345E9A-9A6E-42A3-A7E9-41F3AD9FEC15",
"assetPath": "Assets/Textures/skybox.png",
"isDirectory": false,
"lastModified": "2025-10-06T08:13:12Z",
"loadFlag": false
}
利用例
FlMetaFileManager meta;
meta.StartMonitoring("Assets");
// メタファイル自動生成・追従開始
if (auto guid = meta.FindGuidByAsset("Assets/Textures/skybox.png"))
std::cout << "GUID: " << *guid << std::endl;
// 移動時の追従処理
meta.OnAssetRenamedOrMoved("Assets/Textures/skybox.png", "Assets/Environment/skybox.png");
技術的ポイント
FlFileWatcherにより、ファイルイベント(作成・変更・削除)を非同期監視- GUID 発行は
FlGuidにより生成・保持(再発行防止) FlJsonUtility経由でメタ情報をシリアライズ / デシリアライズFlEditorAdministratorと連携し、操作ログを自動追加- メタファイルは
.FlMetaという隠しディレクトリ内に入れ他のAssetファイルとの混合を避ける
このクラスは、アセットの永続的な一意識別を保証し、 再インポートやエディタ再起動時にも GUID が保持されるよう設計されています。 ファイル管理の自動化基盤として FlFileEditor と密接に連携します。
FlResourceAdministrator – アセット統合管理システム
FlResourceAdministrator は、ゲーム内で使用するすべてのアセットを一元的に管理する中核クラスです。
Shader・Texture・Model・Audio・Binary
といった各種ローダーを統合し、
GUIDベースでキャッシュされたリソースを即座に取得できるよう設計されています。
各アセットローダーは Flyweight パターン
によって設計されており、
同一リソースの多重ロードを防ぎ、効率的なメモリ利用を実現します。
// --- 抜粋: FlResourceAdministrator.h ---
class FlResourceAdministrator
{
public:
void Load(const std::initializer_list<std::string>& assetsPaths) noexcept;
template<typename T>
const std::shared_ptr<T>& Get(const std::string& path);
template<typename T>
const std::shared_ptr<T>& GetByGuid(const std::string& guid);
void AllAssetsCacheClear() noexcept;
const auto& GetMetaFileManager() const noexcept { return m_meta; }
static auto& Instance() noexcept
{
static auto instance{ FlResourceAdministrator{} };
return instance;
}
private:
FlResourceAdministrator();
~FlResourceAdministrator();
std::unique_ptr<ShaderManager> m_shader;
std::unique_ptr<FlTextureManager> m_texture;
std::unique_ptr<ModelManager> m_model;
std::unique_ptr<FlAudioManager> m_audio;
std::unique_ptr<FlBinaryManager> m_binary;
std::unique_ptr<FlMetaFileManager> m_meta;
};
主な特徴
- アセットを統合管理: すべてのリソースローダーを単一クラスからアクセス
- GUIDベースの識別: Meta情報と連携し、アセットの一意性を保証
- キャッシュクリア対応: 全リソースのリロードを即座に実行可能
- シングルトン設計: エンジン全体で統一されたリソース管理を提供
動作概要
// --- Shader 取得例 ---
auto shader = FlResourceAdministrator::Instance().Get<ComPtr<ID3DBlob>>("Shaders/StandardVS.hlsl");
// --- Texture 取得例 ---
auto texture = FlResourceAdministrator::Instance().Get<Texture>("Textures/UI/button.png");
// --- GUID から直接取得 ---
auto model = FlResourceAdministrator::Instance().GetByGuid<ModelData>("A1B2C3D4-5678-9012-3456-ABCDEF123456");
Flyweight パターンの構造
各ローダーは共通の基底クラス BaseBasicResourceManager<T> を継承しており、
アセットのロード済みキャッシュを共有します。これにより、同一アセットを複数オブジェクトで参照しても
メモリ上には一つだけのインスタンスが存在します。
// --- 抜粋: BaseBasicResourceManager.h ---
template<typename T>
class BaseBasicResourceManager
{
public:
virtual ~BaseBasicResourceManager() = default;
virtual const bool Load(const std::string& path) = 0;
const std::shared_ptr<T>& Get(const std::string& path, const std::string& guid) noexcept
{
// 既にロード済みなら再利用
if (auto it = m_resources.find(guid); it != m_resources.end())
return it->second;
// 未ロードならロード処理を実行
if (!Load(path)) return nullptr;
return m_resources[guid];
}
void Clear() { m_resources.clear(); }
protected:
std::unordered_map<std::string, std::shared_ptr<T>> m_resources;
};
技術的ポイント
- テンプレート対応: 取得時の型指定で自動的に適切なローダーを選択
- スマートポインタ管理: 共有ポインタでメモリの安全性と寿命管理を統一
FlResourceAdministrator は、アセットパイプラインの中心的な役割を担います。 ファイル監視・キャッシュ・識別を自動化し、 各アセットマネージャーとの連携によって “一度ロードしたものをどこでも即座に再利用” できる環境を構築しています。
FlAssetProtector – アセット暗号化システム
FlAssetProtector は、ゲーム開発中および配布時の アセットの二次配布防止・データ秘匿化 を目的とした 軽量暗号化システムです。 スタティックライブラリとしてビルドされ、ゲーム本体とは独立して動作するため、 不正な復号・解析を難しくします。
// --- 抜粋: FlCrypter.h ---
namespace FlAssetProtector
{
class CryptoManager
{
public:
static bool EncryptXOR(const std::vector<uint8_t>& plaintext,
std::vector<uint8_t>& ciphertext);
static bool DecryptXOR(const std::vector<uint8_t>& ciphertext,
std::vector<uint8_t>& plaintext);
static std::string EncryptFilename(const std::string& original);
static std::string DecryptFilename(const std::string& encryptedName);
};
bool EncryptAssetFile(const std::filesystem::path& inputPath,
const std::filesystem::path& outputDir);
bool DecryptAssetFile(const std::filesystem::path& encryptedPath,
std::vector<uint8_t>& outData);
bool EncryptAllInDirectory(const std::filesystem::path& inputDir,
const std::filesystem::path& outputDir);
bool DecryptAllToOriginal(const std::filesystem::path& encryptedDir,
const std::filesystem::path& outputDir);
}
主な特徴
- 軽量XOR暗号化: 低負荷・高速な暗号化処理を実現
- ファイル名まで暗号化: 元のファイル構成を推測されにくい安全設計
- 再帰ディレクトリ対応: フォルダ全体を一括で暗号化/復号化可能
- 静的ライブラリ構成: 配布時に外部アクセスを防止
暗号処理の仕組み
XOR演算による単純な暗号化を採用し、バイナリ全体とファイル名の両方を保護します。
XOR_KEY を使用して全バイトを排他的論理和し、元データを難読化します。
// --- XORによる暗号・復号処理 ---
for (size_t i = 0; i < plaintext.size(); ++i)
{
ciphertext[i] = plaintext[i] ^ XOR_KEY;
}
ファイル名も同様に1文字ずつXOR変換され、16進数表現へエンコードされます。 このため、アセットパス構造をそのまま読み取ることができません。
ディレクトリ単位の暗号化処理
// --- Assetsフォルダ全体を暗号化 ---
FlAssetProtector::EncryptAllInDirectory(
"Assets/",
"ProtectedAssets/"
);
// --- 復号化 ---
FlAssetProtector::DecryptAllToOriginal(
"ProtectedAssets/",
"DecryptedAssets/"
);
ファイル名暗号化の流れ
OriginalName : "texture_diffuse.png"
▼ XOR + HEX
EncryptedName : "A1B2C3D4E5F6..."
▼ 復号時
DecryptedName : "texture_diffuse.png"
ストリーム経由での復号読み込み
暗号化されたファイルは、DecryptedInputStream を介して直接読み取ることも可能です。
内部で復号を行い、通常の std::istream として扱えます。
// --- 例: 復号ストリームの使用 ---
FlAssetProtector::DecryptedInputStream stream("ProtectedAssets/logo.enc");
if (stream.IsValid())
{
std::string contents((std::istreambuf_iterator<char>(stream)),
std::istreambuf_iterator<char>());
}
技術的ポイント
- CryptoManager: ファイル内容とファイル名の暗号化ロジックを集約
- ディレクトリ操作対応:
std::filesystemにより再帰的に処理 - 静的リンク前提: 外部DLL依存なし、デプロイ時に安全な組み込みが可能
FlAssetProtector は、 開発資産の セキュリティレイヤー を担うモジュールです。 アセットの無断流用やリバースエンジニアリングに対し、 軽量ながら確実な防御策を提供します。
DebugLogger – 外部ログ出力クラス
DebugLogger は、実行中のエンジンやエディタの状態を 外部ファイルへ出力するための デバッグログ管理クラス です。 各種エラー、アサート、または開発時の挙動確認を目的として設計されています。
概要
このクラスは指定したファイルに対してテキスト出力を行い、
ファイル名・行番号・メッセージを含む詳細なデバッグ情報を記録します。
デフォルト出力先は Assets/Data/Log/DebugLog.log です。
- アプリケーション全体の動作履歴を追跡可能
FlFilePathManagerにより相対パス変換を自動処理- マクロ
DEBUG_LOG()により、簡潔に呼び出し可能
コード抜粋
// ログ出力用クラス
class DebugLogger
{
public:
explicit DebugLogger(const std::string_view& filename =
"Assets/Data/Log/DebugLog.log")
{
m_logFile.open(filename, std::ios::out | std::ios::app);
m_upFPM = std::make_unique<FlFilePathManager>();
if (!m_logFile) _ASSERT_EXPR(false, L"ログファイルがありません");
}
void LogDebug(const std::string& message, const char* file, int line)
{
if (m_logFile.is_open())
{
auto refl = m_upFPM->GetRelative(file).generic_string();
m_logFile << GetCurrentDateTime() << std::endl
<< "[File: " << refl << "] "
<< "[Line: " << line << "] "
<< message << std::endl;
}
}
};
// 呼び出しマクロ
#define DEBUG_LOG(logger, message) logger->LogDebug(message, __FILE__, __LINE__)
利用例
auto logger = std::make_shared<DebugLogger>();
// ファイル書き込みログ
DEBUG_LOG(logger, "Initialize Renderer Success");
// 出力内容例:
// 2025-10-06 17:05:12.123456789
// [File: Source/Graphics/Renderer.cpp] [Line: 85] Initialize Renderer Success
特徴
- 高精度な時刻出力(ナノ秒単位)
- 自動改行+日時付きログ形式
- 開発版・リリース版での切り替えが容易
- 全ファイル共通のデバッグログ基盤として統一使用可能
Formula – 便利関数群
Formula 名前空間は、ゲームロジックやシミュレーションで頻出する 数学的・確率的処理を簡潔に記述するためのユーティリティ集です。 乱数生成、確率抽選、三角関数カーブ、距離計算などを統一的に提供します。
主な機能
- Rand — 任意型(整数・浮動小数点)対応の乱数生成
- Lottery — 重み付き抽選(確率マップ / 配列両対応)
- Sin / Cos / Tan Curve — 角度入力の周期曲線生成
- GetDistance — Vector2 / Vector3 の距離演算
コード抜粋
namespace Formula
{
// ===== 基本乱数 =====
template<typename T>
decltype(auto) Rand(const T min, const T max) noexcept
{
std::random_device rd;
std::mt19937 mt{ rd() };
if constexpr (std::is_integral_v<T>)
return std::uniform_int_distribution<T>{ min, max }(mt);
else
return std::uniform_real_distribution<T>{ min, max }(mt);
}
// ===== 重み付き抽選 =====
const std::string Lottery(const std::unordered_map<std::string, double>& items) noexcept
{
std::vector<std::pair<std::string, double>> cdf;
double cumulative = 0.0;
for (auto& item : items)
{
cumulative += item.second;
cdf.emplace_back(item.first, cumulative);
}
auto r = Rand(0.0, cumulative);
auto it = std::lower_bound(cdf.begin(), cdf.end(), r,
[](const auto& e, double val){ return e.second < val; });
return it->first;
}
// ===== 三角カーブ =====
inline auto SinCurve(float deg, double amp = 1.0, double freq = 1.0, double phase = 0.0) noexcept
{
const auto rad = DirectX::XMConvertToRadians(deg);
return amp * std::sin(freq * rad + phase);
}
// ===== 距離計算 =====
inline auto GetDistance(const Math::Vector3& a, const Math::Vector3& b) noexcept
{
return std::sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));
}
}
利用例
// 整数乱数
int n = Formula::Rand(0, 10);
// 浮動小数点乱数
float t = Formula::Rand(0.0f, 1.0f);
// 抽選(レアドロップ判定など)
std::unordered_map<std::string, double> table = {
{ "Common", 70.0 },
{ "Rare", 25.0 },
{ "Epic", 5.0 }
};
auto result = Formula::Lottery(table);
// サイン波によるゆらぎ
float offset = Formula::SinCurve(time * 60.0f, 5.0, 1.0);
// 座標間の距離
float dist = Formula::GetDistance(playerPos, targetPos);
特徴
- テンプレートで整数・浮動小数点を自動判別
- DirectX数値単位に合わせた角度変換をサポート
- ラムダを活用した柔軟な除外乱数生成