現在、DXライブラリとC++を用いて弾幕STGを制作しています。
タイトルにある通り、非同期読み込みについて質問です。
今回、ゲーム開始時とステージ開始時に非同期読み込みを行っていて、ゲーム開始時の非同期読み込みで無限ロードが起こってしまいます。
まず、アセットの管理方法ですが、管理専門のクラスを用いています。そのクラスのメンバ変数にstd::mapで定義し以下のメンバ関数で
読み込んでいます。
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
※COLOR_TYPE = 5
※EFFECT_MAX = 30
(ヘッダー)
/** フォント情報 **/
std::map<FontKey, const Font> FontInfo =
{
//マメロン サイズ32 - 90
{FK_Mamelon_S32, {"../Asset/Font/Mamelon_S32.dft", 32}},
{FK_Mamelon_S60, {"../Asset/Font/Mamelon_S60.dft", 60}},
{FK_Mamelon_S90, {"../Asset/Font/Mamelon_S90.dft", 90}},
};
/** フォントハンドル **/
int fontBuffer[FK_FontNum];
std::map<FontKey, int> FontHandle =
{
//マメロン サイズ32 - 90
{FK_Mamelon_S32, fontBuffer[0]},
{FK_Mamelon_S60, fontBuffer[1]},
{FK_Mamelon_S90, fontBuffer[2]},
};
/** グラフィック情報 **/
std::map<GraphicKey, const Graphic> GraphicInfo = {
//プレイヤー
{ GK_Player , { "../Asset/Graphics/Player/Player.png", 5, 1, 5, 70, 70 }},
//方向弾を撃つ敵
{ GK_DirectionalShoter , { "../Asset/Graphics/Enemy/EnemyTriangle.png", 5, 1, 5, 63, 70 }},
//渦巻弾を撃つ敵
{ GK_SpiralShoter , { "../Asset/Graphics/Enemy/EnemyBox.png", 5, 1, 5, 70, 70 }},
//特殊弾を撃つ敵
{ GK_SpecialShoter , { "../Asset/Graphics/Enemy/EnemyHexagon.png", 5, 1, 5, 70, 70 }},
//破壊エフェクト
{ GK_BreakEffect , { "../Asset/Graphics/Effect/BreakEffect.png", 30 * 5, 5 * 5, 6, 400, 400 }},
//カラーチェンジエフェクト
{ GK_ColorChangeEffect, { "../Asset/Graphics/Effect/ColorChangeEffect.png", 30 * 5, 5 * 5, 6, 400, 400 }},
//捕食エフェクト
{ GK_PredationEffect, { "../Asset/Graphics/Effect/PredationEffect.png", 30 * 5, 5 * 5, 6, 400, 400 }},
//リスポーンエフェクト
{ GK_RespawnEffect, { "../Asset/Graphics/Effect/RespawnEffect.png", 30 * 5, 5 * 5, 6, 400, 400 }},
//ブロックエフェクト
{ GK_BlockEffect, { "../Asset/Graphics/Effect/BlockEffect.png", 30 * 5, 5 * 5, 6, 400, 400 }},
//レベルアップエフェクト
{ GK_LevelUpEffect, { "../Asset/Graphics/Effect/LevelUpEffect.png", 30 * 5, 5 * 5, 6, 400, 400 }},
//ボス登場エフェクト
{ GK_BossAppearanceEffect, { "../Asset/Graphics/Effect/BossAppearance.png", 30, 5, 6, 800, 800 }},
//プレイヤーの通常弾
{ GK_PlayerNormalBullet, { "../Asset/Graphics/Bullet/PlayerNormal.png", 5, 1, 5, 62, 40 }},
//プレイヤーの円形弾
{ GK_PlayerCircleBullet, { "../Asset/Graphics/Bullet/PlayerCircle.png", 5, 1, 5, 40, 40 }},
//敵の方向弾
{ GK_EnemyDirectionalBullet, { "../Asset/Graphics/Bullet/EnemyDirectional.png", 5, 1, 5, 62, 40 }},
//敵の渦巻弾
{ GK_EnemySpiralBullet, { "../Asset/Graphics/Bullet/EnemySpiral.png", 5, 1, 5, 40, 40 }},
//敵の追尾弾
{ GK_EnemyAimingBullet, { "../Asset/Graphics/Bullet/EnemyAiming.png", 5, 1, 5, 80, 40 }},
};
/** グラフィックハンドル **/
std::map<GraphicKey, int*> GraphicHandle = {
//プレイヤー
{ GK_Player, new int[COLOR_TYPE] },
//方向弾を撃つ敵
{ GK_DirectionalShoter, new int[COLOR_TYPE]},
//渦巻弾を撃つ敵
{ GK_SpiralShoter, new int[COLOR_TYPE]},
//特殊弾を撃つ敵
{ GK_SpecialShoter, new int[COLOR_TYPE]},
//破壊エフェクト
{ GK_BreakEffect, new int[EFFECT_MAX * COLOR_TYPE]},
//カラーチェンジエフェクト
{ GK_ColorChangeEffect, new int[EFFECT_MAX * COLOR_TYPE]},
//捕食エフェクト
{ GK_PredationEffect, new int[EFFECT_MAX * COLOR_TYPE]},
//リスポーンエフェクト
{ GK_RespawnEffect, new int[EFFECT_MAX * COLOR_TYPE]},
//ブロックエフェクト
{ GK_BlockEffect, new int[EFFECT_MAX * COLOR_TYPE]},
//レベルアップエフェクト
{ GK_LevelUpEffect, new int[EFFECT_MAX * COLOR_TYPE]},
//ボス登場エフェクト
{ GK_BossAppearanceEffect, new int[EFFECT_MAX]},
//プレイヤーの通常弾
{ GK_PlayerNormalBullet, new int[COLOR_TYPE]},
//プレイヤーの円形弾
{ GK_PlayerCircleBullet, new int[COLOR_TYPE]},
//敵の方向弾
{ GK_EnemyDirectionalBullet, new int[COLOR_TYPE]},
//敵の渦巻弾
{ GK_EnemySpiralBullet, new int[COLOR_TYPE]},
//敵の追尾弾
{ GK_EnemyAimingBullet, new int[COLOR_TYPE]},
};
/** オーディオ情報 **/
std::map<AudioKey, const Audio> AudioInfo =
{
//決定SE
{AK_Decison, {"../Asset/Audio/SE/Decision.mp3", ST_SE, 2}},
//カーソル移動SE
{AK_Cursor, {"../Asset/Audio/SE/Cursor.mp3", ST_SE, 2}},
//上書きSE
{AK_Overwrite, {"../Asset/Audio/SE/Overwrite.mp3", ST_SE, 2}},
//プレイヤーの射撃SE
{AK_PlayerShot, {"../Asset/Audio/SE/PlayerShot.mp3", ST_SE, 100}},
//敵の射撃SE 1
{AK_EnemyShot1, {"../Asset/Audio/SE/Shot1.mp3", ST_SE, 1000}},
//敵の射撃SE 2
{AK_EnemyShot2, {"../Asset/Audio/SE/Shot2.mp3", ST_SE, 1500}},
//敵の射撃SE 3
{AK_EnemyShot3, {"../Asset/Audio/SE/Shot3.mp3", ST_SE, 1000}},
//ボス登場SE
{AK_BossAppearance, {"../Asset/Audio/SE/BossAppearance.mp3", ST_SE, 1}},
//ヒットSE
{AK_Hit, {"../Asset/Audio/SE/Hit.mp3", ST_SE, 1000}},
//レベルアップSE
{AK_LevelUp, {"../Asset/Audio/SE/LevelUp.mp3", ST_SE, 1}},
//破壊SE
{AK_Break, {"../Asset/Audio/SE/Break.mp3", ST_SE, 50}},
//カラーチェンジSE
{AK_ColorChange, {"../Asset/Audio/SE/ColorChange.mp3", ST_SE, 3}},
//捕食SE
{AK_Predation, {"../Asset/Audio/SE/Predation.mp3", ST_SE, 10}},
//ブロックSE
{AK_Block, {"../Asset/Audio/SE/Block.mp3", ST_SE, 1000}},
//タイトルBGM
{AK_Title, {"../Asset/Audio/BGM/ギリシャの夜明け.mp3", ST_BGM, 1}},
//設定BGM
{AK_Setting, {"../Asset/Audio/BGM/忘れられた神殿.mp3", ST_BGM, 1}},
//クレジットBGM
{AK_Credit, {"../Asset/Audio/BGM/カナリアスキップ.mp3", ST_BGM, 1}},
};
/** オーディオハンドル **/
int audioBuffer[AK_AudioNum];
std::map<AudioKey, int> AudioHandle =
{
//決定SE
{AK_Decison, audioBuffer[0]},
//カーソル移動SE
{AK_Cursor, audioBuffer[1]},
//上書きSE
{AK_Overwrite, audioBuffer[2]},
//プレイヤーの射撃SE
{AK_PlayerShot, audioBuffer[3]},
//敵の射撃SE 1
{AK_EnemyShot1, audioBuffer[4]},
//敵の射撃SE 2
{AK_EnemyShot2, audioBuffer[5]},
//敵の射撃SE 3
{AK_EnemyShot3, audioBuffer[6]},
//ボス登場SE
{AK_BossAppearance, audioBuffer[7]},
//ヒットSE
{AK_Hit, audioBuffer[8]},
//レベルアップSE
{AK_LevelUp, audioBuffer[9]},
//破壊SE
{AK_Break, audioBuffer[10]},
//カラーチェンジSE
{AK_ColorChange, audioBuffer[11]},
//捕食SE
{AK_Predation, audioBuffer[12]},
//ブロックSE
{AK_Block, audioBuffer[13]},
//タイトルBGM
{AK_Title, audioBuffer[14]},
//設定BGM
{AK_Setting, audioBuffer[15]},
//クレジットBGM
{AK_Credit, audioBuffer[16]},
};
(実装ファイル)
//全てのグラフィックアセットを読み込む
void CAssetManager::LoadAllGraphicAssets()
{
//グラフィックハンドルのロード
for (auto itr = GraphicHandle.begin(); itr != GraphicHandle.end(); itr++) {
//読み込むアセットがなければ異常終了
if (LoadDivGraphic(GraphicInfo[itr->first], itr->second) == -1) {
//エラーメッセージを作成
std::string file_path = GraphicInfo[itr->first].FileName;
std::string err_msg = "AssetManager : ファイルパス [" + file_path + "] の画像が読み込めませんでした。";
//エラーメッセージをポップアップ
Process.PutErrWindow(err_msg.c_str());
}
}
}
//全てのオーディオアセットを読み込む
void CAssetManager::LoadAllAudioAssets()
{
//オーディオハンドルのロード
for (auto itr = AudioHandle.begin(); itr != AudioHandle.end(); itr++) {
itr->second = LoadSoundMem(AudioInfo[itr->first].FileName, AudioInfo[itr->first].Buffer);
//読み込むアセットがなければ異常終了
if (itr->second == -1) {
//エラーメッセージを作成
std::string file_path = AudioInfo[itr->first].FileName;
std::string err_msg = "AssetManager : ファイルパス [" + file_path + "] の音声が読み込めませんでした。";
//エラーメッセージをポップアップ
Process.PutErrWindow(err_msg.c_str());
}
}
}
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
上記の関数をSetUseASyncLoadFlagで非同期読み込みをオンにしてから実行し、同じくメンバ関数の非同期読み込みが完了したかを調べる以下の
関数でロードの終了を確認しています。
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
(実装ファイル)
//全てのアセットの非同期読み込みが完了しているか
bool CAssetManager::AreAllAssetsLoaded(int& loadingNum)
{
int num = 0;
bool isLoaded = true;
//グラフィックハンドルの確認
for (auto itr = GraphicHandle.begin(); itr != GraphicHandle.end(); itr++) {
//いずれかの読み込みが終わってなければfalseを返す
bool isAllLoaded = true;
for (int i = 0; i < GraphicInfo[itr->first].Count; i++) {
if (CheckHandleASyncLoad(itr->second[i])) isAllLoaded = false;
}
if (!isAllLoaded) {
isLoaded = false;
num++;
}
}
//オーディオハンドルの確認
for (auto itr = AudioHandle.begin(); itr != AudioHandle.end(); itr++) {
//読み込みが終わってなければfalseを返す
if (CheckHandleASyncLoad(itr->second)) {
isLoaded = false;
num++;
}
}
//ロード中のアセットの数を返す
loadingNum = num;
//全てのアセットの非同期読み込みが終了していたらtrueを返す
return isLoaded;
}
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
上記の関数でブレークポイントを置いたりして確認したところ、必ずグラフィックハンドルのエフェクトのいずれかが読み込まれず無限ロードに
なっていました。ですので、エフェクトとそれ以外のグラフィックで分割する数が違うのでそれが原因かとも思いましたが、非同期読み込みでない
場合には正常に読み込むため原因がわからず質問させていただきました。
ご教授の程よろしくお願いいたします。