ページ 11

ジャンプ、走りのアニメーション

Posted: 2012年7月14日(土) 00:57
by イマダニ
まずこんなプレイヤーの画像をLoadDivGraphで30の配列に分割していれました。

右に向いて立っている=0,1,2,3,4,5
右向きの走り=6,7,8,9,10,11
左向きの走り=12,13,14,15,16,17
左に向いて立っている=18,19,20,21,22,23
ジャンプ=24,25,26,27,28,29

それぞれのアニメーションのコマは6つです。
この画像を使って、プレイヤーを走らせたり、ジャンプをさせようと試みたプログラムがこちらです。

player.cpp

コード:

 
#include "DxLib.h"
#include "Key.h"
#include "player.h"

int img_ch[30];
int sayu;
int grand=360;
double vy;
double ay;
player play;

void pini(){
    play.x=50;
    play.y=grand;
	LoadDivGraph("キャラ.png",30,6,5,128,128,img_ch);
}

void pmove(){
	if(CheckKey( KEY_INPUT_RIGHT)>0){
		sayu=0;
		play.img=6;
		play.x+=4;
	}else if(CheckKey( KEY_INPUT_LEFT )>0){
		sayu=1;
		play.img=12;
		play.x-=4;
	}else{
		if(sayu==1){
			play.img=18;
		}else{
			play.img=0;
		}
	}
}

void pjump(){
	if(CheckKey(KEY_INPUT_SPACE)==1){
	    vy=-4.5;
		ay=0.1;
	}
	vy+=ay;
	play.y+=vy;

	if(play.y>grand){
		play.y=grand;
		vy=0;
		ay=0;
	}
}

void pgraph(){
	DrawRotaGraphF(play.x,play.y,1.0f,0.0f,img_ch[play.img],TRUE);
}
右ボタンを押せば、右走りの一コマに画像が変わり、右方向へ進みます。逆もまたしかりです。
右ボタンを押して、離すと、走るのをやめ、ちゃんと右方向に向いて立つアニメーションの一コマ目に画像が変わり、
右方向に向いて立ちます。逆もまたしかりです。
スペースキーを押せば、画像はかわらず、ぴょーんとじジャンプします。連打すれば無限にジャンプします。
無限にジャンプするのは想定外でしたが、それ以外はいたって正常ですね。ここまではなんとか自力でできました。

で す が

ここから先がわかりません。
いったいどうやってこれをアニメーションさせたらいいんでしょうか?

特にジャンプのアニメーション。さっぱりわかりません。無限ジャンプの原因もさっぱりです。

どうか教えてくださいお願いします。

Re: ジャンプ、走りのアニメーション

Posted: 2012年7月14日(土) 01:24
by jay
全部一遍に解決しようとするとごちゃごちゃになりやすいので、一つずつ確実に片付けて行ってくださいね(←受け売り)

まずはアニメーションから
モーションの番号毎にフレームを割り振らずに、一定の周期で画像を変えるだけならば難しい事はありません
C言語には割った余りを求めてくれる便利な%演算子がありますからね

例えばキャラクターのモーションカウンタという変数をint型で用意します
カウンタなのでメインループ1回ごとにプラス1してあげてくださいね
そして今回は一つの状態に対して6つのアニメーションが用意されているようですね
例えばこれを8フレーム毎に更新してやろうとすればこうなります

コード:

play.count++;	//1フレーム毎に値を増やしていく

//右方向に走っている状態なら、というif文を入れてください
if()
	play.img = 6 + (play.count%48)/8
これで右方向に走っている状態のアニメーションをループ表示させることが出来る筈です
カウンタを48で割った余りを更に8で割っています
%演算子で求めた値はかならず整数になりますが、int型を割った結果が実数(小数点付きの値)になった場合小数点以下は切り捨てられます
よって一定間隔でモーションを更新出来る訳ですね、つまり計算結果が
1.1
1.2
1.3
とかなってる間は、小数点以下が全部切り捨てられて
1
1
1
になるのです。
だから一定の間は同じモーションが表示される訳ですね

まずはアニメーションの方をキッチリしてあげてください
ジャンプのお話はそれからしますね

Re: ジャンプ、走りのアニメーション

Posted: 2012年7月14日(土) 13:27
by イマダニ
返信ありがとうございます。
まず、player.hにある構造体にint countというモーションカウンタをいれました。
player.h

コード:

#ifndef DEF_PLAY_H
#define DEF_PLAY_H
typedef struct{
	int count;        //カウンタ
    int img;        //画像
    double x,y;     //座標
}player;
void pini();
void pcalc();
void pmove();
void pjump();
void pgraph();
#endif

そして、player.cppのキャラの移動制御担うpmove関数にあるif構文の中にアニメーションの文を入れました。
player.cpp

コード:

