ページ 11

MMDモーション再生について

Posted: 2013年9月23日(月) 19:04
by Isanan
初めまして。

http://dixq.net/g/3d_05.html

↑を参考に特定のキーを押した瞬間にキックのモーションを再生するプログラムを作ろうとしたのですが

押した瞬間にアタッチしたモーションの一部を描画するものになってしまいます。

自分では再生時間をどうにか変えなければ改善しないと考えているのですが「どうにか」がわからなくて・・・

どうすればいいでしょうか、教えてください。

コード:

#include "DxLib.h"

int Key[256]; // キーが押されているフレーム数を格納する

// キーの入力状態を更新する
int gpUpdateKey(){
        char tmpKey[256]; // 現在のキーの入力状態を格納する
        GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
        for( int i=0; i<256; i++ ){ 
                if( tmpKey[i] != 0 ){ // i番のキーコードに対応するキーが押されていたら
                        Key[i]++;     // 加算
                } else {              // 押されていなければ
                        Key[i] = 0;   // 0にする
                }
        }
        return 0;
}

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
    ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定

	int ModelHandle, AttachIndex ;
    float TotalTime, PlayTime ;

    // 3Dモデルの読み込み
    ModelHandle = MV1LoadModel( "dat/Lat式ミク/Lat式ミクVer2.3_Normal.pmd" ) ;

    //奥行0.1~1000までをカメラの描画範囲とする
    SetCameraNearFar( 0.1f, 1000.0f ) ;

    //(0,10,-20)の視点から(0,10,0)のターゲットを見る角度にカメラを設置
    SetCameraPositionAndTarget_UpVecY( VGet( 0, 20, -20 ), VGet( 0.0f, 10.0f, 0.0f ) ) ;

	 // 3Dモデルの1番目のアニメーションをアタッチする
    AttachIndex = MV1AttachAnim( ModelHandle, 0, -1, FALSE ) ;

    // アタッチしたアニメーションの総再生時間を取得する
    TotalTime = MV1GetAttachAnimTotalTime( ModelHandle, AttachIndex ) ;

    // 再生時間の初期化
    PlayTime = 0.0f ;

	while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && gpUpdateKey()==0 ){

		if( Key[KEY_INPUT_SPACE] == 1 ){ // スペースキーが押された瞬間なら

        // 再生時間を進める
        PlayTime += 0.2f ;

		// 再生時間をセットする
        MV1SetAttachAnimTime( ModelHandle, AttachIndex, PlayTime ) ;

        }

        // 3Dモデルの描画
        MV1DrawModel( ModelHandle ) ;
    }

        DxLib_End(); // DXライブラリ終了処理
        return 0;
} 

Re: MMDモーション再生について

Posted: 2013年9月23日(月) 19:31
by みけCAT
1.スペースキーが押されたら再生時間を初期化して「再生中」のフラグを立てる
2.「再生中」のフラグが立っていたら
 2-1.再生時間を進め、再生時間をセットする
 2-2.再生時間があらかじめ決めた時間に達したら、「再生中」のフラグを折る

というように処理するといいと思います。

Re: MMDモーション再生について

Posted: 2013年9月23日(月) 19:52
by Isanan
ご回答ありがとうございます。

不安なところもありますが少し自力で頑張ってみます。

Re: MMDモーション再生について

Posted: 2013年9月23日(月) 20:57
by Isanan
本当に申し訳ないのですがフラグの立て方と折り方の講座サイトを教えてください。

少し自分で検索してみてどうもint型とbool型があるのはわかったので(もしかしたらこれも間違っているかも知れませんが)

あとサイトにサンプルコードがのっていると非常に助かります。

よろしくお願いします。

コード:

#include "DxLib.h"

int Key[256]; // キーが押されているフレーム数を格納する

// キーの入力状態を更新する
int gpUpdateKey(){
        char tmpKey[256]; // 現在のキーの入力状態を格納する
        GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
        for( int i=0; i<256; i++ ){ 
                if( tmpKey[i] != 0 ){ // i番のキーコードに対応するキーが押されていたら
                        Key[i]++;     // 加算
                } else {              // 押されていなければ
                        Key[i] = 0;   // 0にする
                }
        }
        return 0;
}

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
    ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定

	int ModelHandle, AttachIndex ;
    float TotalTime, PlayTime ;

    // 3Dモデルの読み込み
    ModelHandle = MV1LoadModel( "dat/ソリッド・スネーク ver1.2/ソリッド・スネーク.pmd" ) ;

    //奥行0.1~1000までをカメラの描画範囲とする
    SetCameraNearFar( 0.1f, 1000.0f ) ;

    //(0,10,-20)の視点から(0,10,0)のターゲットを見る角度にカメラを設置
    SetCameraPositionAndTarget_UpVecY( VGet( 0, 20, -20 ), VGet( 0.0f, 10.0f, 0.0f ) ) ;

	 // 3Dモデルの1番目のアニメーションをアタッチする
    AttachIndex = MV1AttachAnim( ModelHandle, 0, -1, FALSE ) ;

    // アタッチしたアニメーションの総再生時間を取得する
    TotalTime = MV1GetAttachAnimTotalTime( ModelHandle, AttachIndex ) ;

    // 再生時間の初期化
    PlayTime = 0.0f ;

	while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && gpUpdateKey()==0 ){

		if( Key[KEY_INPUT_SPACE] == 1 ){ // スペースキーが押された瞬間なら
		    PlayTime = 0.0f ;		//再生時間を初期化
									//「再生中」のフラグを立てる

				if(  ){				//「再生中」のフラグが立っていたら
					PlayTime += 0.2f ;// 再生時間を進める
					MV1SetAttachAnimTime( ModelHandle, AttachIndex, PlayTime ) ;// 再生時間をセットする
				
				else( PlayTime = 150.0f ){//再生時間があらかじめ決めた時間に達したら
					                      //「再生中」のフラグを折る
        }

       

        }

        // 3Dモデルの描画
        MV1DrawModel( ModelHandle ) ;
    }

        DxLib_End(); // DXライブラリ終了処理
        return 0;
} 

