管理人殿
いつも質問に答えていただき、ありがとうございます。
ゲーム制作をしていたら、
DXライブラリがうまく動かないようにみえる事象に遭遇したため、
相談させてください。
DXライブラリの3D関係関数を使って、
ゲームを作らせていただいております。
事象内容についてですが、
アニメーション再生を管理するための構造体を定義して、
モーションブレンドなども考慮して、
現在再生中のアニメーションをこの構造体のvector配列として
保持させようとしました。
この構造体のコンストラクタの中で、
MV1AttachAnim を実行してアニメーションをアタッチする実装にしたのですが、
vector配列でinsertを使って構造体を追加すると、
コンストラクタ内で MV1AttachAnim がうまく動作しません。
(アニメーションアタッチ番号が全て 0 になってしまいます)
コンストラクタ内で他のメンバ変数の初期化は
正しく行われておりました。
insert経由で、コンストラクタ内で MV1AttachAnim が実行されると
上手く動かないということがあるのでしょうか?
なお構造体を new で生成した場合は、
MV1AttachAnim は正常に機能することを確認しました。
回避策はあるので困っているわけではないのですが、
なぜうまく動作しないのかが気になるので、
お手数ですがご解析いただくことは可能でしょうか。
当方の環境は、
環境はVS2017、DXライブラリバージョンはVer3.18a(Log.txtから)です。
以下に問題が発生したソースを記載します。
-------------------------------------------------------------------------------
#include "DxLib.h"
// #### アニメーション再生管理構造体
struct AnimPlayBackInfo
{
// モーションのアタッチインデックス( MV1AttachAnim のリターン値 )
int m_AttachIndex;
// アニメーション再生情報
float m_CurPlayTime; // 現在の再生時間
int m_iModelHandle; // モデルハンドル
int m_iAttachedMotion; // 適用中のモーション( 初音ミクxxx.vmd ← xxxの番号 )
AnimPlayBackInfo(int ModelHandle, int AttachedMotion); // コンストラクタ
~AnimPlayBackInfo(); // デストラクタ
void ReAttach(); // MV1AttachAnim を行うだけ。
};
// コンストラクタ
AnimPlayBackInfo::AnimPlayBackInfo(int ModelHandle, int AttachedMotion) :
m_iModelHandle(ModelHandle),
m_iAttachedMotion(AttachedMotion),
m_CurPlayTime(0.0)
{
m_AttachIndex = MV1AttachAnim(ModelHandle, AttachedMotion, -1, FALSE);
}
// デストラクタ
AnimPlayBackInfo::~AnimPlayBackInfo()
{
MV1DetachAnim(m_iModelHandle, m_AttachIndex); // 古いアニメーションのデタッチ(デタッチしないとAnimationが混じって変なことになる)
}
// MV1AttachAnim を行うだけ。
void AnimPlayBackInfo::ReAttach()
{
m_AttachIndex = MV1AttachAnim(m_iModelHandle, m_iAttachedMotion, -1, FALSE);
}
// #############################################################################
// main
// #############################################################################
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
// ################## DXライブラリ関係の初期設定 #######################
if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //初期化処理
SetDrawScreen( DX_SCREEN_BACK ); // 裏画面に設定
SetCameraNearFar( 1.0f, 1500.0f ) ; // カメラの 手前クリップ距離と 奥クリップ距離を設定
// ################## 変数の定義・初期化 #######################
// タイマを生成 ★自作クラス★
PrecisionTimer timer;
// 仮想コントローラーのインスタンス化 ★自作クラス★
VirtualController VController;
VController.CheckAndSetGamePadMode(); // ゲームパッドが使えるのなら有効にする
// AnimationManagerのインスタンス化
vector<AnimPlayBackInfo> AnimPlayInfoArray;
int curAnimID = 3;
int ModelHandle = MV1LoadModel( "..\\mmd_model\\初音ミク.pmd" );
// 新しいモーションを生成
AnimPlayInfoArray.insert(AnimPlayInfoArray.begin(), AnimPlayBackInfo(ModelHandle, curAnimID));
// ################## メインループの開始 #######################
timer.Start(); // タイマ活性化
while(!ScreenFlip() && !ProcessMessage() && !ClearDrawScreen()){
// タイムスライスを取得
double timeelaps = timer.TimeElapsed();
// ################## コントローラーを更新 #######################
VController.Update(timeelaps);
// ################## キー入力受付 #######################
if( VController.ButA.isNowPush() )
{
// 次のAnimationを表示
curAnimID++;
if (!(curAnimID < 15)) curAnimID = 3;
AnimPlayInfoArray.clear();
AnimPlayInfoArray.insert(AnimPlayInfoArray.begin(), AnimPlayBackInfo(ModelHandle, curAnimID));
// AnimPlayInfoArray[0].ReAttach(); // ← ★これを有効にすると、アニメーションが正常に再生される!
}
// ################## アニメーションの再生 #######################
AnimPlayInfoArray[0].m_CurPlayTime += 20.0 * timeelaps; // curplaytime : 次の再生時刻
MV1SetAttachAnimTime(AnimPlayInfoArray[0].m_iModelHandle, AnimPlayInfoArray[0].m_AttachIndex, AnimPlayInfoArray[0].m_CurPlayTime ); // 再生時間をセットする
MV1DrawModel( ModelHandle ); // モデルの描画
// ################## カメラ設定 #######################
// ★ CameraWorkManager は自作クラス ★
CameraWorkManager::Instance()->Update( timeelaps );
CameraWorkManager::Instance()->setCamera();
}
DxLib_End() ; // DXライブラリ使用の終了処理
return 0 ; // ソフトの終了
}
-------------------------------------------------------------------------------