#include "DxLib.h"
#include "Key.h"
#include "player.h"

int img_ch[30];
int sayu;
int grand=360;
double vy;
double ay;
player play;

void pini(){
    play.x=50;
    play.y=grand;
	LoadDivGraph("キャラ.png",30,6,5,128,128,img_ch);
}

void pcalc(){
	play.count++;  //1フレーム毎に値を増やしていく
}

void pmove(){
	if(CheckKey( KEY_INPUT_RIGHT)>0){
		sayu=0;
		play.img=6+(play.count%48)/8;
		play.x+=4;
	}else if(CheckKey( KEY_INPUT_LEFT )>0){
		sayu=1;
		play.img=12+(play.count%48)/8;
		play.x-=4;
	}else{
		if(sayu==1){
			play.img=18+(play.count%48)/8;
		}else{
			play.img=0+(play.count%48)/8;
		}
	}
}

void pjump(){
	if(CheckKey(KEY_INPUT_SPACE)==1){
	    vy=-4.5;
		ay=0.1;
	}
	vy+=ay;
	play.y+=vy;

	if(play.y>grand){
		play.y=grand;
		vy=0;
		ay=0;
	}
}

void pgraph(){
	DrawRotaGraphF(play.x,play.y,1.0f,0.0f,img_ch[play.img],TRUE);
}

特に問題なく、キャラを走らせることができました。立ち、走りのアニメーション両方とも問題なく動きます。
ありがとうございます。
そして、次はジャンプなんですが、ここに質問する前にぼくなりに考えていたジャンプのアニメーション法があるんですけど
ジャンプボタンが押された瞬間、vyが4.5の時、ジャンプをしようとする画像に切り替えるといったように
一定の高さというか、加速度、ごとに画像を差し替えていけばいいんでしょうか?
もしこの考えが正しいとしてこれをプログラムに組み込むことはできるのでしょうか?
教えてください。

Re: ジャンプ、走りのアニメーション

Posted: 2012年7月14日(土) 16:50
by softya(ソフト屋)
イマダニ さんが書きました:特に問題なく、キャラを走らせることができました。立ち、走りのアニメーション両方とも問題なく動きます。
ありがとうございます。
そして、次はジャンプなんですが、ここに質問する前にぼくなりに考えていたジャンプのアニメーション法があるんですけど
ジャンプボタンが押された瞬間、vyが4.5の時、ジャンプをしようとする画像に切り替えるといったように
一定の高さというか、加速度、ごとに画像を差し替えていけばいいんでしょうか?
もしこの考えが正しいとしてこれをプログラムに組み込むことはできるのでしょうか?
教えてください。
プログラムに出来ますが、加速度は一定ですから速度(vy)を基準にする必要があります。
速度でジャンプ直後、上昇中、下降中の区別ができますので、それで絵を切り替えて下さい。
単なるif文ですね。

Re: ジャンプ、走りのアニメーション

Posted: 2012年7月14日(土) 18:46
by ISLe
jay さんが書きました:そして今回は一つの状態に対して6つのアニメーションが用意されているようですね
例えばこれを8フレーム毎に更新してやろうとすればこうなります

コード:

play.count++;	//1フレーム毎に値を増やしていく

//右方向に走っている状態なら、というif分を入れてください
if()
	play.img = 6 + (play.count%48)/8
これで右方向に走っている状態のアニメーションをループ表示させることが出来る筈です
カウンタを48で割った余りを更に8で割っています
8フレームずつ6パターンの繰り返しであれば、
(play.count/8)%6
のほうが分かりやすいのではないでしょうか。

Re: ジャンプ、走りのアニメーション

Posted: 2012年7月14日(土) 19:47
by イマダニ
ひとまずsoft屋さんの言うとおり、速度を基準に画像を差し替えてみました。
player.cpp

コード:

pjump(){
	if(CheckKey(KEY_INPUT_SPACE)==1){
	    vy=-4.5;
		ay=0.1;
	}
	vy+=ay;
	play.y+=vy;

	if(play.y>grand){
		play.y=grand;
		vy=0;
		ay=0;
	}
	if(vy==-4.5 && ay==0.1){
		play.img=25;  //飛ぶために踏ん張る画像
	}else if(vy>-4.0 && vy<-2.0){
		play.img=26;  //飛んで上昇中の画像
	}else if(vy>-1.9 && vy<4.4 && ay==0.1){
		play.img=27;  //落下中の画像
	}else if(vy==4.5 && ay==0.1){
		play.img=28;  //着地の画像
	}
}

void pgraph(){
	DrawRotaGraphF(play.x,play.y,1.0f,0.0f,img_ch[play.img],TRUE);
}
飛んで上昇中の画像と、落下中の画像は出てほしいところで出ましたが、
最初の踏ん張りと、最後の着地が一瞬すぎるのか見えません。