Re: MMDモーション再生について

Posted: 2013年9月23日(月) 21:14
by みけCAT
Isanan さんが書きました:本当に申し訳ないのですがフラグの立て方と折り方の講座サイトを教えてください。
[search=google]フラグ 立て方[/search]
[search=google]フラグ 折り方[/search]

プログラミングでのフラグは、状態を示す変数を使用します。
サンプルコード

コード:

bool hogeFlag=false;

hogeFlag=true; // フラグを立てる
hogeFlag=false; //フラグを折る

if(hogeFlag) {
    //フラグが立っている時の処理
}

Re: MMDモーション再生について

Posted: 2013年10月11日(金) 00:05
by softya(ソフト屋)
間違えて、あちらに投稿されたので転載しておきます。
「MMDモーション再生について2 • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/viewtopic.php?f=3&t=13996
2は閉鎖してあります。
Isanan さんが書きました:
1.スペースキーが押されたら再生時間を初期化して「再生中」のフラグを立てる
2.「再生中」のフラグが立っていたら
 2-1.再生時間を進め、再生時間をセットする
 2-2.再生時間があらかじめ決めた時間に達したら、「再生中」のフラグを折る
アドバイスを元に少し間が空きましたが自分なりにフラグ処理を入れてみました

http://dixq.net/g/25.html

やはりキックのモーション再生がうまくいきません

実行結果が150.0fまで0.4fの早さで再生のはずがモーション中の0.4fの場面を表示になってしまいます

bool型も試しましたが結果は変わりませんでした

初心者
環境:[OS]windows7 [コンパイラ名]VC++ 2008EE
DXライブラリ

コード:

#include "DxLib.h"
 
typedef struct{
        int playing_flag;
}ch_t;

int Key[256]; // キーが押されているフレーム数を格納する
 
// キーの入力状態を更新する
int gpUpdateKey(){
        char tmpKey[256]; // 現在のキーの入力状態を格納する
        GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
        for( int i=0; i<256; i++ ){ 
                if( tmpKey[i] != 0 ){ // i番のキーコードに対応するキーが押されていたら
                        Key[i]++;     // 加算
                } else {              // 押されていなければ
                        Key[i] = 0;   // 0にする
                }
        }
        return 0;
}
 
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
    ch_t ch;
	
	ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
 
    int ModelHandle, AttachIndex ;
    float TotalTime, PlayTime ;
	ch.playing_flag=0 ;

    // 3Dモデルの読み込み
    ModelHandle = MV1LoadModel( "Lat式ミク.pmd" ) ;
 
    //奥行0.1~1000までをカメラの描画範囲とする
    SetCameraNearFar( 0.1f, 1000.0f ) ;
 
    //(0,10,-20)の視点から(0,10,0)のターゲットを見る角度にカメラを設置
    SetCameraPositionAndTarget_UpVecY( VGet( 0, 20, -20 ), VGet( 0.0f, 10.0f, 0.0f ) ) ;
 
     // 3Dモデルの1番目のアニメーションをアタッチする
    AttachIndex = MV1AttachAnim( ModelHandle, 0, -1, FALSE ) ;
 
    // アタッチしたアニメーションの総再生時間を取得する
    TotalTime = MV1GetAttachAnimTotalTime( ModelHandle, AttachIndex ) ;
 
    // 再生時間の初期化
    PlayTime = 0.0f ;
 
	while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && gpUpdateKey()==0 ){
        if( Key[KEY_INPUT_SPACE] == 1 ){ // スペースキーが押された瞬間なら
            PlayTime = 0.0f ;       //再生時間を初期化
              ch.playing_flag=0 ;	//「再生中」のフラグを立てる
 
                if( ch.playing_flag=1 ){             //「再生中」のフラグが立っていたら
                    PlayTime += 0.4f ;// 再生時間を進める
                    MV1SetAttachAnimTime( ModelHandle, AttachIndex, PlayTime ) ;// 再生時間をセットする
				}
                    if( PlayTime = 150.0f ){//再生時間があらかじめ決めた時間に達したら
					  ch.playing_flag=0 ;                   //「再生中」のフラグを折る
				}

        }
 
        // 3Dモデルの描画
        MV1DrawModel( ModelHandle ) ;
}
 
        DxLib_End(); // DXライブラリ終了処理
        return 0;
}

コード:

#include "DxLib.h"
 
int Key[256]; // キーが押されているフレーム数を格納する
 
