キャラクターの移動について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
フォンクス

キャラクターの移動について

#1

投稿記事 by フォンクス » 16年前

このサイトに載っている一定区間を歩かせるプログラムを参考に
ジョイパッドで動かせるプログラムを作成したのですが、
動いている途中で別のキーを押すと動かなくなってしまうのですが、
それがどうしても直せなかったので助けてください
typedef struct{
	int Graph[16];
	int PlayerID;
	int hp,x,y,muki;
	int Speed , Kyori;
	int walkflg;
	tama_t Tama;
}Player_t;
Player_t Player[4];
ソース
if(Player[0].x % 32 == 0 && Player[0].y % 32 == 0){
		Player[0].walkflg = 1;//移動
		if(GetJoypadInputState(DX_INPUT_PAD1) & PAD_INPUT_LEFT){
			Player[0].muki = 1;//左
		}else if(GetJoypadInputState(DX_INPUT_PAD1) & PAD_INPUT_UP){
			Player[0].muki = 0;//上
		}else if(GetJoypadInputState(DX_INPUT_PAD1) & PAD_INPUT_RIGHT){
			Player[0].muki = 3;//右
		}else if(GetJoypadInputState(DX_INPUT_PAD1) & PAD_INPUT_DOWN){
			Player[0].muki = 2;//下
		}else{
			Player[0].walkflg = 0;
		}
		if((GetJoypadInputState(DX_INPUT_PAD1) & PAD_INPUT_Z)){ //方向転換
			Player[0].walkflg = 0;
			if(GetJoypadInputState(DX_INPUT_PAD1) & PAD_INPUT_LEFT){
				Player[0].muki = 1;//左
			}else if(GetJoypadInputState(DX_INPUT_PAD1) & PAD_INPUT_UP){
				Player[0].muki = 0;//上
			}else if(GetJoypadInputState(DX_INPUT_PAD1) & PAD_INPUT_RIGHT){
				Player[0].muki = 3;//右
			}else if(GetJoypadInputState(DX_INPUT_PAD1) & PAD_INPUT_DOWN){
				Player[0].muki = 2;//下
			}
		}
	}

kazuoni

Re:キャラクターの移動について

#2

投稿記事 by kazuoni » 16年前

規約通り、コードはプレタグで囲ってください。
あと字下げをしないとなかなか見づらいです。

あと、方向転換は歩いてる途中でキー入力を受け付けているのですが、
1区間歩かせたいならこの処理はNGだと思います。。
32で割れない時に違う方向に進んでしまうので。
何を実装しようとしているのか分からないので何とも言えないですが・・・

フォンクス

Re:キャラクターの移動について

#3

投稿記事 by フォンクス » 16年前

すみませんでした。今度から気をつけます。

移動と書いてある方は実際にキャラを移動させて、
方向転換はジョイパッドの6番が押されてるときに
方向だけ変えたいのです。

kazuoni

Re:キャラクターの移動について

#4

投稿記事 by kazuoni » 16年前

編集してもらえばよいのですが^^;

>方向転換はジョイパッドの6番が押されてるときに
>方向だけ変えたいのです

もし右に進んでいて元いた場所から29進み、
方向転換のif文に合致したとします。(y方向)
向きのフラグは変わりますが、
次にループで移動のif文には合致しません。
なぜならxが29進んだだけで止まっているからです。(32で割ったときに余りが出続ける)
すると歩かないフラグが立ちます。→歩きません。

kazuoni

Re:キャラクターの移動について

#5

投稿記事 by kazuoni » 16年前

ちょっと解釈違っていました。。
>すると歩かないフラグが立ちます。
は方向転換のif文に入ったときに歩かないフラグが立つのですね^^;
失礼しました。

フォンクス

Re:キャラクターの移動について

#6

投稿記事 by フォンクス » 16年前

すみません。編集しました。

kazuoni

Re:キャラクターの移動について

#7

投稿記事 by kazuoni » 16年前

今見て気がついたのですが・・・
このコードだと
「x,yともに32で割り切れるときに方向を決定し、方向変換可能」
ということなので、右向いていて、6番+左キー押されたら左を向くってことですか^^;
大変失礼しました。
このプログラムには特に問題がないと思うのですが・・・
32で割り切れない時のボタンと移動の処理はどのように書いていますか?

フォンクス

Re:キャラクターの移動について

#8

投稿記事 by フォンクス » 16年前

32で割り切れない時には入力は何もやっていません。
移動は4キャラ用にループで回しています。

Player[/url].Speedは初期値として 1 が入っています。