Re: ジャンプ、走りのアニメーション

Posted: 2012年7月14日(土) 19:51
by イマダニ
イマダニ さんが書きました:ひとまずsoft屋さんの言うとおり、速度を基準に画像を差し替えてみました。
player.cpp

コード:

pjump(){
	if(CheckKey(KEY_INPUT_SPACE)==1){
	    vy=-4.5;
		ay=0.1;
	}
	vy+=ay;
	play.y+=vy;

	if(play.y>grand){
		play.y=grand;
		vy=0;
		ay=0;
	}
	if(vy==-4.5 && ay==0.1){
		play.img=25;  //飛ぶために踏ん張る画像
	}else if(vy>-4.4 && vy<-2.0){
		play.img=26;  //飛んで上昇中の画像
	}else if(vy>-1.9 && vy<4.4 && ay==0.1){
		play.img=27;  //落下中の画像
	}else if(vy==4.5 && ay==0.1){
		play.img=28;  //着地の画像
	}
}

void pgraph(){
	DrawRotaGraphF(play.x,play.y,1.0f,0.0f,img_ch[play.img],TRUE);
}
飛んで上昇中の画像と、落下中の画像は出てほしいところで出ましたが、
最初の踏ん張りと、最後の着地が一瞬すぎるのか見えません。

Re: ジャンプ、走りのアニメーション

Posted: 2012年7月14日(土) 21:01
by softya(ソフト屋)
vy+=ay;しているので、-4.5+0.1がジャンプした瞬間の速度です。
それと既にこの時点で飛んでいるので踏ん張るアニメは空中で行うことになりますが良いのでしょうか?
アニメのコマを優先するのならジャンプしたフレームは速度の設定だけにとどめて空中への移動開始は1フレーム遅らせたほうが良いと思います。
ちなみに、このプログラムだとジャンプにガードが掛かっていないので何度でもジャンプが出来るように見えます。

あと着地で高い所から飛び降りた場合や障害物に頭をぶつけた場合も考えると着地時に4.5の速度である保証はありません。
なので着地をトリガとして着地の画像を1コマから数コマ表示させるようにしないといけません。

※ISLeさんのコメントもお忘れなく。

Re: ジャンプ、走りのアニメーション

Posted: 2012年7月14日(土) 21:38
by jay
あ~、知らない間に凄くお話が進んでる(苦笑)
まぁでも、ちょっとはお役に立てたみたいですから良しとしましょう
ジャンプの方はsoftyaさんにお任せしますね(←逃げた)

ISLe さんが書きました:8フレームずつ6パターンの繰り返しであれば、
(play.count/8)%6
のほうが分かりやすいのではないでしょうか。
あっ、ホントですね!
”8”と”6”というキーワードが入ってるからこちらの方が直感的に分かりやすいですね~
僕って教わったやり方をずっと続けちゃうタイプなので
もっといいやり方があっても知らなかったりするんですよね
よほどのことが無いと新しいやり方を探そうとも思いませんし…
ともかくこのやり方は今後僕も使わせてもらうとしますね(笑) ありがとうございます

Re: ジャンプ、走りのアニメーション

Posted: 2012年7月14日(土) 23:16
by イマダニ
softya さんが書きました:それと既にこの時点で飛んでいるので踏ん張るアニメは空中で行うことになりますが良いのでしょうか?
よくないですね。何やってんだろ俺……
では踏ん張るアニメを入れるには

コード:

if(vyが0でスペースキーが押された時){
      画像を踏ん張りに変える。
}
でいいのかな?
softya さんが書きました:ちなみに、このプログラムだとジャンプにガードが掛かっていないので何度でもジャンプが出来るように見えます。
はい、無限ジャンプしちゃって、ヌルゲーになっちゃって困ってます。
ガードを入れるにはどうしたらいいんでしょう?
考えとしてはvy(速度)とay(重力?)が無い、0の時、ジャンプボタンを押せる。
vyとayがある時、0以上、または以下の時、ジャンプボタンを押せないようにする。
でいいんでしょうか?

Re: ジャンプ、走りのアニメーション

Posted: 2012年7月15日(日) 11:31
by softya(ソフト屋)
イマダニ さんが書きました:
softya さんが書きました:それと既にこの時点で飛んでいるので踏ん張るアニメは空中で行うことになりますが良いのでしょうか?
よくないですね。何やってんだろ俺……
では踏ん張るアニメを入れるには

コード:

if(vyが0でスペースキーが押された時){
      画像を踏ん張りに変える。
}
でいいのかな?
これだけだとジャンプを1フレーム遅延する仕組みが無いですね。どうされますか?
イマダニ さんが書きました:
softya さんが書きました:ちなみに、このプログラムだとジャンプにガードが掛かっていないので何度でもジャンプが出来るように見えます。
はい、無限ジャンプしちゃって、ヌルゲーになっちゃって困ってます。
ガードを入れるにはどうしたらいいんでしょう?
考えとしてはvy(速度)とay(重力?)が無い、0の時、ジャンプボタンを押せる。
vyとayがある時、0以上、または以下の時、ジャンプボタンを押せないようにする。
でいいんでしょうか?
試してみると分かります。聞くより早いですよ。
色々やるのは経験になるのでご自分で試すことをおすすめします。その上でよく分からなったら聞いて下さい。
ちなみにジャンプの頂点でもvyは0になるのでvyはダメだと思います。

Re: ジャンプ、走りのアニメーション

Posted: 2012年7月15日(日) 14:02
by イマダニ
ガードをこんな感じで入れてみました。

コード:

void pjump(){
	if(jumpflag==0){
		if(CheckKey(KEY_INPUT_SPACE)==1){
			vy=-4.5;
			jumpflag=1;
		}
	}
	if(jumpflag==1  && vy==0 && ay==0){
		jumpflag=0;
	}
	ay=0.1;
	vy+=ay;
	play.y+=vy;

	if(play.y>grand){
		play.y=grand;
		vy=0;
		ay=0;
	}

	if(vy==0 && CheckKey(KEY_INPUT_SPACE)==1){
		play.img=25;  //飛ぶために踏ん張る画像
	}else if(vy>-4.5 && vy<-2.0){
		play.img=26;  //飛んで上昇中の画像
	}else if(vy>-1.9 && vy<4.4 && ay==0.1){
		play.img=27;  //落下中の画像
	}else if(vy==0 && ay==0.1){
		play.img=28;  //着地の画像
	}

}
これで無限ジャンプはしなくなりました。ありがとうございます。
ですぅが、
[quote"softya"]アニメのコマを優先するのならジャンプしたフレームは速度の設定だけにとどめて空中への移動開始は1フレーム遅らせたほうが良いと思います。[/quote]
これがよくわかりません。
キャラの画像を先に表示させて、後からジャンプさせるということですか?

Re: ジャンプ、走りのアニメーション

Posted: 2012年7月15日(日) 15:07
by softya(ソフト屋)
デバッガで変数の変化を追いかけると分かると思いますが、変数の変化を頭でシミュレート出来ていないと思います。

コード:

void pjump(){
    if(jumpflag==0){
        if(CheckKey(KEY_INPUT_SPACE)==1){
            vy=-4.5;	←	(1)	ジャンプ開始です。速度が設定されています。
            jumpflag=1;
        }
    }
    if(jumpflag==1  && vy==0 && ay==0){
        jumpflag=0;
    }
    ay=0.1;
    vy+=ay;
    play.y+=vy;
 
    if(play.y>grand){
        play.y=grand;
        vy=0;
        ay=0;	←	(2)	ジャンプしていないときは常に0になります。
    }
 
    if(vy==0 && CheckKey(KEY_INPUT_SPACE)==1){	←	(1)の状況と矛盾します。
        play.img=25;  //飛ぶために踏ん張る画像
    }else if(vy>-4.5 && vy<-2.0){
        play.img=26;  //飛んで上昇中の画像
    }else if(vy>-1.9 && vy<4.4 && ay==0.1){
        play.img=27;  //落下中の画像
    }else if(vy==0 && ay==0.1){					←	(2)の状況と矛盾します。ジャンプ頂点で条件を満たします。
        play.img=28;  //着地の画像
    }
 
}
ジャンプ直後か判断する一番素直な方法は、ジャンプ開始からの経過フレームをカウントすることです。
ジャンプ開始直後なら0にしておけば判別できると思いますので、ifで分岐して play.y+=vy;をしない様にしましょう。

Re: ジャンプ、走りのアニメーション

Posted: 2012年7月15日(日) 17:31
by イマダニ
まだ途中ですが、今こんな感じで、混乱してます……

コード:

void pjump(){
	frmcnt++;
	if(jumpflag==0){
		if(CheckKey(KEY_INPUT_SPACE)==1){
			frmcnt=0;
			jumpflag=1;
		}
		if(jumpflag==1 && frmcnt>1){
			vy=-4.5;
		}
	}
	if(jumpflag==1  && vy==0 && ay==0){
		jumpflag=0;
	}

	ay=0.1;
	vy+=ay;
	play.y+=vy;

	if(play.y>grand){
		play.y=grand;
		vy=0;
		ay=0;
	}
	
	if(frmcnt==0){
		play.img=25;  //飛ぶために踏ん張る画像
	}

}
softya さんが書きました:ジャンプ開始直後なら0にしておけば判別できると思いますので

Re: ジャンプ、走りのアニメーション