// キーの入力状態を更新する
int gpUpdateKey(){
        char tmpKey[256]; // 現在のキーの入力状態を格納する
        GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
        for( int i=0; i<256; i++ ){ 
                if( tmpKey[i] != 0 ){ // i番のキーコードに対応するキーが押されていたら
                        Key[i]++;     // 加算
                } else {              // 押されていなければ
                        Key[i] = 0;   // 0にする
                }
        }
        return 0;
}
 
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
	
	ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
 
    int ModelHandle, AttachIndex ;
    float TotalTime, PlayTime ;
	bool playing_Flag=false ;

    // 3Dモデルの読み込み
    ModelHandle = MV1LoadModel( "dat/ソリッド・スネーク ver1.2/ソリッド・スネーク.pmd" ) ;
 
    //奥行0.1~1000までをカメラの描画範囲とする
    SetCameraNearFar( 0.1f, 1000.0f ) ;
 
    //(0,10,-20)の視点から(0,10,0)のターゲットを見る角度にカメラを設置
    SetCameraPositionAndTarget_UpVecY( VGet( 0, 20, -20 ), VGet( 0.0f, 10.0f, 0.0f ) ) ;
 
     // 3Dモデルの1番目のアニメーションをアタッチする
    AttachIndex = MV1AttachAnim( ModelHandle, 0, -1, FALSE ) ;
 
    // アタッチしたアニメーションの総再生時間を取得する
    TotalTime = MV1GetAttachAnimTotalTime( ModelHandle, AttachIndex ) ;
 
    // 再生時間の初期化
    PlayTime = 0.0f ;
 
	while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && gpUpdateKey()==0 ){
        if( Key[KEY_INPUT_SPACE] == 1 ){ // スペースキーが押された瞬間なら
            PlayTime = 0.0f ;            //再生時間を初期化
              playing_Flag=true ;	     //「再生中」のフラグを立てる
			  
                if( playing_Flag=true ){                                         //「再生中」のフラグが立っていたら
                    PlayTime += 0.4f ;                                           // 再生時間を進める
                    MV1SetAttachAnimTime( ModelHandle, AttachIndex, PlayTime ) ; // 再生時間をセットする
				}

                if( PlayTime = 150.0f ){    //再生時間があらかじめ決めた時間に達したら
					playing_Flag=false ;     //「再生中」のフラグを折る
				}

        }
 
        // 3Dモデルの描画
        MV1DrawModel( ModelHandle ) ;
}
 
        DxLib_End(); // DXライブラリ終了処理
        return 0;
}

Re: MMDモーション再生について

Posted: 2013年10月11日(金) 00:08
by softya(ソフト屋)
ソースを見ての思ったのですが、3D以前に「スペースキーが押されたら白丸が表示、もう一度押されたら白丸が消える。以下繰り返し。」と言う仕様のプログラムが作れないとこれは解決できません。

ヒント:if文は条件が成立無いと、その処理は行われない。

Re: MMDモーション再生について

Posted: 2013年10月11日(金) 23:21
by みけCAT
スペースキーが押されているかの判定と再生中かの判定は独立です。
また、if文の条件式で無意味に代入しないように気をつけましょう。

Re: MMDモーション再生について

Posted: 2013年10月13日(日) 17:40
by Isanan
みけCAT さんが書きました:スペースキーが押されているかの判定と再生中かの判定は独立です。
また、if文の条件式で無意味に代入しないように気をつけましょう。
softya(ソフト屋) さんが書きました:ソースを見ての思ったのですが、3D以前に「スペースキーが押されたら白丸が表示、もう一度押されたら白丸が消える。以下繰り返し。」と言う仕様のプログラムが作れないとこれは解決できません。

ヒント:if文は条件が成立無いと、その処理は行われない。
作りました

そして無意味に条件式に代入してはいけないのは意図した代入か==のタイプミスか判断しにくいからであっていますか?

コード:

#include "DxLib.h"

int Key[256]; // キーが押されているフレーム数を格納する
 
// キーの入力状態を更新する
int gpUpdateKey(){
        char tmpKey[256]; // 現在のキーの入力状態を格納する
        GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
        for( int i=0; i<256; i++ ){ 
                if( tmpKey[i] != 0 ){ // i番のキーコードに対応するキーが押されていたら
                        Key[i]++;     // 加算
                } else {              // 押されていなければ
                        Key[i] = 0;   // 0にする
                }
        }
        return 0;
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ){
    ChangeWindowMode(TRUE), DxLib_Init(); //ウィンドウモード変更と初期化

	int Circle ;

    if( DxLib_Init() == -1 )        // DXライブラリ初期化処理
    {
         return -1;        // エラーが起きたら直ちに終了
    }

    Circle = GetColor(   255 ,   255 , 255 ) ;    // 青色の値を取得

    while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && gpUpdateKey()==0 ){
		   if( Key[KEY_INPUT_SPACE] == 1 ){			     //スペースキーを押されたら瞬間
		   DrawCircle( 320 , 240 , 100 , Circle , TRUE ) ; // 円を描画
		   WaitKey() ;									   //キー入力待ち
		   }	

		   if(Key[KEY_INPUT_SPACE] == 1 ){              //再度スペースキーが押されたら
			   ClearDrawScreen();
		   }

	}

    DxLib_End() ;            // DXライブラリ使用の終了処理

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

Re: MMDモーション再生について

Posted: 2013年10月13日(日) 17:45
by softya(ソフト屋)
それだとフラグを使っていないので、フラグの話の意味が無くなってしまいます。
フラグを使って同じこと実現してみましょう。WaitKey() ; はこの場合は使用禁止です。
こういう処理作るのはWaitKey() ;が楽でしょうがフラグを覚えるのには害でしか無いです。
【補足】
こういうのはフラグと言うか状態遷移の考え方を身につける必要があります。ゲームには必須なのです。
フラグは状態が2つしか無い状態遷移です。
「状態遷移表による設計手法(1):状態遷移表設計手法の概要 (3/3) - MONOist(モノイスト)」 ←参考に。
http://monoist.atmarkit.co.jp/mn/articl ... 001_3.html

