モーションが切り替わらない。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
keito94
記事: 264
登録日時: 3年前
連絡を取る:

モーションが切り替わらない。

#1

投稿記事 by keito94 » 3年前

久々に質問させていただきます。アクションゲームを作る一環でキャラのモーションを動かしてますが、何故かモーションが切り替わりません。
Anim.h

コード:

#pragma once
#include <vector>
using namespace std;

const int MLOOP = -1;
const int MSTOP = -2;
const int MEND = -3;

enum MOTION_NAME{
	STAND,WALK,JUMPUP,JUMPDOWN,LAND
};

class CMotion {
public:
	int No;
	int Time;
};

class CAnim {
public:
	int AnimIndex, MotionType,PrevMotion;
	float AnimCnt;
	CAnim(const CMotion* motion, int col, int row);
	vector<vector<CMotion>> WMotion;
	vector<CMotion> VMotion;
	void Animation(float anim_spped);
	void MotionChange(int motion);
	int GetAnimNo() const { return WMotion[MotionType][AnimIndex].No; }
};
Anim.cpp

コード:

#include "Anim.h"

CAnim::CAnim(const CMotion* motion, int col, int row)
	:AnimIndex(0),MotionType(0), AnimCnt(0.0F),PrevMotion(-1){
	for (int i = 0; i < col; i++) {
		for (int j = 0; j < row; j++) {
			VMotion.push_back(motion[i*row + j]);
		}
		WMotion.push_back(VMotion);
		VMotion.clear();
	}
}

void CAnim::Animation(float anim_spped) {
	AnimCnt += anim_spped;
	if (AnimCnt > WMotion[MotionType][AnimIndex].Time) {
		AnimCnt = 0;
		AnimIndex++;
		if (WMotion[MotionType][AnimIndex].No == MLOOP) {
			AnimIndex = 0;
		}
		else if (WMotion[MotionType][AnimIndex].No == MEND) {
			MotionType = 0;
			AnimIndex = 0;
		}
		else if (WMotion[MotionType][AnimIndex].No == MSTOP) {
			AnimIndex--;
		}
		else {

		}
	}
}

void CAnim::MotionChange(int motion) {
	//前と同じなら変更なし。
	if (motion == PrevMotion) return;
	motion = PrevMotion;
	// 前と同じモーションなら変更しない
	if (motion == PrevMotion) return;
	PrevMotion = motion;
	//モーション変更の特殊条件
	//ジャンプモーションから立ちモーションへの直接移行はない
	if ((MotionType == JUMPUP || MotionType == JUMPDOWN || MotionType == LAND || MotionType == STAND) &&
		motion == STAND)	return;
	if (MotionType == JUMPUP && motion == WALK) return;
	AnimIndex = 0;
	AnimCnt = 0;
	MotionType = motion;
}
MotionChange(モーション名)でモーションを切り替えます。
なんとか治そうと列挙体について調べてみたのですが、よくわからないと言うのもあります。
どうすればいいのでしょうか?
※コードは一部のみなので単体では動きません。
最後に編集したユーザー keito94 on 2017年4月23日(日) 18:29 [ 編集 1 回目 ]
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
keito94
記事: 264
登録日時: 3年前
連絡を取る:

Re: モーションが切り替わらない。

#2

投稿記事 by keito94 » 3年前

Player.cpp(一部のみ)

コード:

	JoyPad.Update();
	if (JoyPad.Get(PAD_INPUT_RIGHT)) {
		AnimObj->MotionChange(WALK);
		Dir = FALSE;
		VX = 3.0F;
	}
	else if (JoyPad.Get(PAD_INPUT_LEFT)){
		AnimObj->MotionChange(WALK);
		Dir = TRUE;
		VX = -3.0F;
	}
	else {
		AnimObj->MotionChange(WALK);
		VX = 0;
	}
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
みけCAT
記事: 6284
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: モーションが切り替わらない。

#3