for(i=0;i<4;i++){
		if(Player.walkflg == 1){
			switch(Player.muki){
				case 0://上
					Player.y -= Player.Speed;
					break;
				case 1://左
					Player.x -= Player.Speed;
					break;
				case 2://下
					Player.y += Player.Speed;
					break;
				case 3://右
					Player.x += Player.Speed;
					break;

			}
		}
	}

kazuoni

Re:キャラクターの移動について

#9

投稿記事 by kazuoni » 16年前

んん・・・特に問題がないように思えます・・・が・・・。
自分の家にジョイパッドがないので、ちょっと試せる環境にないので
動かすことができないのですが・・・。
とりあえず、移動中は何を押そうが、No:27839のコードには影響はしないので
他の部分でジョイパッドのボタンを押したときに
Player[0].walkflg=0になって止まっているのか確認してみてください。
もしかしたら全コードをUPしてもらったほうが早いかもしれません。

Dixq (管理人)

Re:キャラクターの移動について

#10

投稿記事 by Dixq (管理人) » 16年前

こんにちは。
何度もGetJoypadInputState(DX_INPUT_PAD1)を呼んでるのがちょっともったいないですね。
ゲームプログラミングの館40章のように、
キーの入力状態を最初に配列か構造体に入れてしまい、それを使った方が良さそうです。

また、コード全文を投稿してもらった方がわかりやすいかもしれません。

フォンクス

Re:キャラクターの移動について

#11

投稿記事 by フォンクス » 16年前

キャラクターの移動に関しては下のとおりです
ブロックの当たり判定の部分は、ブロックの描画の座標が全てY軸方向に+32にしてあるので
当たり判定の部分でずらしてます。


#include"GV.h"
	/*キャラクターの向き
		0:上 Y - 1
		1:左 X - 1
		2:下 Y + 1
		3:右 X + 1
	*/

int HitBlock(int x,int y,int muki,int num)	//X座標 Y座標 向き キャラ番号(1P:0 2P:1 3P:2 4P:3)
{
	//Map.Normal[ Y ][ X ]
	switch(muki){
		case 0:
			switch(Map.Normal[(Player[num].y / 32) - 2][Player[num].x / 32]){
				case 0:
					return 0;
				case 1:
					return 1;
				case 2:
					return 2;
				case 3:
					return 3;
			}
			break;
		case 1:
			switch(Map.Normal[(Player[num].y / 32 ) - 1][(Player[num].x / 32) - 1]){
				case 0:
					return 0;
				case 1:
					return 1;
				case 2:
					return 2;
				case 3:
					return 3;
			}
			break;
		case 2:
			switch(Map.Normal[Player[num].y / 32][Player[num].x / 32]){
				case 0:
					return 0;
				case 1:
					return 1;
				case 2:
					return 2;
				case 3:
					return 3;
			}
			break;
		case 3:
			switch(Map.Normal[(Player[num].y / 32) -1][(Player[num].x / 32) + 1]){
				case 0:
					return 0;
				case 1:
					return 1;
				case 2:
					return 2;
				case 3:
					return 3;
			}
			break;
	}
	return 0;
}