あとインデントを綺麗に揃える癖をつけたほうが良いでしょう。
「mixcpp/投稿前チェックリスト - PukiWiki」 チェック3をお読み下さい。
http://uchan.net/w/index.php?mixcpp%2F% ... 5%B9%A5%C8

Re: MMDモーション再生について

Posted: 2013年10月14日(月) 15:33
by みけCAT
Isanan さんが書きました:そして無意味に条件式に代入してはいけないのは意図した代入か==のタイプミスか判断しにくいからであっていますか?
今回の私の発言は、「どう考えても比較するべき場所で代入している、よくあるバグがある」という意味でした。
if文の条件式での無意味じゃない代入は、例えば

コード:

FILE* fp;
if(fp=fopen("hoge.txt","r")) {
    /* ファイルが開けたので処理する */
    fclose(fp);
}
などが考えられます。

Re: MMDモーション再生について

Posted: 2013年11月09日(土) 04:28
by Isanan
フラグを使ってもう一度作りました

実行結果は“円が描画した瞬間に消える”というものになりました

作りたいのは“スペースキーが押されたら白丸が表示、もう一度押されたら白丸が消える。以下繰り返し。”なので

自分でソースを見直したんですが

コード:

#include "DxLib.h"
 
int Key[256]; // キーが押されているフレーム数を格納する
 
// キーの入力状態を更新する
int gpUpdateKey()
{
    char tmpKey[256]; // 現在のキーの入力状態を格納する
    GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
    for( int i=0; i<256; i++ )
	{ 
        if( tmpKey[i] != 0 )// i番のキーコードに対応するキーが押されていたら
		{ 
            Key[i]++;     // 加算
            } 
		
		else  // 押されていなければ
		{             
            Key[i] = 0;   // 0にする
        }
	}
    return 0;
}
 
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
    ChangeWindowMode(TRUE), DxLib_Init(); //ウィンドウモード変更と初期化
 
    int Circle ;
	bool hogeFlag = false ;

    if( DxLib_Init() == -1 )        // DXライブラリ初期化処理
    {
        return -1;        // エラーが起きたら直ちに終了
    }
 
    Circle = GetColor(   255 ,   255 , 255 ) ;    //白色の値を取得
 
    while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && gpUpdateKey()==0 )
	{
        if( Key[KEY_INPUT_SPACE] == 1 )                  //スペースキーを押した瞬間
	    {
	        hogeFlag = true ;							 //フラグを立てる
	    }

        if( hogeFlag )									 //フラグが立っていたとき
	    {	 
		    DrawCircle( 320, 240, 100, Circle,TRUE ) ;   //円を描画
		
		    if( Key[KEY_INPUT_SPACE] == 1 )				 //スペースキーを押した瞬間
	        {
		        hogeFlag = false ;						 //フラグを折る
	        }
		}
    }
 
    DxLib_End() ;            // DXライブラリ使用の終了処理
 
    return 0 ;            // ソフトの終了
}
何度もすみませんが回答お願いします。

初心者
環境:[OS]windows7 [コンパイラ名]VC++ 2008EE
DXライブラリ

Re: MMDモーション再生について

Posted: 2013年11月09日(土) 09:40
by みけCAT
同じフレームで白丸の出現と消滅の判定を順番に行っているので、出現したフレームで消滅します。
例えば、このようにするといいと思います。

コード:

        if( hogeFlag )                                   //フラグが立っていたとき
        {    
            DrawCircle( 320, 240, 100, Circle,TRUE ) ;   //円を描画
        
            if( Key[KEY_INPUT_SPACE] == 1 )              //スペースキーを押した瞬間
            {
                hogeFlag = false ;                       //フラグを折る
            }
        } else {
            if( Key[KEY_INPUT_SPACE] == 1 )                  //スペースキーを押した瞬間
            {
                hogeFlag = true ;                            //フラグを立てる

                //1フレームの遅延が気になるなら下の1行を入れる。そうでなければ冗長なので入れない。
                DrawCircle( 320, 240, 100, Circle,TRUE ) ;   //円を描画
            }
        }

Re: MMDモーション再生について

Posted: 2013年11月09日(土) 09:41
by みけCAT
もしくは、こっちの方がいいかもしれません。

コード:

        if( Key[KEY_INPUT_SPACE] == 1 )              //スペースキーを押した瞬間
        {
            hogeFlag = !hogeFlag ;                       //フラグを反転
        }
        if( hogeFlag )                                   //フラグが立っていたとき
        {    
            DrawCircle( 320, 240, 100, Circle,TRUE ) ;   //円を描画
        }

Re: MMDモーション再生について

Posted: 2013年11月14日(木) 06:37
by Isanan
みけCAT さんが書きました:もしくは、こっちの方がいいかもしれません。

コード:

        if( Key[KEY_INPUT_SPACE] == 1 )              //スペースキーを押した瞬間
        {
            hogeFlag = !hogeFlag ;                       //フラグを反転
        }
        if( hogeFlag )                                   //フラグが立っていたとき
        {    
            DrawCircle( 320, 240, 100, Circle,TRUE ) ;   //円を描画
        }
みけCAT さんが書きました:同じフレームで白丸の出現と消滅の判定を順番に行っているので、出現したフレームで消滅します。
例えば、このようにするといいと思います。

コード:

        if( hogeFlag )                                   //フラグが立っていたとき
        {    
            DrawCircle( 320, 240, 100, Circle,TRUE ) ;   //円を描画
        
            if( Key[KEY_INPUT_SPACE] == 1 )              //スペースキーを押した瞬間
            {
                hogeFlag = false ;                       //フラグを折る
            }
        } else {
            if( Key[KEY_INPUT_SPACE] == 1 )                  //スペースキーを押した瞬間
            {
                hogeFlag = true ;                            //フラグを立てる

                //1フレームの遅延が気になるなら下の1行を入れる。そうでなければ冗長なので入れない。
                DrawCircle( 320, 240, 100, Circle,TRUE ) ;   //円を描画
            }
        }