投稿記事 by みけCAT » 3年前

keito94 さんが書きました:どうすればいいのでしょうか?
デバッグをすればいいでしょう。
変数の値が意図したものかや、条件分岐が意図した通りに行われているかなどを、デバッガまたはログを出力するコードの挿入(printfデバッグ的な)などを用いてチェックするといいかもしれません。
keito94 さんが書きました:Player.cpp(一部のみ)
モーションとしてWALKしか渡していないので、切り替えていないから切り替わらないという可能性が考えられます。
keito94 さんが書きました:

コード:

void CAnim::MotionChange(int motion) {
	//前と同じなら変更なし。
	if (motion == PrevMotion) return;
	motion = PrevMotion;
	// 前と同じモーションなら変更しない
	if (motion == PrevMotion) return;
motionにPrevMotionを代入した直後に「motionとPrevMotionが同じならreturnする」という処理をしているので、
・デバッガや宇宙線、他のスレッドなど外部からmotionまたはPrevMotionがこの間に書き換えられる
・motionが読み取り専用メモリに割り当てられている、最適化のバグなどの原因で、motionが書き換えられない
などの変なことが起きなければ、絶対returnしてしまうでしょう。
これは怪しいですね。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
keito94
記事: 264
登録日時: 3年前
連絡を取る:

Re: モーションが切り替わらない。

#4

投稿記事 by keito94 » 3年前

みけCATさんに言われたとおりデバッグコンソールを使ってみたら、

コード:

bool CPlayer::Move() {
	Game->OffSetPlayer();
	JoyPad.Update();
	if (JoyPad.Get(PAD_INPUT_RIGHT)) {
		AnimObj->MotionChange(WALK);
		Dir = FALSE;
		VX = 3.0F;
	}
	else if (JoyPad.Get(PAD_INPUT_LEFT)){
		AnimObj->MotionChange(WALK);
		Dir = TRUE;
		VX = -3.0F;
	}
	else {
		AnimObj->MotionChange(WALK);
		VX = 0;
	}

	ColObj->GetMove(&X, &Y, &VX, &VY, &JumpCount, &GroundFlag, &JumpTime, &JumpGrav);

	//ジャンプボタンが押されているフレームを確保する(二段ジャンプとか用)
	if (JoyPad.Get(PAD_INPUT_1)) {
		JBFrame++;
	}
	else {
		JBFrame = 0;
	}

	//二段ジャンプに対応する。
	if (JBFrame == 1) {
		JumpCount = 0;
		JumpTime++;
	}

	//ジャンプボタンが押されていれば重力は小さくなり、離されていれば大きくなる。
	if (JBFrame > 0) {
		JumpGrav = true;
	}
	else {
		JumpGrav = false;
	}

	//ジャンプ回数をカウントする。
	if (JumpTime > 2) {
		MaxJump = true;
	}
	else {
		MaxJump = false;
	}

	if (JoyPad.Get(PAD_INPUT_1) > 0 && JumpCount < 5) {
		if (JumpCount < 1 && !MaxJump) {
			JumpCount++;
			VY = -7.0F;
		}
	}
	AnimObj->Animation(0.4F);
	printf("アニメモーション番号:%d", AnimObj->MotionType);
	return true;
}
移動しても、

コード:

アニメモーション番号:0
のままでした。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
keito94
記事: 264
登録日時: 3年前
連絡を取る:

Re: モーションが切り替わらない。

#5

投稿記事 by keito94 » 3年前

みけCAT さんが書きました: motionにPrevMotionを代入した直後に「motionとPrevMotionが同じならreturnする」という処理をしているので、
・デバッガや宇宙線、他のスレッドなど外部からmotionまたはPrevMotionがこの間に書き換えられる
・motionが読み取り専用メモリに割り当てられている、最適化のバグなどの原因で、motionが書き換えられない
などの変なことが起きなければ、絶対returnしてしまうでしょう。
これは怪しいですね。
言われてみればたしかに怪しいですね…。
いまいちよくわからないのでキャラのモーションの切り替えプログラムのサンプルコードでも上げてくれないでしょうか?
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
keito94
記事: 264
登録日時: 3年前
連絡を取る:

Re: モーションが切り替わらない。

#6

投稿記事 by keito94 » 3年前

物は試し、と

コード:

	//前と同じなら変更なし。
	if (PrevMotion == motion) return;
	motion = PrevMotion;
	// 前と同じモーションなら変更しない
	if (PrevMotion == motion) return;
	PrevMotion = motion;
を削除してみたところ、モーションの切り替えはできたのですが、今度は移動のときにキャラが消えてしまいます。
デバッグコンソールによると、移動モーション時に

コード:

アニメモーション番号:1
アニメフレーム番号:-8
と移動モーションではありえない数値が書かれているのがわかりました。
移動モーションの数字と移動ルーチンのソースコードは以下のとおりです。
Player.cpp

コード:

	CMotion temp[MOTION_MAX][ANIM_MAX]=
	{
		//上から順に
		//{STAND,WALK,JUMPUP,JUMPDOWN,LAND}
		{{0,3},{1,3} ,{2,6},{1,3}, {0,3} ,{MLOOP,0}},//立ち
		{{3,3},{4,3},{0,3},{5,3},{6,3},{7,3} ,{MLOOP,0}},//歩き
		{{0,3},{8,3},{9,3},{10,15},{MSTOP,0}},//ジャンプ上り
		{{11,3},{12,3}, {13,3},{MSTOP,0}},//ジャンプ下り
		{{15,3},{16,3}, {17,3}, {MEND,0}},//着地
	};
//省略
bool CPlayer::Move() {
	Game->OffSetPlayer();
	JoyPad.Update();
	if (JoyPad.Get(PAD_INPUT_RIGHT)) {
		AnimObj->MotionChange(WALK);
		Dir = FALSE;
		VX = 3.0F;
	}
	else if (JoyPad.Get(PAD_INPUT_LEFT)){
		AnimObj->MotionChange(WALK);
		Dir = TRUE;
		VX = -3.0F;
	}
	else {
		AnimObj->MotionChange(STAND);
		VX = 0;
	}

	ColObj->GetMove(&X, &Y, &VX, &VY, &JumpCount, &GroundFlag, &JumpTime, &JumpGrav);

	//ジャンプボタンが押されているフレームを確保する(二段ジャンプとか用)
	if (JoyPad.Get(PAD_INPUT_1)) {
		JBFrame++;
	}
	else {
		JBFrame = 0;
	}

	//二段ジャンプに対応する。
	if (JBFrame == 1) {
		JumpCount = 0;
		JumpTime++;
	}

	//ジャンプボタンが押されていれば重力は小さくなり、離されていれば大きくなる。
	if (JBFrame > 0) {
		JumpGrav = true;
	}
	else {
		JumpGrav = false;
	}

	//ジャンプ回数をカウントする。
	if (JumpTime > 2) {
		MaxJump = true;
	}
	else {
		MaxJump = false;
	}

	if (JoyPad.Get(PAD_INPUT_1) > 0 && JumpCount < 5) {
		if (JumpCount < 1 && !MaxJump) {
			JumpCount++;
			VY = -7.0F;
		}
	}
	AnimObj->Animation(0.4F);
	printf("アニメモーション番号:%d\n", AnimObj->MotionType);
	printf("アニメフレーム番号:%d\n",AnimObj->GetAnimNo());
	return true;
}
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
keito94
記事: 264
登録日時: 3年前
連絡を取る:

Re: モーションが切り替わらない。

#7

投稿記事 by keito94 » 3年前

今の質問はひとまず解決とさせていただきます。
さっきの質問はまた別のスレで答えようと思います。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

返信

“C言語何でも質問掲示板” へ戻る