Posted: 2012年7月15日(日) 17:32
by イマダニ
イマダニ さんが書きました:まだ途中ですが、今こんな感じで、混乱してます……

コード:

void pjump(){
	frmcnt++;
	if(jumpflag==0){
		if(CheckKey(KEY_INPUT_SPACE)==1){
			frmcnt=0;
			jumpflag=1;
		}
		if(jumpflag==1 && frmcnt>1){
			vy=-4.5;
		}
	}
	if(jumpflag==1  && vy==0 && ay==0){
		jumpflag=0;
	}

	ay=0.1;
	vy+=ay;
	play.y+=vy;

	if(play.y>grand){
		play.y=grand;
		vy=0;
		ay=0;
	}
	
	if(frmcnt==0){
		play.img=25;  //飛ぶために踏ん張る画像
	}

}
softya さんが書きました:ジャンプ開始直後なら0にしておけば判別できると思いますので
これはなんとなくわかったんですが
softya さんが書きました: play.y+=vy;をしない様にしましょう。
これがよくわからないです

Re: ジャンプ、走りのアニメーション

Posted: 2012年7月15日(日) 17:38
by softya(ソフト屋)
ようはジャンプした直後1フレームだけは垂直移動しないように
ay=0.1;
vy+=ay;
play.y+=vy;
はスキップしてくださいということです。踏ん張る画像で上に動いたらマズイですよね?
何らかのフラグ・カウンタで条件判断をお願いします。
ちなみにfrmcntで良いのですがfrmcntがカウントされていないようですね。

Re: ジャンプ、走りのアニメーション

Posted: 2012年7月15日(日) 18:21
by イマダニ
などぅほど、なるほど

コード:

void pjump(){
	frmcnt++;
	if(jumpflag==0){
		if(CheckKey(KEY_INPUT_SPACE)==1){
			frmcnt=0;
			vy=-4.5;
			jumpflag=1;
		}
	}
	if(jumpflag==1 && frmcnt>1){
		ay=0.1;
		vy+=ay;
		play.y+=vy;
	}
	if(jumpflag==1 && vy==0 && ay==0){
		jumpflag=0;
	}


	if(play.y>grand){
		play.y=grand;
		vy=0;
		ay=0;
	}
	if(frmcnt==0){
		play.img=25;  //飛ぶために踏ん張る画像
	}

}
こういうことか!と思って組んだんですが、飛ばなくなりました(;ω;)

Re: ジャンプ、走りのアニメーション

Posted: 2012年7月15日(日) 18:28
by softya(ソフト屋)

コード:

if(jumpflag==1 && frmcnt>1){
        ay=0.1;
        vy+=ay;
        play.y+=vy;
    }
この条件、ジャンプしていない時も実行しないといけないのでは?
あとfrmcnt>1だと2フレーム飛びませんが予定通りですか?

それとデバッガで変数の変化必ず調査してくださいね。printDXでも良いです。

Re: ジャンプ、走りのアニメーション

Posted: 2012年7月15日(日) 19:06
by イマダニ
踏ん張った!踏ん張りました!

コード:

void pjump(){
	frmcnt++;
	if(jumpflag==0){
		if(CheckKey(KEY_INPUT_SPACE)==1){
			frmcnt=0;
			vy=-4.5;
			jumpflag=1;
		}
		if(frmcnt>10){
			ay=0.1;
			vy+=ay;
			play.y+=vy;
		}
	}
	if(jumpflag==1  && ay==0){
		jumpflag=0;
	}


	if(play.y>grand){
		play.y=grand;
		vy=0;
		ay=0;
	}
	if(frmcnt>=0 && frmcnt<10){
		play.img=25;  //飛ぶために踏ん張る画像
	}else if(vy>-4.5 && vy<0 && ay==0.1){
		play.img=26;
	}else if(vy>0 && vy<4.5 && ay==0.1){
		play.img=27;
	}
}
こうしたら踏ん張りました。
ですが、起動した瞬間、ほんの一瞬だけ、踏ん張った状態になってから、通常の状態になります。
それとジャンプのどの地点が何フレームかわからないので飛んでる画像は早さを条件にしました。
着地はどうしたらいいかわかりません。
そしてこの事なんですが……
softya さんが書きました:それとデバッガで変数の変化必ず調査してくださいね。printDXでも良いです。
すいません。とてつもなく恥ずかしいんですが、デバッガで変数の変化とか見れるんですか?
初めて知りました。

Re: ジャンプ、走りのアニメーション

Posted: 2012年7月15日(日) 19:31
by softya(ソフト屋)
踏ん張り時間が一瞬なのは15行目と20行目の働きによるものです。
着地はjumpflagが1でplay.y>grandの時に特殊なことをするしか無いでしょう。