ご回答ありがとうございます。

おかげで完成しました。

コード:

#include "DxLib.h"
 
int Key[256]; // キーが押されているフレーム数を格納する
 
// キーの入力状態を更新する
int gpUpdateKey()
{
    char tmpKey[256]; // 現在のキーの入力状態を格納する
    GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
    for( int i=0; i<256; i++ )
	{ 
        if( tmpKey[i] != 0 )// i番のキーコードに対応するキーが押されていたら
		{ 
            Key[i]++;     // 加算
            } 
		
		else  // 押されていなければ
		{             
            Key[i] = 0;   // 0にする
        }
	}
    return 0;
}
 
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
    ChangeWindowMode(TRUE), DxLib_Init(); //ウィンドウモード変更と初期化
 
    int Circle ;
	bool hogeFlag = false ;

    if( DxLib_Init() == -1 )        // DXライブラリ初期化処理
    {
        return -1;        // エラーが起きたら直ちに終了
    }
 
    Circle = GetColor(   255 ,   255 , 255 ) ;    //白色の値を取得
 
    while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && gpUpdateKey()==0 )
	{
        if( Key[KEY_INPUT_SPACE] == 1 )              //スペースキーを押した瞬間
        {
            hogeFlag = !hogeFlag ;                       //フラグを反転
        }
        if( hogeFlag )                                   //フラグが立っていたとき
        {    
            DrawCircle( 320, 240, 100, Circle,TRUE ) ;   //円を描画
        }
	}
    DxLib_End() ;            // DXライブラリ使用の終了処理
 
    return 0 ;            // ソフトの終了
}
これを使ってMMDのモーション再生について書いてみます。

Re: MMDモーション再生について

Posted: 2013年12月05日(木) 07:03
by Isanan
やっと出来ました。

ありがとうございます。

コード:

#include "DxLib.h"
 
int Key[256]; // キーが押されているフレーム数を格納する
 
// キーの入力状態を更新する
int gpUpdateKey()
{
        char tmpKey[256]; // 現在のキーの入力状態を格納する
        GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
        for( int i=0; i<256; i++ )
		{ 
                if( tmpKey[i] != 0 ) // i番のキーコードに対応するキーが押されていたら
				{
                        Key[i]++;     // 加算
                } 
				else 
				{              // 押されていなければ
                        Key[i] = 0;   // 0にする
                }
        }
        return 0;
}
 
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{    	
	ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
 
    int ModelHandle, AttachIndex ;
    float TotalTime, PlayTime ;
	bool playing_Flag= false ;

    // 3Dモデルの読み込み
    ModelHandle = MV1LoadModel( "dat/Lat式ミク/Lat式ミク.pmd" ) ;
 
    //奥行0.1~1000までをカメラの描画範囲とする
    SetCameraNearFar( 0.1f, 1000.0f ) ;
 
    //(0,10,-20)の視点から(0,10,0)のターゲットを見る角度にカメラを設置
    SetCameraPositionAndTarget_UpVecY( VGet( 0, 20, -20 ), VGet( 0.0f, 10.0f, 0.0f ) ) ;
 
     // 3Dモデルの1番目のアニメーションをアタッチする
    AttachIndex = MV1AttachAnim( ModelHandle, 0, -1, FALSE ) ;
 
    // アタッチしたアニメーションの総再生時間を取得する
    TotalTime = MV1GetAttachAnimTotalTime( ModelHandle, AttachIndex ) ;
	 
    // 再生時間の初期化
    PlayTime = 0.0f ;

	while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && gpUpdateKey()==0 )
	{
		if( Key[KEY_INPUT_SPACE] == 1 )                  //スペースキーを押した瞬間
        {
			PlayTime = 0.0f ;							  //再生時間の初期化
            playing_Flag = true ;                         //フラグを立てる
		}

        if( playing_Flag )                                   //フラグが立っていたとき
        {    
            PlayTime += 0.4f ;                                           // 再生時間を進める
		    MV1SetAttachAnimTime( ModelHandle, AttachIndex, PlayTime ) ; // 再生時間をセットする
            if( Key[KEY_INPUT_SPACE] == 1 )              //スペースキーを押した瞬間
            {
				playing_Flag = false ;                   //フラグを折る
            }
			}else{
			if( TotalTime = PlayTime )                  //再生時間が総再生時間に達したら
            {
				PlayTime = 0.0f ;
                playing_Flag = true ;                            //フラグを立てる

			}
        }

        // 3Dモデルの描画
        MV1DrawModel( ModelHandle ) ;
	}
 
        DxLib_End(); // DXライブラリ終了処理
        return 0;
}

Re: MMDモーション再生について

Posted: 2013年12月05日(木) 23:02
by みけCAT
どう考えてもたまたまそれっぽく動いているだけのコードだと思います。
まずはきちんとインデントをしましょう。

Re: MMDモーション再生について

Posted: 2013年12月07日(土) 15:46
by Isanan
みけCAT さんが書きました:どう考えてもたまたまそれっぽく動いているだけのコードだと思います。
まずはきちんとインデントをしましょう。
すいません。

このコードのどこが間違っているか教えてくれませんか。

コード:

#include "DxLib.h"
 
int Key[256]; // キーが押されているフレーム数を格納する
 