void PlayerInput()
{
	int i; //カウンター変数
	//--------------------1P入力-------------------
	if(Player[0].x % 32 == 0 && Player[0].y % 32 == 0){
		Player[0].walkflg = 1;//移動
		if(GetJoypadInputState(DX_INPUT_PAD1) & PAD_INPUT_LEFT){
			Player[0].muki = 1;//左
		}else if(GetJoypadInputState(DX_INPUT_PAD1) & PAD_INPUT_UP){
			Player[0].muki = 0;//上
		}else if(GetJoypadInputState(DX_INPUT_PAD1) & PAD_INPUT_RIGHT){
			Player[0].muki = 3;//右
		}else if(GetJoypadInputState(DX_INPUT_PAD1) & PAD_INPUT_DOWN){
			Player[0].muki = 2;//下
		}else{
			Player[0].walkflg = 0;
		}
		if((GetJoypadInputState(DX_INPUT_PAD1) & PAD_INPUT_Z)){ //方向転換
			Player[0].walkflg = 0;
			if(GetJoypadInputState(DX_INPUT_PAD1) & PAD_INPUT_LEFT){
				Player[0].muki = 1;//左
			}else if(GetJoypadInputState(DX_INPUT_PAD1) & PAD_INPUT_UP){
				Player[0].muki = 0;//上
			}else if(GetJoypadInputState(DX_INPUT_PAD1) & PAD_INPUT_RIGHT){
				Player[0].muki = 3;//右
			}else if(GetJoypadInputState(DX_INPUT_PAD1) & PAD_INPUT_DOWN){
				Player[0].muki = 2;//下
			}
		}
	}
	
	//---------------------------------------------


	//------------------2P入力---------------------
	if(Player[1].x % 32 == 0 && Player[1].y % 32 == 0){
		Player[1].walkflg = 1;
		if(GetJoypadInputState(DX_INPUT_PAD2) & PAD_INPUT_LEFT){
			Player[1].muki = 1;
		}else if(GetJoypadInputState(DX_INPUT_PAD2) & PAD_INPUT_UP){
			Player[1].muki = 0;
		}else if(GetJoypadInputState(DX_INPUT_PAD2) & PAD_INPUT_RIGHT){
			Player[1].muki = 3;
		}else if(GetJoypadInputState(DX_INPUT_PAD2) & PAD_INPUT_DOWN){
			Player[1].muki = 2;
		}else{
			Player[1].walkflg = 0;
		}
		if(GetJoypadInputState(DX_INPUT_PAD2) & PAD_INPUT_Z){
			if(GetJoypadInputState(DX_INPUT_PAD2) & PAD_INPUT_LEFT){
				Player[1].muki = 1;//左
				Player[1].walkflg = 0;
			}else if(GetJoypadInputState(DX_INPUT_PAD2) & PAD_INPUT_UP){
				Player[1].muki = 0;//上
				Player[1].walkflg = 0;
			}else if(GetJoypadInputState(DX_INPUT_PAD2) & PAD_INPUT_RIGHT){
				Player[1].muki = 3;//右
				Player[1].walkflg = 0;
			}else if(GetJoypadInputState(DX_INPUT_PAD2) & PAD_INPUT_DOWN){
				Player[1].muki = 2;//下	
				Player[1].walkflg = 0;
			}
		}
	}
	//--------------------------------------------
	for(i=0;i<2;i++){
		if(Player.walkflg == 1){
			switch(HitBlock(Player.x,Player.y,Player.muki,i)){
				case 1:
					Player.walkflg = 0;
					break;
			}
		}
	}

	for(i=0;i<2;i++){
		if(Player.walkflg == 1){
			switch(Player.muki){
				case 0://上
					Player.y -= Player.Speed;
					break;
				case 1://左
					Player.x -= Player[i].Speed;
					break;
				case 2://下
					Player[i].y += Player[i].Speed;
					break;
				case 3://右
					Player[i].x += Player[i].Speed;
					break;

			}
		}
	}
	return;
}

void DrawPlayer()
{
	int i;
	for(i=0;i<2;i++)
		DrawGraph(Player[i].x,Player[i].y,Player[i].Graph[( Player[i].x % 32 + Player[i].y % 32 )/8 + Player[i].muki*4],TRUE);

}

non

Re:キャラクターの移動について

#12

投稿記事 by non » 16年前

>動いている途中で別のキーを押すと動かなくなってしまうのですが

ということは、途中でキーを押さなければ、壁まで進んで壁でとまるのでしょうか?
私、DXライブラリを使ったことがないので、素人考えですが・・・
私の考えが間違っていればご指摘ください。
for(i=0;i<2;i++){
		if(Player.walkflg == 1){
			switch(HitBlock(Player.x,Player.y,Player.muki,i)){
				case 1:
					Player.walkflg = 0;
					break;
			}
		}
	}