なんか色々と混乱している見たいですから、整理するため各状態を表す値と状態が移行する条件、変化する値をまとめて書きだしてみてはどうでしょうか?
まとまったら状態を数値分け(enum推奨)してswitch~caseで状態別の処理をします。

参考
(1)通常
(2)ジャンプ踏ん張り
(3)ジャンプ上昇中

(1)→(2) jumpflagが0でSPACEキーを押下。frmcntが0で、jumpflagが1になりvyが-4.5となる。


デバッガの使い方については。
「太田研究室 > Visual C++ 2008 Express Edition プログラミング入門」
http://cvwww.ee.ous.ac.jp/vc08prog.html#6

ミスです。printDX→printfDXでした。

Re: ジャンプ、走りのアニメーション

Posted: 2012年7月16日(月) 19:44
by イマダニ
こんな感じでしょうか?

(1)通常
(2)ジャンプ踏ん張り
(3)ジャンプ上昇中
(4)ジャンプ落下中
(5)着地

(1)→(2) jumpflagが0で、SPACEキーを押下。frmcntが0で、jumpflagが1になりvyが-4.5となる。

(2)→(3) jumpflagが1で、frmcntが0~10へ上昇中。その間だけ、play.imgが25に変わる。

(3)→(4) frmcountが10以上になった時にvyにayを加算代入、play.yにvyを加算代入する。
      ジャンプ開始。play.imgが26に変わる。

(4)→(5) vyがゼロになり、頂点に達する。
      ayが加算されているので、vyが正の数になる。よって落下。
      play.imgが27に変わる。

(5)→(1) play.yがgrandを超え、延々と下に落ちてしまうため、
       vyとayを0にし、play.yにgrandを代入。
       play.imgが28に変わる。その後jumpflagが0になる。

Re: ジャンプ、走りのアニメーション

Posted: 2012年7月16日(月) 21:33
by softya(ソフト屋)
しまった!場合分けで書き忘れました。
(1)通常
(2)ジャンプ踏ん張り
(3)ジャンプ上昇中
(4)ジャンプ落下中
(5)着地
各状態の時に各々必ずやる処理も書いて下さい。
(2)→(3) jumpflagが1で、frmcntが0~10へ上昇中。その間だけ、play.imgが25に変わる。
10フレーム(約0.17秒)も踏ん張るアニメでしょうか?
その間はplay.yにvyを加算が無いので上への移動は出来ないのですが攻撃回避とか大丈夫ですか?

「jumpflagが1で、frmcntが0~10へ上昇中。」に付いては、(3)→(4) の説明を読んで下さい。

>その間だけ、play.imgが25に変わる。
これは、(2)の状態の時必ずする処理ですね。なので(2)→(3)からは分離して下さい。

(2)ジャンプ踏ん張り
play.imgが25に変わる。
となります。


(3)→(4) frmcountが10以上になった時にvyにayを加算代入、play.yにvyを加算代入する。
      ジャンプ開始。play.imgが26に変わる。
「frmcountが10以上になった時に」は(3)→(4) の条件ではないではなく(2)→(3) の条件です。
「vyにayを加算代入、play.yにvyを加算代入する。ジャンプ開始。play.imgが26に変わる。」も(3)の状態処理ですね。

以下同様にお願いします。

【補足】
とりあえずサンプルを書いておきます。
よりプログラムに近づけてあります。

コード:

(1)通常
	play.imgは通常のもの。
	(1)→(2) 条件(jumpflagが0で、SPACEキーを押下)	条件成立時(状態を(2)に変更。frmcntが0で、jumpflagが1になりvyが-4.5となる)

(2)ジャンプ踏ん張り
	play.imgが25。
	frmcount++
	(2)→(3) 条件(frmcountが10以上になったら)		条件成立時(状態を(3)に変更)

Re: ジャンプ、走りのアニメーション

Posted: 2012年7月19日(木) 22:59
by イマダニ
遅くなりました
こんな感じですかね?

(1)通常
play.imgは通常のもの。
(1)→(2) 条件(jumpflagが0で、SPACEキーを押下)
条件成立時(状態を(2)に変更。frmcntが0で、jumpflagが1になりvyが-4.5となる);

(2)ジャンプ踏ん張り
play.imgが25。
frmcount++
(2)→(3) 条件(frmcountが4以上になったら)

(3)ジャンプ上昇
play.img=26。
vyにayを加算代入、play.yにvyを加算代入する。
(3)→(4) 条件(ayが0.1の時、vyが0になったら)
条件成立時(状態を(4)に変更)

(4)ジャンプ落下
play.img=27。
(4)→(5) 条件(play.yがgrandになったら)
条件成立時(状態を(5)に変更)

(5)着地
    vy=0,ay=0。
play.img=28。
(5)→(1) 条件(jumpflagが0になったら)
条件成立時(状態を(1)に変更)

Re: ジャンプ、走りのアニメーション