// キーの入力状態を更新する
int gpUpdateKey()
{
    char tmpKey[256]; // 現在のキーの入力状態を格納する
    GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
    for( int i=0; i<256; i++ )
	{ 
        if( tmpKey[i] != 0 ) // i番のキーコードに対応するキーが押されていたら
		{
            Key[i]++;     // 加算
        } 
		else 
		{              // 押されていなければ
            Key[i] = 0;   // 0にする
        }
    }
    return 0;
}
 
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{    	
	ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
 
    int ModelHandle, AttachIndex ;
    float TotalTime, PlayTime ;
	bool playing_Flag= false ;

    // 3Dモデルの読み込み
    ModelHandle = MV1LoadModel( "dat/Lat式ミク/Lat式ミク.pmd" ) ;
 
    //奥行0.1~1000までをカメラの描画範囲とする
    SetCameraNearFar( 0.1f, 1000.0f ) ;
 
    //(0,10,-20)の視点から(0,10,0)のターゲットを見る角度にカメラを設置
    SetCameraPositionAndTarget_UpVecY( VGet( 0, 20, -20 ), VGet( 0.0f, 10.0f, 0.0f ) ) ;
 
     // 3Dモデルの1番目のアニメーションをアタッチする
    AttachIndex = MV1AttachAnim( ModelHandle, 0, -1, FALSE ) ;
 
    // アタッチしたアニメーションの総再生時間を取得する
    TotalTime = MV1GetAttachAnimTotalTime( ModelHandle, AttachIndex ) ;
	 
    // 再生時間の初期化
    PlayTime = 0.0f ;

	while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && gpUpdateKey()==0 )
	{
	    if( Key[KEY_INPUT_SPACE] == 1 )                  //スペースキーを押した瞬間
        {
			PlayTime = 0.0f ;							  //再生時間の初期化
            playing_Flag = true ;                         //フラグを立てる
		}

        if( playing_Flag )                                   //フラグが立っていたとき
        {    
            PlayTime += 0.4f ;                                           // 再生時間を進める
		    MV1SetAttachAnimTime( ModelHandle, AttachIndex, PlayTime ) ; // 再生時間をセットする
            if( Key[KEY_INPUT_SPACE] == 1 )              //スペースキーを押した瞬間
            {
			    playing_Flag = false ;                   //フラグを折る
            }

			}else{

			if( TotalTime = PlayTime )                  //再生時間が総再生時間に達したら
            {
				PlayTime = 0.0f ;
                playing_Flag = true ;                            //フラグを立てる

			}
        }

        // 3Dモデルの描画
        MV1DrawModel( ModelHandle ) ;
	}
 
        DxLib_End(); // DXライブラリ終了処理
        return 0;
}

Re: MMDモーション再生について

Posted: 2013年12月07日(土) 16:11
by みけCAT
インデントを整えましょう。

コード:

#include "DxLib.h"

int Key[256]; // キーが押されているフレーム数を格納する

// キーの入力状態を更新する
int gpUpdateKey()
{
	char tmpKey[256]; // 現在のキーの入力状態を格納する
	GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
	for( int i=0; i<256; i++ )
	{ 
		if( tmpKey[i] != 0 ) // i番のキーコードに対応するキーが押されていたら
		{
			Key[i]++;     // 加算
		} 
		else 
		{              // 押されていなければ
			Key[i] = 0;   // 0にする
		}
	}
	return 0;
}

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{       
	ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定

	int ModelHandle, AttachIndex ;
	float TotalTime, PlayTime ;
	bool playing_Flag= false ;

	// 3Dモデルの読み込み
	ModelHandle = MV1LoadModel( "dat/Lat式ミク/Lat式ミク.pmd" ) ;

	//奥行0.1~1000までをカメラの描画範囲とする
	SetCameraNearFar( 0.1f, 1000.0f ) ;

	//(0,10,-20)の視点から(0,10,0)のターゲットを見る角度にカメラを設置
	SetCameraPositionAndTarget_UpVecY( VGet( 0, 20, -20 ), VGet( 0.0f, 10.0f, 0.0f ) ) ;

	// 3Dモデルの1番目のアニメーションをアタッチする
	AttachIndex = MV1AttachAnim( ModelHandle, 0, -1, FALSE ) ;

	// アタッチしたアニメーションの総再生時間を取得する
	TotalTime = MV1GetAttachAnimTotalTime( ModelHandle, AttachIndex ) ;

	// 再生時間の初期化
	PlayTime = 0.0f ;

	while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && gpUpdateKey()==0 )
	{
		if( Key[KEY_INPUT_SPACE] == 1 )                  //スペースキーを押した瞬間
		{
			PlayTime = 0.0f ;                             //再生時間の初期化
			playing_Flag = true ;                         //フラグを立てる
		}

		if( playing_Flag )                                   //フラグが立っていたとき
		{    
			PlayTime += 0.4f ;                                           // 再生時間を進める
			MV1SetAttachAnimTime( ModelHandle, AttachIndex, PlayTime ) ; // 再生時間をセットする
			if( Key[KEY_INPUT_SPACE] == 1 )              //スペースキーを押した瞬間
			{
				/***** 間違い!指摘したバグが直っていません。 *****/
				playing_Flag = false ;                   //フラグを折る
			}

		}else{

			/***** 間違い!if文の中で代入し、比較していません。 *****/
			/***** =を==に修正しても、完全一致することはほとんどないと思われるので、
			       大小で比較するべき。 *****/
			if( TotalTime = PlayTime )                  //再生時間が総再生時間に達したら
			{
				PlayTime = 0.0f ;
				/***** ここでフラグを立てているので、
				       たまたま動いて見えるのではないですか?
				       動いている状態でスペースキーを押すと、きちんと止まりますか? *****/
				playing_Flag = true ;                            //フラグを立てる

			}
		}

		// 3Dモデルの描画
		MV1DrawModel( ModelHandle ) ;
	}

	DxLib_End(); // DXライブラリ終了処理
	return 0;
}