この部分は、壁にぶつかったら止まるためのプログラムだと思います。
しかし
if(Player[0].x % 32 == 0 && Player[0].y % 32 == 0){
の部分の外ですから、1ドット動くたびにチェックしてます。
32の倍数以外でチェックすると、その次のマップ位置をチェックすることになるので、私の考えでは
壁にぶつかる31ドット前で止まると思うのですが、違いますか?
そうすると、最初に述べたように、途中で何もキーを押さないときは、壁の1ドット前で止まるはずは
ないということになりますので、その辺いかがですか?

次にint HitBlock(int x,int y,int muki,int num)関数ですが、numを引数で渡しているのだから
xやyを渡す必要がありません。また、
また、例えば上に動くときのチェックだけど、
switch(Map.Normal[(Player[num].y / 32) - 2][Player[num].x / 32]){
なぜ、-2なのか分かりません。自分の位置と上下方向のマップと一つずれているとわかりにくいです。

さらに、管理人さんが指摘されているように、GetJoypadInputState(DX_INPUT_PAD1)はループの中で
1回だけにしないと、無駄と言うよりも、タイミングによりループの途中で値が変わることにより思わぬ
バグを生じることになります。

non

Re:キャラクターの移動について

#13

投稿記事 by non » 16年前

>switch(Map.Normal[(Player[num].y / 32) - 2][Player[num].x / 32]){
>なぜ、-2なのか分かりません。

書いてありましたね。でも、そのような設計にしなければならないことに問題があったのでは?

JT

Re:キャラクターの移動について

#14

投稿記事 by JT » 16年前

私もnonさんと同意見です

non

Re:キャラクターの移動について

#15

投稿記事 by non » 16年前

>32の倍数以外でチェックすると、その次のマップ位置をチェックすることになるので、私の考えでは
>壁にぶつかる31ドット前で止まると思うのですが、違いますか?
>そうすると、最初に述べたように、途中で何もキーを押さないときは、壁の1ドット前で止まるはずは
>ないということになりますので、その辺いかがですか?

折角、JTさんから賛同を得ましたが、この説明には間違いがあったかもしれません。
+方向に座標が増えた場合は、x/32が切り捨てになるので問題ないですね。
問題があるのは-方向でしょうか?例えばxが64だったときx/32=2ですから1のマップが
進めるかチェックしますね。1ドットマイナスすると、63になるのでx/32=1となり、0の
マップのチェックになります。

フォンクス

Re:キャラクターの移動について

#16

投稿記事 by フォンクス » 16年前

入力の方を直してみました。
GetJoypadInputStateは1Pと2P用で2回呼んでるだけになりました。
2Pは同じなんで省略しました。
int i,key; //カウンター変数
	//--------------------1P入力-------------------
	if(Player[0].x % 32 == 0 && Player[0].y % 32 == 0){
		Player[0].walkflg = 1;//移動
		key = GetJoypadInputState(DX_INPUT_PAD1);
		if(key & PAD_INPUT_LEFT){
			Player[0].muki = 1;//左
		}else if(key & PAD_INPUT_UP){
			Player[0].muki = 0;//上
		}else if(key & PAD_INPUT_RIGHT){
			Player[0].muki = 3;//右
		}else if(key & PAD_INPUT_DOWN){
			Player[0].muki = 2;//下
		}else{
			Player[0].walkflg = 0;
		}
		if((key & PAD_INPUT_Z)){ //方向転換
			Player[0].walkflg = 0;
			if(key & PAD_INPUT_LEFT){
				Player[0].muki = 1;//左
			}else if(key & PAD_INPUT_UP){
				Player[0].muki = 0;//上
			}else if(key & PAD_INPUT_RIGHT){
				Player[0].muki = 3;//右
			}else if(key & PAD_INPUT_DOWN){
				Player[0].muki = 2;//下
			}
		}
	}
壁にぶつかった時に当たり判定なんですが、画像の様な
表示をさせたかったのでずらしたんですが・・・。

non

Re:キャラクターの移動について

#17

投稿記事 by non » 16年前

GetJoypadInputStateの方は、この方がいいですね。
上下のマップのずれは、本人がわかりやすいのなら、それで、いいですよ。
それより、通れないところの判定のタイミングの方はよくなりましたか?

フォンクス

Re:キャラクターの移動について

#18

投稿記事 by フォンクス » 16年前

移動の判定なんですが、壁じゃないところで動かなくなってしまう時があります。
座標を見ると、32で割り切れないところで止まっているのでそのせいだと思うんですが
壁のあたり判定を見直してます

non

Re:キャラクターの移動について

#19

投稿記事 by non » 16年前

移動判定をこの中に入れてみたらどうでしょうか?
if(Player[0].x % 32 == 0 && Player[0].y % 32 == 0){

フォンクス

Re:キャラクターの移動について

#20

投稿記事 by フォンクス » 16年前

if(Player[0].x % 32 == 0 && Player[0].y % 32 == 0){
		Player[0].walkflg = 1;//移動
		key[0] = GetJoypadInputState(DX_INPUT_PAD1);
		if(key[0] & PAD_INPUT_LEFT){
			Player[0].muki = 1;//左
		}else if(key[0] & PAD_INPUT_UP){
			Player[0].muki = 0;//上
		}else if(key[0] & PAD_INPUT_RIGHT){
			Player[0].muki = 3;//右
		}else if(key[0] & PAD_INPUT_DOWN){
			Player[0].muki = 2;//下
		}else{
			Player[0].walkflg = 0;
		}
		if((key[0] & PAD_INPUT_Z)){ //方向転換
			Player[0].walkflg = 0;
			if(key[0] & PAD_INPUT_LEFT){
				Player[0].muki = 1;//左
			}else if(key[0] & PAD_INPUT_UP){
				Player[0].muki = 0;//上
			}else if(key[0] & PAD_INPUT_RIGHT){
				Player[0].muki = 3;//右
			}else if(key[0] & PAD_INPUT_DOWN){
				Player[0].muki = 2;//下
			}
		}
		if(Player[0].walkflg == 1){
			switch(HitBlock(0)){//壁などの当たり判定
				case 1://壁があった場合
					Player[0].walkflg = 0;
					break;
			}
		}
	}
この様にした所、変な場所で止まらなくなりました。
回答して下さった皆様、ありがとうございました。

閉鎖

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