Posted: 2012年7月19日(木) 23:38
by softya(ソフト屋)
状態変化条件で、各状態の時に変化or設定していないのに条件になっているものがあります。
(3)→(4) 条件(ayが0.1の時、vyが0になったら) (3)ジャンプ上昇にayに関する記述がない。
(4)→(5) 条件(play.yがgrandになったら) (4)ジャンプ落下にplay.yに関する記述がない。
(5)→(1) 条件(jumpflagが0になったら) (5)着地にjumpflagに関する記述がない。

Re: ジャンプ、走りのアニメーション

Posted: 2012年8月01日(水) 19:50
by イマダニ
テストで遅れました。これでいいですか?

(1)通常
play.imgは通常のもの。
(1)→(2) 条件(jumpflagが0で、SPACEキーを押下)
条件成立時(状態を(2)に変更。frmcntが0で、jumpflagが1になりvyが-4.5となる);

(2)ジャンプ踏ん張り
play.imgが25。
frmcount++
(2)→(3) 条件(frmcountが4以上になったら)

(3)ジャンプ上昇
play.imgが26。
ay=0.1。
vyにayを加算代入、play.yにvyを加算代入する。
(3)→(4) 条件(ayが0.1の時、vyが0になったら)
条件成立時(状態を(4)に変更)

(4)ジャンプ落下
play.imgが27。
play.y>grand
(4)→(5) 条件(play.yがgrandを超えたら)
条件成立時(状態を(5)に変更)

(5)着地
vy=0,ay=0。
play.y=grand
play.img=28。
jumpflag=0
(5)→(1) 条件(jumpflagが0になったら)
条件成立時(状態を(1)に変更)

Re: ジャンプ、走りのアニメーション

Posted: 2012年8月01日(水) 20:51
by softya(ソフト屋)
状態遷移の基本的な流れとしてはOKですが細かい所に問題があるので調整していきましょう。
まず、switch文型の状態遷移(状態が変わること)に1フレーム必要ですので、アニメと実際の落下状態にずれが起きないかよく検証する必要があります。

まず、
(3)→(4) 条件(ayが0.1の時、vyが0になったら)
ですがfloat型変数がジャスト0になることは無いと思って下さい(誤差のため)。成ることもありますが何時も起こる偶然ではありません。
v>0なら下降中と断言できると思います。
あと(3)→(4)の時はbreak;せずに(4)に移行する必要があります。下降中に下降のアニメに即時移行のためです。

(4)→(5) 条件(play.yがgrandを超えたら)
に関しても上と同様にbreak;せずに(5)に移行する必要があります。着地で着地のアニメに即時移行のためです。