Re: MMDモーション再生について

Posted: 2013年12月22日(日) 20:01
by Isanan

コード:

      }else{
 
            /***** 間違い!if文の中で代入し、比較していません。 *****/
            /***** =を==に修正しても、完全一致することはほとんどないと思われるので、
                   大小で比較するべき。 *****/
            if( PlayTime >= TotalTime )                  //再生時間が総再生時間に達したら
            {
                PlayTime = 0.0f ;
                /***** ここでフラグを立てているので、
                       たまたま動いて見えるのではないですか?
                       動いている状態でスペースキーを押すと、きちんと止まりますか? *****/
                playing_Flag = true ;                            //フラグを立てる
 
            }
        }
 
        // 3Dモデルの描画
        MV1DrawModel( ModelHandle ) ;
    }
 
    DxLib_End(); // DXライブラリ終了処理
    return 0;
}
これであってますか?

コード:

    while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && gpUpdateKey()==0 )
    {
        if( Key[KEY_INPUT_SPACE] == 1 )                  //スペースキーを押した瞬間
        {
            PlayTime = 0.0f ;                             //再生時間の初期化
            playing_Flag = true ;                         //フラグを立てる
        }
 
        if( playing_Flag )                                   //フラグが立っていたとき
        {    
            PlayTime += 0.4f ;                                           // 再生時間を進める
            MV1SetAttachAnimTime( ModelHandle, AttachIndex, PlayTime ) ; // 再生時間をセットする
            if( Key[KEY_INPUT_SPACE] == 1 )              //スペースキーを押した瞬間
            {
                /***** 間違い!指摘したバグが直っていません。 *****/
                playing_Flag = false ;                   //フラグを折る
            }
 
ここのバグって条件式に代入~とかいうものですか?

Re: MMDモーション再生について

Posted: 2013年12月22日(日) 20:16
by みけCAT
上について:多分大丈夫だと思います。
下について:No: 13で指摘したバグ(フラグを立てたフレームですぐにフラグを折る)です。

Re: MMDモーション再生について

Posted: 2013年12月24日(火) 21:53
by Isanan
条件を「もしフラグがたっており、なおかつスペースキーを押したら」に変えてみました。

実行したところスペースキーを押しても何も起こりませんでした。

条件式をどう変更すべきでしょうか

コード:

#include "DxLib.h"
 
int Key[256]; // キーが押されているフレーム数を格納する
 
// キーの入力状態を更新する
int gpUpdateKey()
{
    char tmpKey[256]; // 現在のキーの入力状態を格納する
    GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
    for( int i=0; i<256; i++ )
	{ 
        if( tmpKey[i] != 0 ) // i番のキーコードに対応するキーが押されていたら
		{
            Key[i]++;     // 加算
        } 
		else 
		{              // 押されていなければ
            Key[i] = 0;   // 0にする
        }
    }
    return 0;
}
 
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{    	
	ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
 
    int ModelHandle, AttachIndex ;
    float TotalTime, PlayTime ;
	bool playing_Flag= false ;

    // 3Dモデルの読み込み
    ModelHandle = MV1LoadModel( "Lat式ミク.pmd" ) ;
 
    //奥行0.1~1000までをカメラの描画範囲とする
    SetCameraNearFar( 0.1f, 1000.0f ) ;
 
    //(0,10,-20)の視点から(0,10,0)のターゲットを見る角度にカメラを設置
    SetCameraPositionAndTarget_UpVecY( VGet( 0, 20, -20 ), VGet( 0.0f, 10.0f, 0.0f ) ) ;
 
     // 3Dモデルの1番目のアニメーションをアタッチする
    AttachIndex = MV1AttachAnim( ModelHandle, 0, -1, FALSE ) ;
 
    // アタッチしたアニメーションの総再生時間を取得する
    TotalTime = MV1GetAttachAnimTotalTime( ModelHandle, AttachIndex ) ;
	 
    // 再生時間の初期化
    PlayTime = 0.0f ;

	while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && gpUpdateKey()==0 )
	{
	    if( Key[KEY_INPUT_SPACE] == 1 )                  //スペースキーを押した瞬間
        {
			PlayTime = 0.0f ;							  //再生時間の初期化
            playing_Flag = true ;                         //フラグを立てる
		}

		if( playing_Flag && Key[KEY_INPUT_SPACE] == 1 )
		{
			playing_Flag = false ;
		}

        if( playing_Flag )                                   //フラグが立っていたとき
        {    
            PlayTime += 0.4f ;                                           // 再生時間を進める
		    MV1SetAttachAnimTime( ModelHandle, AttachIndex, PlayTime ) ; // 再生時間をセットする
		
		}else{

			if( PlayTime >= TotalTime )                  //再生時間が総再生時間に達したら
            {
				PlayTime = 0.0f ;
				playing_Flag = true ;                            //フラグを立てる

			}
		}
        // 3Dモデルの描画
        MV1DrawModel( ModelHandle ) ;
	}
 
        DxLib_End(); // DXライブラリ終了処理
        return 0;
}

Re: MMDモーション再生について

Posted: 2013年12月24日(火) 22:24
by みけCAT
条件式をネストさせるのがわかりやすいと思います。

コード:

        if( Key[KEY_INPUT_SPACE] == 1 )                  //スペースキーを押した瞬間
        {
            if(playing_Flag) {
                playing_Flag = false ;
            } else {
                PlayTime = 0.0f ;                             //再生時間の初期化
                playing_Flag = true ;                         //フラグを立てる
            }
        }

Re: MMDモーション再生について

Posted: 2013年12月28日(土) 11:49
by Isanan
実行結果は「スペースキーを押すとモーションを再生し、もう一度スペースキーを押すと停止」となりました。

コード:

#include "DxLib.h"
 
int Key[256]; // キーが押されているフレーム数を格納する
 
// キーの入力状態を更新する
int gpUpdateKey()
{
    char tmpKey[256]; // 現在のキーの入力状態を格納する
    GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
    for( int i=0; i<256; i++ )
	{ 
        if( tmpKey[i] != 0 ) // i番のキーコードに対応するキーが押されていたら
		{
            Key[i]++;     // 加算
        } 
		else 
		{              // 押されていなければ
            Key[i] = 0;   // 0にする
        }
    }
    return 0;
}
 
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{    	
	ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
 
    int ModelHandle, AttachIndex ;
    float TotalTime, PlayTime ;
	bool playing_Flag= false ;

    // 3Dモデルの読み込み
    ModelHandle = MV1LoadModel( "dat/ソリッド・スネーク ver1.2/ソリッド・スネーク.pmd" ) ;
 
    //奥行0.1~1000までをカメラの描画範囲とする
    SetCameraNearFar( 0.1f, 1000.0f ) ;
 
    //(0,10,-20)の視点から(0,10,0)のターゲットを見る角度にカメラを設置
    SetCameraPositionAndTarget_UpVecY( VGet( 0, 20, -20 ), VGet( 0.0f, 10.0f, 0.0f ) ) ;
 
     // 3Dモデルの1番目のアニメーションをアタッチする
    AttachIndex = MV1AttachAnim( ModelHandle, 0, -1, FALSE ) ;
 
    // アタッチしたアニメーションの総再生時間を取得する
    TotalTime = MV1GetAttachAnimTotalTime( ModelHandle, AttachIndex ) ;
	 
    // 再生時間の初期化
    PlayTime = 0.0f ;

	while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && gpUpdateKey()==0 )
	{
        if( Key[KEY_INPUT_SPACE] == 1 )                  //スペースキーを押した瞬間
        {
            if( playing_Flag ) 
			{

                playing_Flag = false ;

            } else {

                PlayTime = 0.0f ;                             //再生時間の初期化
                playing_Flag = true ;                         //フラグを立てる
            }
		}

        if( playing_Flag )                                   //フラグが立っていたとき
        {    
            PlayTime += 0.4f ;                                           // 再生時間を進める
		    MV1SetAttachAnimTime( ModelHandle, AttachIndex, PlayTime ) ; // 再生時間をセットする
		
		}else{

			if( PlayTime >= TotalTime )                  //再生時間が総再生時間に達したら
            {
				PlayTime = 0.0f ;
				playing_Flag = true ;                            //フラグを立てる

			}
		}
        // 3Dモデルの描画
        MV1DrawModel( ModelHandle ) ;
	}
 
        DxLib_End(); // DXライブラリ終了処理
        return 0;
}

Re: MMDモーション再生について

Posted: 2013年12月28日(土) 15:11
by みけCAT
「スペースキーを押したら再生を開始し、モーションの最後まで行ったら再生を停止する」プログラムです。
Isananさんが求めている動作はどのようなものですか?

コード:

// 52行目
        if( Key[KEY_INPUT_SPACE] == 1 )                  //スペースキーを押した瞬間
        {
            if( !playing_Flag ) 
            {

                PlayTime = 0.0f ;                             //再生時間の初期化
                playing_Flag = true ;                         //フラグを立てる
            }
        }

        if( playing_Flag )                                   //フラグが立っていたとき
        {    
            PlayTime += 0.4f ;                                           // 再生時間を進める
            MV1SetAttachAnimTime( ModelHandle, AttachIndex, PlayTime ) ; // 再生時間をセットする

            if( PlayTime >= TotalTime )                  //再生時間が総再生時間に達したら
            {
                PlayTime = 0.0f ;
                playing_Flag = false ;                            //フラグを折る

            }
        }
// 79行目

Re: MMDモーション再生について

Posted: 2014年1月09日(木) 17:56
by Isanan
みけCAT さんが書きました:「スペースキーを押したら再生を開始し、モーションの最後まで行ったら再生を停止する」プログラムです。
Isananさんが求めている動作はどのようなものですか?

コード:

// 52行目
        if( Key[KEY_INPUT_SPACE] == 1 )                  //スペースキーを押した瞬間
        {
            if( !playing_Flag ) 
            {

                PlayTime = 0.0f ;                             //再生時間の初期化
                playing_Flag = true ;                         //フラグを立てる
            }
        }

        if( playing_Flag )                                   //フラグが立っていたとき
        {    
            PlayTime += 0.4f ;                                           // 再生時間を進める
            MV1SetAttachAnimTime( ModelHandle, AttachIndex, PlayTime ) ; // 再生時間をセットする

            if( PlayTime >= TotalTime )                  //再生時間が総再生時間に達したら
            {
                PlayTime = 0.0f ;
                playing_Flag = false ;                            //フラグを折る

            }
        }
// 79行目

返信遅れました。


No:16のように結果が偶然できたものかどうか確かめたいだけでつくりたいのはそれであっています。