(5)→(1) 条件(jumpflagが0になったら)
に関しては次フレームで移動アニメに移行するなら(jumpflagが0になったらは不要で無条件で良いでしょう。
こうすれば、1フレームだけ着地アニメが表示されます。

重要ポイント:(3)→(4) と(4)→(5)の条件成立時は即時状態移行のためbreak;しないで下さい。
理解できたら、プログラムのswitch文に書き換えてみましょう。

Re: ジャンプ、走りのアニメーション

Posted: 2012年8月03日(金) 01:57
by イマダニ
理屈はなんとなくわかります
ですが、何を目安に状態遷移したらいいかわかりません。
早い話が、どの変数をcaseにすればいいのかってことなんですけど
switch()←このカッコ内
フレーム数で分けるのか、それともジャンプフラグで分けるか……

Re: ジャンプ、走りのアニメーション

Posted: 2012年8月03日(金) 10:35
by softya(ソフト屋)
専用の変数を設けましょう。ついでにenum化もしましょうか。
こんな感じで組みます。

コード:

//	アクション状態のenum定義
enum ActionState_e {
	ACTION_STATE_MOVE,		//(1)通常
	ACTION_STATE_JUMP,		//(2)ジャンプ踏ん張り
	ACTION_STATE_JUMP_UP,	//(3)ジャンプ上昇中
	ACTION_STATE_JUMP_DOWN,	//(4)ジャンプ落下中
	ACTION_STATE_LANDING,	//(5)着地
};

//	アクション状態の変数
enum ActionState_e action_state = ACTION_STATE_MOVE;

//	アクション状態別処理。
switch( action_state ) {
case ACTION_STATE_MOVE:			//(1)通常
	break;
case ACTION_STATE_JUMP:			//(2)ジャンプ踏ん張り
	break;
case ACTION_STATE_JUMP_UP:		//(3)ジャンプ上昇中
	break;//上にも書いた通り要条件
case ACTION_STATE_JUMP_DOWN:	//(4)ジャンプ落下中
	break;//上にも書いた通り要条件
case ACTION_STATE_LANDING:		//(5)着地
	break;
}

Re: ジャンプ、走りのアニメーション

Posted: 2012年8月04日(土) 16:49
by イマダニ
そうか!enum使うこと忘れてました……

コード:

#include "DxLib.h"
#include "Key.h"
#include "player.h"

enum ActionState_e {
    ACTION_STATE_MOVE,      //(1)通常
    ACTION_STATE_JUMP,      //(2)ジャンプ踏ん張り
    ACTION_STATE_JUMP_UP,   //(3)ジャンプ上昇中
    ACTION_STATE_JUMP_DOWN, //(4)ジャンプ落下中
    ACTION_STATE_LANDING,   //(5)着地
};

enum ActionState_e action_state = ACTION_STATE_MOVE;

int img_ch[30];
int sayu;
int grand=360;
double vy,ay;
int frmcnt;
int jumpflag;
player play;

void pini(){
    play.x=50;
    play.y=grand;
	jumpflag=0;
	LoadDivGraph("キャラ.png",30,6,5,128,128,img_ch);
}

void pcalc(){
	play.count++;  //1フレーム毎に値を増やしていく
}

void pmove(){
	if(CheckKey( KEY_INPUT_RIGHT)>0){
		sayu=0;
		play.img=6+(play.count/8)%6;
		play.x+=4;
	}else if(CheckKey( KEY_INPUT_LEFT )>0){
		sayu=1;
		play.img=12+(play.count/8)%6;
		play.x-=4;
	}else{
		if(sayu==1){
			play.img=18+(play.count/8)%6;
		}else{
			play.img=0+(play.count/8)%6;
		}
	}
}

void pjump(){
	switch( action_state ) {
	case ACTION_STATE_MOVE:         //(1)通常
		if(CheckKey(KEY_INPUT_SPACE)>0){ //スペースが押されたら
			jumpflag=1;//フラグを1に
			vy=-4.5; //vyを-4.5
			frmcnt=0; //frmcnt=をゼロに
			action_state=ACTION_STATE_JUMP;
		}
		break;
	case ACTION_STATE_JUMP:         //(2)ジャンプ踏ん張り
		play.img=25; //画像を25に
		frmcnt++; //フレーム加算開始
		if(frmcnt>4){ //フレームが4になったら
			action_state=ACTION_STATE_JUMP_UP; //じゃんぷ
		}
		break;
	case ACTION_STATE_JUMP_UP:      //(3)ジャンプ上昇中
		play.img=26;
		ay=0.1; //重力追加
		vy+=ay; //vyにayを加算
		play.y+=vy; //プレイヤー座標にvyを加算
		if(ay==0.1 && vy>0){ //ayが0.1でvyが0以下の時
			action_state=ACTION_STATE_JUMP_DOWN;
		}
		break;
	case ACTION_STATE_JUMP_DOWN:    //(4)ジャンプ落下中
		play.img=27;
		ay=0.1;
		vy+=ay;
		play.y+=vy;
		if(play.y>grand){
			action_state=ACTION_STATE_LANDING;
		}
		break;
	case ACTION_STATE_LANDING:      //(5)着地
		vy=0;
		ay=0;
		play.y=grand;
		play.img=28;
		jumpflag=0;
		action_state=ACTION_STATE_MOVE;
		break;
	}
}

void pgraph(){
	DrawRotaGraphF(play.x,play.y,1.0f,0.0f,img_ch[play.img],TRUE);
}
これでしっかり踏ん張ってからジャンプし、しっかり着地してから、通常の状態に戻りました。
ジャンプ成功です!break;を消すと踏ん張りの状態で止まってしまうのでつけたままにしました。
ここまで来れたのも、ソフト屋さんが丁寧に教えてくれたおかげです!本当にありがとうございます!
走りのアニメーションについて教えてくださった、ISLeさんとjayさんにも感謝です。ありがとうございました!
で、このコードなんですか、なにか問題というか、もっとこうしたほうがいいなどあったら教えてください。

Re: ジャンプ、走りのアニメーション

Posted: 2012年8月04日(土) 17:08
by softya(ソフト屋)
気になるのはグローバル変数が多いところでしょうか。
あと構造体でまとめることも必要だと思います。
でbreak;の件ですが。

コード:

        if(ay==0.1 && vy>0){ //ayが0.1でvyが0以下の時
            action_state=ACTION_STATE_JUMP_DOWN;
            //break; わざとしません。このまま下のcase文の処理に進みます。
		} else {
			break;//このまま抜けます。
		}
と言う感じで処理すれば問題ないはずでが?

switch~case文で書いた今回の様な制御を状態遷移(せんい)による制御といいます。
ゲームだとメニュー処理やタイトル画面と本編の切り替えなど応用範囲が広いので覚えて置いてください

よく有るゲームの基本的な状態遷移図。 今回は書きませんでしたが図に書くのが分かりやすくするコツです。
画像